blob: a558a61592f5b3e43c474ede6653e56c5347d9f4 [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 Grosbachad353c62012-03-30 19:59:02 +0000785 // Only use this when not representable as a plain so_imm.
786 return ARM_AM::getSOImmVal(Value) == -1 &&
787 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000788 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000789 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000790 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
792 if (!CE) return false;
793 int64_t Value = CE->getValue();
794 return ARM_AM::getT2SOImmVal(Value) != -1;
795 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000796 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000797 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000798 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
799 if (!CE) return false;
800 int64_t Value = CE->getValue();
801 return ARM_AM::getT2SOImmVal(~Value) != -1;
802 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000803 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000804 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000805 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
806 if (!CE) return false;
807 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000808 // Only use this when not representable as a plain so_imm.
809 return ARM_AM::getT2SOImmVal(Value) == -1 &&
810 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000811 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000812 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000813 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000814 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
815 if (!CE) return false;
816 int64_t Value = CE->getValue();
817 return Value == 1 || Value == 0;
818 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000819 bool isReg() const { return Kind == k_Register; }
820 bool isRegList() const { return Kind == k_RegisterList; }
821 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
822 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
823 bool isToken() const { return Kind == k_Token; }
824 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
825 bool isMemory() const { return Kind == k_Memory; }
826 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
827 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
828 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
829 bool isRotImm() const { return Kind == k_RotateImmediate; }
830 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
831 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000832 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000833 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000834 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000835 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000836 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000837 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000838 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000839 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
840 (alignOK || Memory.Alignment == 0);
841 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000842 bool isMemPCRelImm12() const {
843 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
844 return false;
845 // Base register must be PC.
846 if (Memory.BaseRegNum != ARM::PC)
847 return false;
848 // Immediate offset in range [-4095, 4095].
849 if (!Memory.OffsetImm) return true;
850 int64_t Val = Memory.OffsetImm->getValue();
851 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
852 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000853 bool isAlignedMemory() const {
854 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000855 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000856 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000857 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000858 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000859 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000860 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000861 if (!Memory.OffsetImm) return true;
862 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000863 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000864 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000865 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000866 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000867 // Immediate offset in range [-4095, 4095].
868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
869 if (!CE) return false;
870 int64_t Val = CE->getValue();
871 return Val > -4096 && Val < 4096;
872 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000873 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000874 // If we have an immediate that's not a constant, treat it as a label
875 // reference needing a fixup. If it is a constant, it's something else
876 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000877 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000878 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000879 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000880 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000882 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000883 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000884 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000885 if (!Memory.OffsetImm) return true;
886 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000887 return Val > -256 && Val < 256;
888 }
889 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000890 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000892 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000893 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
894 // Immediate offset in range [-255, 255].
895 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
896 if (!CE) return false;
897 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000898 // Special case, #-0 is INT32_MIN.
899 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000900 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000901 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000902 // If we have an immediate that's not a constant, treat it as a label
903 // reference needing a fixup. If it is a constant, it's something else
904 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000905 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000906 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000907 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000908 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000910 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000911 if (!Memory.OffsetImm) return true;
912 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000913 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000914 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000915 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000916 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000917 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000918 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000919 return false;
920 return true;
921 }
922 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000923 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000924 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
925 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000926 return false;
927 return true;
928 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000929 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000930 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000931 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000932 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000933 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000934 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000935 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
936 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000937 return false;
938 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000940 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000941 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000942 return false;
943 return true;
944 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000945 bool isMemThumbRR() const {
946 // Thumb reg+reg addressing is simple. Just two registers, a base and
947 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000948 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000949 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000950 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 return isARMLowRegister(Memory.BaseRegNum) &&
952 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000953 }
954 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000955 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000956 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000957 return false;
958 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000959 if (!Memory.OffsetImm) return true;
960 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000961 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
962 }
Jim Grosbach38466302011-08-19 18:55:51 +0000963 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000964 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000966 return false;
967 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000968 if (!Memory.OffsetImm) return true;
969 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000970 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
971 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000972 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000973 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000974 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000975 return false;
976 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000977 if (!Memory.OffsetImm) return true;
978 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000979 return Val >= 0 && Val <= 31;
980 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000981 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000982 if (!isMemory() || Memory.OffsetRegNum != 0 ||
983 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000984 return false;
985 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000986 if (!Memory.OffsetImm) return true;
987 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000988 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000989 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000990 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000991 // If we have an immediate that's not a constant, treat it as a label
992 // reference needing a fixup. If it is a constant, it's something else
993 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000994 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000995 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001001 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001003 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001005 return false;
1006 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001007 if (!Memory.OffsetImm) return true;
1008 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001009 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1010 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001011 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001012 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001013 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001014 // Base reg of PC isn't allowed for these encodings.
1015 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001016 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001019 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001020 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001021 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001023 return false;
1024 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001025 if (!Memory.OffsetImm) return true;
1026 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001027 return Val >= 0 && Val < 256;
1028 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001029 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001030 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001031 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001032 // Base reg of PC isn't allowed for these encodings.
1033 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001034 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001035 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001037 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001038 }
1039 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001040 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001041 return false;
1042 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001043 if (!Memory.OffsetImm) return true;
1044 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001045 return (Val >= 0 && Val < 4096);
1046 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001047 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001048 // If we have an immediate that's not a constant, treat it as a label
1049 // reference needing a fixup. If it is a constant, it's something else
1050 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001051 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001052 return true;
1053
Jim Grosbach57dcb852011-10-11 17:29:55 +00001054 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 return false;
1056 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001057 if (!Memory.OffsetImm) return true;
1058 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001059 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001060 }
1061 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001062 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1064 if (!CE) return false;
1065 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001066 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001067 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001068 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001069 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001070 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1071 if (!CE) return false;
1072 int64_t Val = CE->getValue();
1073 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1074 (Val == INT32_MIN);
1075 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001076
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001077 bool isMSRMask() const { return Kind == k_MSRMask; }
1078 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001079
Jim Grosbach0e387b22011-10-17 22:26:03 +00001080 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001081 bool isSingleSpacedVectorList() const {
1082 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1083 }
1084 bool isDoubleSpacedVectorList() const {
1085 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1086 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001087 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001088 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001089 return VectorList.Count == 1;
1090 }
1091
Jim Grosbach28f08c92012-03-05 19:33:30 +00001092 bool isVecListDPair() const {
1093 if (!isSingleSpacedVectorList()) return false;
1094 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1095 .contains(VectorList.RegNum));
1096 }
1097
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001098 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001099 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001100 return VectorList.Count == 3;
1101 }
1102
Jim Grosbachb6310312011-10-21 20:35:01 +00001103 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001104 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001105 return VectorList.Count == 4;
1106 }
1107
Jim Grosbachc3384c92012-03-05 21:43:40 +00001108 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001109 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001110 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1111 .contains(VectorList.RegNum));
1112 }
1113
Jim Grosbachc387fc62012-01-23 23:20:46 +00001114 bool isVecListThreeQ() const {
1115 if (!isDoubleSpacedVectorList()) return false;
1116 return VectorList.Count == 3;
1117 }
1118
Jim Grosbach7945ead2012-01-24 00:43:12 +00001119 bool isVecListFourQ() const {
1120 if (!isDoubleSpacedVectorList()) return false;
1121 return VectorList.Count == 4;
1122 }
1123
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001124 bool isSingleSpacedVectorAllLanes() const {
1125 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1126 }
1127 bool isDoubleSpacedVectorAllLanes() const {
1128 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1129 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001130 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001131 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001132 return VectorList.Count == 1;
1133 }
1134
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001135 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001136 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001137 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1138 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001139 }
1140
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001141 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001142 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001143 return VectorList.Count == 2;
1144 }
1145
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001146 bool isVecListThreeDAllLanes() const {
1147 if (!isSingleSpacedVectorAllLanes()) return false;
1148 return VectorList.Count == 3;
1149 }
1150
1151 bool isVecListThreeQAllLanes() const {
1152 if (!isDoubleSpacedVectorAllLanes()) return false;
1153 return VectorList.Count == 3;
1154 }
1155
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001156 bool isVecListFourDAllLanes() const {
1157 if (!isSingleSpacedVectorAllLanes()) return false;
1158 return VectorList.Count == 4;
1159 }
1160
1161 bool isVecListFourQAllLanes() const {
1162 if (!isDoubleSpacedVectorAllLanes()) return false;
1163 return VectorList.Count == 4;
1164 }
1165
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001166 bool isSingleSpacedVectorIndexed() const {
1167 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1168 }
1169 bool isDoubleSpacedVectorIndexed() const {
1170 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1171 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001172 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001173 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001174 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1175 }
1176
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001177 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001178 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001179 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1180 }
1181
1182 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001183 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001184 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1185 }
1186
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001187 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001188 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001189 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1190 }
1191
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001192 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001193 if (!isSingleSpacedVectorIndexed()) return false;
1194 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1195 }
1196
1197 bool isVecListTwoQWordIndexed() const {
1198 if (!isDoubleSpacedVectorIndexed()) return false;
1199 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1200 }
1201
1202 bool isVecListTwoQHWordIndexed() const {
1203 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001204 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1205 }
1206
1207 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001209 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1210 }
1211
Jim Grosbach3a678af2012-01-23 21:53:26 +00001212 bool isVecListThreeDByteIndexed() const {
1213 if (!isSingleSpacedVectorIndexed()) return false;
1214 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1215 }
1216
1217 bool isVecListThreeDHWordIndexed() const {
1218 if (!isSingleSpacedVectorIndexed()) return false;
1219 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1220 }
1221
1222 bool isVecListThreeQWordIndexed() const {
1223 if (!isDoubleSpacedVectorIndexed()) return false;
1224 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1225 }
1226
1227 bool isVecListThreeQHWordIndexed() const {
1228 if (!isDoubleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1230 }
1231
1232 bool isVecListThreeDWordIndexed() const {
1233 if (!isSingleSpacedVectorIndexed()) return false;
1234 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1235 }
1236
Jim Grosbache983a132012-01-24 18:37:25 +00001237 bool isVecListFourDByteIndexed() const {
1238 if (!isSingleSpacedVectorIndexed()) return false;
1239 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1240 }
1241
1242 bool isVecListFourDHWordIndexed() const {
1243 if (!isSingleSpacedVectorIndexed()) return false;
1244 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1245 }
1246
1247 bool isVecListFourQWordIndexed() const {
1248 if (!isDoubleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1250 }
1251
1252 bool isVecListFourQHWordIndexed() const {
1253 if (!isDoubleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1255 }
1256
1257 bool isVecListFourDWordIndexed() const {
1258 if (!isSingleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1260 }
1261
Jim Grosbach460a9052011-10-07 23:56:00 +00001262 bool isVectorIndex8() const {
1263 if (Kind != k_VectorIndex) return false;
1264 return VectorIndex.Val < 8;
1265 }
1266 bool isVectorIndex16() const {
1267 if (Kind != k_VectorIndex) return false;
1268 return VectorIndex.Val < 4;
1269 }
1270 bool isVectorIndex32() const {
1271 if (Kind != k_VectorIndex) return false;
1272 return VectorIndex.Val < 2;
1273 }
1274
Jim Grosbach0e387b22011-10-17 22:26:03 +00001275 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001276 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001277 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1278 // Must be a constant.
1279 if (!CE) return false;
1280 int64_t Value = CE->getValue();
1281 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1282 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001283 return Value >= 0 && Value < 256;
1284 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001285
Jim Grosbachea461102011-10-17 23:09:09 +00001286 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001287 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001288 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1289 // Must be a constant.
1290 if (!CE) return false;
1291 int64_t Value = CE->getValue();
1292 // i16 value in the range [0,255] or [0x0100, 0xff00]
1293 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1294 }
1295
Jim Grosbach6248a542011-10-18 00:22:00 +00001296 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001297 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001298 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1299 // Must be a constant.
1300 if (!CE) return false;
1301 int64_t Value = CE->getValue();
1302 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1303 return (Value >= 0 && Value < 256) ||
1304 (Value >= 0x0100 && Value <= 0xff00) ||
1305 (Value >= 0x010000 && Value <= 0xff0000) ||
1306 (Value >= 0x01000000 && Value <= 0xff000000);
1307 }
1308
1309 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001310 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001311 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1312 // Must be a constant.
1313 if (!CE) return false;
1314 int64_t Value = CE->getValue();
1315 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1316 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1317 return (Value >= 0 && Value < 256) ||
1318 (Value >= 0x0100 && Value <= 0xff00) ||
1319 (Value >= 0x010000 && Value <= 0xff0000) ||
1320 (Value >= 0x01000000 && Value <= 0xff000000) ||
1321 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1322 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1323 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001324 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001325 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001326 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1327 // Must be a constant.
1328 if (!CE) return false;
1329 int64_t Value = ~CE->getValue();
1330 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1331 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1332 return (Value >= 0 && Value < 256) ||
1333 (Value >= 0x0100 && Value <= 0xff00) ||
1334 (Value >= 0x010000 && Value <= 0xff0000) ||
1335 (Value >= 0x01000000 && Value <= 0xff000000) ||
1336 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1337 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1338 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001339
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001340 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001341 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1343 // Must be a constant.
1344 if (!CE) return false;
1345 uint64_t Value = CE->getValue();
1346 // i64 value with each byte being either 0 or 0xff.
1347 for (unsigned i = 0; i < 8; ++i)
1348 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1349 return true;
1350 }
1351
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001352 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001353 // Add as immediates when possible. Null MCExpr = 0.
1354 if (Expr == 0)
1355 Inst.addOperand(MCOperand::CreateImm(0));
1356 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001357 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1358 else
1359 Inst.addOperand(MCOperand::CreateExpr(Expr));
1360 }
1361
Daniel Dunbar8462b302010-08-11 06:36:53 +00001362 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001363 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001364 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001365 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1366 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001367 }
1368
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001369 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
1371 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1372 }
1373
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001374 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1377 }
1378
1379 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1380 assert(N == 1 && "Invalid number of operands!");
1381 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1382 }
1383
Jim Grosbach89df9962011-08-26 21:43:41 +00001384 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1387 }
1388
1389 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1392 }
1393
Jim Grosbachd67641b2010-12-06 18:21:12 +00001394 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
1396 Inst.addOperand(MCOperand::CreateReg(getReg()));
1397 }
1398
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001399 void addRegOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateReg(getReg()));
1402 }
1403
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001404 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001405 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001406 assert(isRegShiftedReg() &&
1407 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001408 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1409 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001410 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001411 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001412 }
1413
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001414 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001415 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001416 assert(isRegShiftedImm() &&
1417 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001418 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001419 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001420 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001421 }
1422
Jim Grosbach580f4a92011-07-25 22:20:28 +00001423 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001424 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001425 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1426 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001427 }
1428
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001429 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001430 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001431 const SmallVectorImpl<unsigned> &RegList = getRegList();
1432 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001433 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1434 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001435 }
1436
Bill Wendling0f630752010-11-17 04:32:08 +00001437 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1438 addRegListOperands(Inst, N);
1439 }
1440
1441 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1442 addRegListOperands(Inst, N);
1443 }
1444
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001445 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1448 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1449 }
1450
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001451 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 // Munge the lsb/width into a bitfield mask.
1454 unsigned lsb = Bitfield.LSB;
1455 unsigned width = Bitfield.Width;
1456 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1457 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1458 (32 - (lsb + width)));
1459 Inst.addOperand(MCOperand::CreateImm(Mask));
1460 }
1461
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001462 void addImmOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
1464 addExpr(Inst, getImm());
1465 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001466
Jim Grosbach4050bc42011-12-22 22:19:05 +00001467 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1470 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1471 }
1472
1473 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
1475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1476 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1477 }
1478
Jim Grosbach9d390362011-10-03 23:38:36 +00001479 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001481 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1482 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1483 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001484 }
1485
Jim Grosbacha77295d2011-09-08 22:07:06 +00001486 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 // FIXME: We really want to scale the value here, but the LDRD/STRD
1489 // instruction don't encode operands that way yet.
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1492 }
1493
Jim Grosbach72f39f82011-08-24 21:22:15 +00001494 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 // The immediate is scaled by four in the encoding and is stored
1497 // in the MCInst as such. Lop off the low two bits here.
1498 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1499 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1500 }
1501
1502 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1503 assert(N == 1 && "Invalid number of operands!");
1504 // The immediate is scaled by four in the encoding and is stored
1505 // in the MCInst as such. Lop off the low two bits here.
1506 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1507 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1508 }
1509
Jim Grosbachf4943352011-07-25 23:09:14 +00001510 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 // The constant encodes as the immediate-1, and we store in the instruction
1513 // the bits as encoded, so subtract off one here.
1514 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1515 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1516 }
1517
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001518 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1519 assert(N == 1 && "Invalid number of operands!");
1520 // The constant encodes as the immediate-1, and we store in the instruction
1521 // the bits as encoded, so subtract off one here.
1522 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1523 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1524 }
1525
Jim Grosbach70939ee2011-08-17 21:51:27 +00001526 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1527 assert(N == 1 && "Invalid number of operands!");
1528 // The constant encodes as the immediate, except for 32, which encodes as
1529 // zero.
1530 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1531 unsigned Imm = CE->getValue();
1532 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1533 }
1534
Jim Grosbachf6c05252011-07-21 17:23:04 +00001535 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1538 // the instruction as well.
1539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1540 int Val = CE->getValue();
1541 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1542 }
1543
Jim Grosbach89a63372011-10-28 22:36:30 +00001544 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1545 assert(N == 1 && "Invalid number of operands!");
1546 // The operand is actually a t2_so_imm, but we have its bitwise
1547 // negation in the assembly source, so twiddle it here.
1548 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1549 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1550 }
1551
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001552 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 // The operand is actually a t2_so_imm, but we have its
1555 // negation in the assembly source, so twiddle it here.
1556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1557 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1558 }
1559
Jim Grosbache70ec842011-10-28 22:50:54 +00001560 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 // The operand is actually a so_imm, but we have its bitwise
1563 // negation in the assembly source, so twiddle it here.
1564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1565 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1566 }
1567
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001568 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 // The operand is actually a so_imm, but we have its
1571 // negation in the assembly source, so twiddle it here.
1572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1573 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1574 }
1575
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001576 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1579 }
1580
Jim Grosbach7ce05792011-08-03 23:50:40 +00001581 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1582 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001583 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001584 }
1585
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001586 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 int32_t Imm = Memory.OffsetImm->getValue();
1589 // FIXME: Handle #-0
1590 if (Imm == INT32_MIN) Imm = 0;
1591 Inst.addOperand(MCOperand::CreateImm(Imm));
1592 }
1593
Jim Grosbach57dcb852011-10-11 17:29:55 +00001594 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 2 && "Invalid number of operands!");
1596 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1597 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1598 }
1599
Jim Grosbach7ce05792011-08-03 23:50:40 +00001600 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1601 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001602 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1603 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001604 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1605 // Special case for #-0
1606 if (Val == INT32_MIN) Val = 0;
1607 if (Val < 0) Val = -Val;
1608 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1609 } else {
1610 // For register offset, we encode the shift type and negation flag
1611 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001612 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1613 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001614 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001615 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1616 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001617 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001618 }
1619
Jim Grosbach039c2e12011-08-04 23:01:30 +00001620 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1621 assert(N == 2 && "Invalid number of operands!");
1622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1623 assert(CE && "non-constant AM2OffsetImm operand!");
1624 int32_t Val = CE->getValue();
1625 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1626 // Special case for #-0
1627 if (Val == INT32_MIN) Val = 0;
1628 if (Val < 0) Val = -Val;
1629 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1630 Inst.addOperand(MCOperand::CreateReg(0));
1631 Inst.addOperand(MCOperand::CreateImm(Val));
1632 }
1633
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001634 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1635 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001636 // If we have an immediate that's not a constant, treat it as a label
1637 // reference needing a fixup. If it is a constant, it's something else
1638 // and we reject it.
1639 if (isImm()) {
1640 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1641 Inst.addOperand(MCOperand::CreateReg(0));
1642 Inst.addOperand(MCOperand::CreateImm(0));
1643 return;
1644 }
1645
Jim Grosbache53c87b2011-10-11 15:59:20 +00001646 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1647 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001648 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1649 // Special case for #-0
1650 if (Val == INT32_MIN) Val = 0;
1651 if (Val < 0) Val = -Val;
1652 Val = ARM_AM::getAM3Opc(AddSub, Val);
1653 } else {
1654 // For register offset, we encode the shift type and negation flag
1655 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001656 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001657 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001658 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1659 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001660 Inst.addOperand(MCOperand::CreateImm(Val));
1661 }
1662
1663 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001665 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001666 int32_t Val =
1667 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1668 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1669 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001670 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001671 }
1672
1673 // Constant offset.
1674 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1675 int32_t Val = CE->getValue();
1676 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1677 // Special case for #-0
1678 if (Val == INT32_MIN) Val = 0;
1679 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001680 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001681 Inst.addOperand(MCOperand::CreateReg(0));
1682 Inst.addOperand(MCOperand::CreateImm(Val));
1683 }
1684
Jim Grosbach7ce05792011-08-03 23:50:40 +00001685 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1686 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001687 // If we have an immediate that's not a constant, treat it as a label
1688 // reference needing a fixup. If it is a constant, it's something else
1689 // and we reject it.
1690 if (isImm()) {
1691 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1692 Inst.addOperand(MCOperand::CreateImm(0));
1693 return;
1694 }
1695
Jim Grosbach7ce05792011-08-03 23:50:40 +00001696 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001697 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001698 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1699 // Special case for #-0
1700 if (Val == INT32_MIN) Val = 0;
1701 if (Val < 0) Val = -Val;
1702 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001703 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001704 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001705 }
1706
Jim Grosbacha77295d2011-09-08 22:07:06 +00001707 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1708 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001709 // If we have an immediate that's not a constant, treat it as a label
1710 // reference needing a fixup. If it is a constant, it's something else
1711 // and we reject it.
1712 if (isImm()) {
1713 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1714 Inst.addOperand(MCOperand::CreateImm(0));
1715 return;
1716 }
1717
Jim Grosbache53c87b2011-10-11 15:59:20 +00001718 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1719 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001720 Inst.addOperand(MCOperand::CreateImm(Val));
1721 }
1722
Jim Grosbachb6aed502011-09-09 18:37:27 +00001723 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1724 assert(N == 2 && "Invalid number of operands!");
1725 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001726 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1727 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001728 Inst.addOperand(MCOperand::CreateImm(Val));
1729 }
1730
Jim Grosbach7ce05792011-08-03 23:50:40 +00001731 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1732 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001733 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1734 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001735 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001736 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001737
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001738 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1739 addMemImm8OffsetOperands(Inst, N);
1740 }
1741
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001742 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001743 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001744 }
1745
1746 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1747 assert(N == 2 && "Invalid number of operands!");
1748 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001749 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001750 addExpr(Inst, getImm());
1751 Inst.addOperand(MCOperand::CreateImm(0));
1752 return;
1753 }
1754
1755 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001756 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1757 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001758 Inst.addOperand(MCOperand::CreateImm(Val));
1759 }
1760
Jim Grosbach7ce05792011-08-03 23:50:40 +00001761 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001763 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001764 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001765 addExpr(Inst, getImm());
1766 Inst.addOperand(MCOperand::CreateImm(0));
1767 return;
1768 }
1769
1770 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001771 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001773 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001774 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001775
Jim Grosbach7f739be2011-09-19 22:21:13 +00001776 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001778 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1779 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001780 }
1781
1782 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1783 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001784 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1785 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001786 }
1787
Jim Grosbach7ce05792011-08-03 23:50:40 +00001788 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1789 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001790 unsigned Val =
1791 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1792 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001793 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1794 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001795 Inst.addOperand(MCOperand::CreateImm(Val));
1796 }
1797
Jim Grosbachab899c12011-09-07 23:10:15 +00001798 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1799 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001800 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1801 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1802 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001803 }
1804
Jim Grosbach7ce05792011-08-03 23:50:40 +00001805 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1806 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001807 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1808 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001809 }
1810
Jim Grosbach60f91a32011-08-19 17:55:24 +00001811 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1812 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001813 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1814 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001815 Inst.addOperand(MCOperand::CreateImm(Val));
1816 }
1817
Jim Grosbach38466302011-08-19 18:55:51 +00001818 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1819 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001820 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1821 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001822 Inst.addOperand(MCOperand::CreateImm(Val));
1823 }
1824
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001825 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1826 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001827 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1828 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001829 Inst.addOperand(MCOperand::CreateImm(Val));
1830 }
1831
Jim Grosbachecd85892011-08-19 18:13:48 +00001832 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1833 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001834 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1835 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001836 Inst.addOperand(MCOperand::CreateImm(Val));
1837 }
1838
Jim Grosbach7ce05792011-08-03 23:50:40 +00001839 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1840 assert(N == 1 && "Invalid number of operands!");
1841 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1842 assert(CE && "non-constant post-idx-imm8 operand!");
1843 int Imm = CE->getValue();
1844 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001845 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001846 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1847 Inst.addOperand(MCOperand::CreateImm(Imm));
1848 }
1849
Jim Grosbach2bd01182011-10-11 21:55:36 +00001850 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1851 assert(N == 1 && "Invalid number of operands!");
1852 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1853 assert(CE && "non-constant post-idx-imm8s4 operand!");
1854 int Imm = CE->getValue();
1855 bool isAdd = Imm >= 0;
1856 if (Imm == INT32_MIN) Imm = 0;
1857 // Immediate is scaled by 4.
1858 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1859 Inst.addOperand(MCOperand::CreateImm(Imm));
1860 }
1861
Jim Grosbach7ce05792011-08-03 23:50:40 +00001862 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1863 assert(N == 2 && "Invalid number of operands!");
1864 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001865 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1866 }
1867
1868 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1869 assert(N == 2 && "Invalid number of operands!");
1870 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1871 // The sign, shift type, and shift amount are encoded in a single operand
1872 // using the AM2 encoding helpers.
1873 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1874 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1875 PostIdxReg.ShiftTy);
1876 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001877 }
1878
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001879 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1880 assert(N == 1 && "Invalid number of operands!");
1881 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1882 }
1883
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001884 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1885 assert(N == 1 && "Invalid number of operands!");
1886 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1887 }
1888
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001889 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001890 assert(N == 1 && "Invalid number of operands!");
1891 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1892 }
1893
Jim Grosbach7636bf62011-12-02 00:35:16 +00001894 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1895 assert(N == 2 && "Invalid number of operands!");
1896 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1897 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1898 }
1899
Jim Grosbach460a9052011-10-07 23:56:00 +00001900 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1901 assert(N == 1 && "Invalid number of operands!");
1902 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1903 }
1904
1905 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1906 assert(N == 1 && "Invalid number of operands!");
1907 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1908 }
1909
1910 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1911 assert(N == 1 && "Invalid number of operands!");
1912 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1913 }
1914
Jim Grosbach0e387b22011-10-17 22:26:03 +00001915 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1916 assert(N == 1 && "Invalid number of operands!");
1917 // The immediate encodes the type of constant as well as the value.
1918 // Mask in that this is an i8 splat.
1919 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1920 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1921 }
1922
Jim Grosbachea461102011-10-17 23:09:09 +00001923 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1924 assert(N == 1 && "Invalid number of operands!");
1925 // The immediate encodes the type of constant as well as the value.
1926 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1927 unsigned Value = CE->getValue();
1928 if (Value >= 256)
1929 Value = (Value >> 8) | 0xa00;
1930 else
1931 Value |= 0x800;
1932 Inst.addOperand(MCOperand::CreateImm(Value));
1933 }
1934
Jim Grosbach6248a542011-10-18 00:22:00 +00001935 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1936 assert(N == 1 && "Invalid number of operands!");
1937 // The immediate encodes the type of constant as well as the value.
1938 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1939 unsigned Value = CE->getValue();
1940 if (Value >= 256 && Value <= 0xff00)
1941 Value = (Value >> 8) | 0x200;
1942 else if (Value > 0xffff && Value <= 0xff0000)
1943 Value = (Value >> 16) | 0x400;
1944 else if (Value > 0xffffff)
1945 Value = (Value >> 24) | 0x600;
1946 Inst.addOperand(MCOperand::CreateImm(Value));
1947 }
1948
1949 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1950 assert(N == 1 && "Invalid number of operands!");
1951 // The immediate encodes the type of constant as well as the value.
1952 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1953 unsigned Value = CE->getValue();
1954 if (Value >= 256 && Value <= 0xffff)
1955 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1956 else if (Value > 0xffff && Value <= 0xffffff)
1957 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1958 else if (Value > 0xffffff)
1959 Value = (Value >> 24) | 0x600;
1960 Inst.addOperand(MCOperand::CreateImm(Value));
1961 }
1962
Jim Grosbach9b087852011-12-19 23:51:07 +00001963 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1964 assert(N == 1 && "Invalid number of operands!");
1965 // The immediate encodes the type of constant as well as the value.
1966 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1967 unsigned Value = ~CE->getValue();
1968 if (Value >= 256 && Value <= 0xffff)
1969 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1970 else if (Value > 0xffff && Value <= 0xffffff)
1971 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1972 else if (Value > 0xffffff)
1973 Value = (Value >> 24) | 0x600;
1974 Inst.addOperand(MCOperand::CreateImm(Value));
1975 }
1976
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001977 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1978 assert(N == 1 && "Invalid number of operands!");
1979 // The immediate encodes the type of constant as well as the value.
1980 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1981 uint64_t Value = CE->getValue();
1982 unsigned Imm = 0;
1983 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1984 Imm |= (Value & 1) << i;
1985 }
1986 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1987 }
1988
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001989 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001990
Jim Grosbach89df9962011-08-26 21:43:41 +00001991 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001992 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001993 Op->ITMask.Mask = Mask;
1994 Op->StartLoc = S;
1995 Op->EndLoc = S;
1996 return Op;
1997 }
1998
Chris Lattner3a697562010-10-28 17:20:03 +00001999 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002000 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002001 Op->CC.Val = CC;
2002 Op->StartLoc = S;
2003 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002004 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002005 }
2006
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002007 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002008 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002009 Op->Cop.Val = CopVal;
2010 Op->StartLoc = S;
2011 Op->EndLoc = S;
2012 return Op;
2013 }
2014
2015 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002016 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002017 Op->Cop.Val = CopVal;
2018 Op->StartLoc = S;
2019 Op->EndLoc = S;
2020 return Op;
2021 }
2022
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002023 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2024 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2025 Op->Cop.Val = Val;
2026 Op->StartLoc = S;
2027 Op->EndLoc = E;
2028 return Op;
2029 }
2030
Jim Grosbachd67641b2010-12-06 18:21:12 +00002031 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002032 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002033 Op->Reg.RegNum = RegNum;
2034 Op->StartLoc = S;
2035 Op->EndLoc = S;
2036 return Op;
2037 }
2038
Chris Lattner3a697562010-10-28 17:20:03 +00002039 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002040 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002041 Op->Tok.Data = Str.data();
2042 Op->Tok.Length = Str.size();
2043 Op->StartLoc = S;
2044 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002045 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002046 }
2047
Bill Wendling50d0f582010-11-18 23:43:05 +00002048 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002049 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002050 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002051 Op->StartLoc = S;
2052 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002053 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002054 }
2055
Jim Grosbache8606dc2011-07-13 17:50:29 +00002056 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2057 unsigned SrcReg,
2058 unsigned ShiftReg,
2059 unsigned ShiftImm,
2060 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002061 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002062 Op->RegShiftedReg.ShiftTy = ShTy;
2063 Op->RegShiftedReg.SrcReg = SrcReg;
2064 Op->RegShiftedReg.ShiftReg = ShiftReg;
2065 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002066 Op->StartLoc = S;
2067 Op->EndLoc = E;
2068 return Op;
2069 }
2070
Owen Anderson92a20222011-07-21 18:54:16 +00002071 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2072 unsigned SrcReg,
2073 unsigned ShiftImm,
2074 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002075 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002076 Op->RegShiftedImm.ShiftTy = ShTy;
2077 Op->RegShiftedImm.SrcReg = SrcReg;
2078 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002079 Op->StartLoc = S;
2080 Op->EndLoc = E;
2081 return Op;
2082 }
2083
Jim Grosbach580f4a92011-07-25 22:20:28 +00002084 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002085 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002086 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002087 Op->ShifterImm.isASR = isASR;
2088 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002089 Op->StartLoc = S;
2090 Op->EndLoc = E;
2091 return Op;
2092 }
2093
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002094 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002095 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002096 Op->RotImm.Imm = Imm;
2097 Op->StartLoc = S;
2098 Op->EndLoc = E;
2099 return Op;
2100 }
2101
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002102 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2103 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002104 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002105 Op->Bitfield.LSB = LSB;
2106 Op->Bitfield.Width = Width;
2107 Op->StartLoc = S;
2108 Op->EndLoc = E;
2109 return Op;
2110 }
2111
Bill Wendling7729e062010-11-09 22:44:22 +00002112 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002113 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002114 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002115 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002116
Jim Grosbachd300b942011-09-13 22:56:44 +00002117 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002118 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002119 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002120 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002121 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002122
2123 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002124 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002125 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002126 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002127 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002128 Op->StartLoc = StartLoc;
2129 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002130 return Op;
2131 }
2132
Jim Grosbach862019c2011-10-18 23:02:30 +00002133 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002134 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002135 ARMOperand *Op = new ARMOperand(k_VectorList);
2136 Op->VectorList.RegNum = RegNum;
2137 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002138 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002139 Op->StartLoc = S;
2140 Op->EndLoc = E;
2141 return Op;
2142 }
2143
Jim Grosbach98b05a52011-11-30 01:09:44 +00002144 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002145 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002146 SMLoc S, SMLoc E) {
2147 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2148 Op->VectorList.RegNum = RegNum;
2149 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002150 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002151 Op->StartLoc = S;
2152 Op->EndLoc = E;
2153 return Op;
2154 }
2155
Jim Grosbach7636bf62011-12-02 00:35:16 +00002156 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002157 unsigned Index,
2158 bool isDoubleSpaced,
2159 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002160 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2161 Op->VectorList.RegNum = RegNum;
2162 Op->VectorList.Count = Count;
2163 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002164 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002165 Op->StartLoc = S;
2166 Op->EndLoc = E;
2167 return Op;
2168 }
2169
Jim Grosbach460a9052011-10-07 23:56:00 +00002170 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2171 MCContext &Ctx) {
2172 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2173 Op->VectorIndex.Val = Idx;
2174 Op->StartLoc = S;
2175 Op->EndLoc = E;
2176 return Op;
2177 }
2178
Chris Lattner3a697562010-10-28 17:20:03 +00002179 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002180 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002181 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002182 Op->StartLoc = S;
2183 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002184 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002185 }
2186
Jim Grosbach7ce05792011-08-03 23:50:40 +00002187 static ARMOperand *CreateMem(unsigned BaseRegNum,
2188 const MCConstantExpr *OffsetImm,
2189 unsigned OffsetRegNum,
2190 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002191 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002192 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002193 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002194 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002195 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002196 Op->Memory.BaseRegNum = BaseRegNum;
2197 Op->Memory.OffsetImm = OffsetImm;
2198 Op->Memory.OffsetRegNum = OffsetRegNum;
2199 Op->Memory.ShiftType = ShiftType;
2200 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002201 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002202 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002203 Op->StartLoc = S;
2204 Op->EndLoc = E;
2205 return Op;
2206 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002207
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002208 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2209 ARM_AM::ShiftOpc ShiftTy,
2210 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002211 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002212 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002213 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002214 Op->PostIdxReg.isAdd = isAdd;
2215 Op->PostIdxReg.ShiftTy = ShiftTy;
2216 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002217 Op->StartLoc = S;
2218 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002219 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002220 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002221
2222 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002223 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002224 Op->MBOpt.Val = Opt;
2225 Op->StartLoc = S;
2226 Op->EndLoc = S;
2227 return Op;
2228 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002229
2230 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002231 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002232 Op->IFlags.Val = IFlags;
2233 Op->StartLoc = S;
2234 Op->EndLoc = S;
2235 return Op;
2236 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002237
2238 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002239 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002240 Op->MMask.Val = MMask;
2241 Op->StartLoc = S;
2242 Op->EndLoc = S;
2243 return Op;
2244 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002245};
2246
2247} // end anonymous namespace.
2248
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002249void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002250 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002251 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002252 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002253 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002254 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002255 OS << "<ccout " << getReg() << ">";
2256 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002257 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002258 static const char *MaskStr[] = {
2259 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2260 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2261 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002262 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2263 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2264 break;
2265 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002266 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002267 OS << "<coprocessor number: " << getCoproc() << ">";
2268 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002269 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002270 OS << "<coprocessor register: " << getCoproc() << ">";
2271 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002272 case k_CoprocOption:
2273 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2274 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002275 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002276 OS << "<mask: " << getMSRMask() << ">";
2277 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002278 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002279 getImm()->print(OS);
2280 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002281 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002282 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2283 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002284 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002285 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002286 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002287 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002288 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002289 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002290 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2291 << PostIdxReg.RegNum;
2292 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2293 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2294 << PostIdxReg.ShiftImm;
2295 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002296 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002297 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002298 OS << "<ARM_PROC::";
2299 unsigned IFlags = getProcIFlags();
2300 for (int i=2; i >= 0; --i)
2301 if (IFlags & (1 << i))
2302 OS << ARM_PROC::IFlagsToString(1 << i);
2303 OS << ">";
2304 break;
2305 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002306 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002307 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002308 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002309 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002310 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2311 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002312 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002313 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002314 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002315 << RegShiftedReg.SrcReg << " "
2316 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2317 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002318 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002319 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002320 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002321 << RegShiftedImm.SrcReg << " "
2322 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2323 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002324 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002325 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002326 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2327 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002328 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002329 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2330 << ", width: " << Bitfield.Width << ">";
2331 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002332 case k_RegisterList:
2333 case k_DPRRegisterList:
2334 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002335 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002336
Bill Wendling5fa22a12010-11-09 23:28:44 +00002337 const SmallVectorImpl<unsigned> &RegList = getRegList();
2338 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002339 I = RegList.begin(), E = RegList.end(); I != E; ) {
2340 OS << *I;
2341 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002342 }
2343
2344 OS << ">";
2345 break;
2346 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002347 case k_VectorList:
2348 OS << "<vector_list " << VectorList.Count << " * "
2349 << VectorList.RegNum << ">";
2350 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002351 case k_VectorListAllLanes:
2352 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2353 << VectorList.RegNum << ">";
2354 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002355 case k_VectorListIndexed:
2356 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2357 << VectorList.Count << " * " << VectorList.RegNum << ">";
2358 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002359 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002360 OS << "'" << getToken() << "'";
2361 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002362 case k_VectorIndex:
2363 OS << "<vectorindex " << getVectorIndex() << ">";
2364 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002365 }
2366}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002367
2368/// @name Auto-generated Match Functions
2369/// {
2370
2371static unsigned MatchRegisterName(StringRef Name);
2372
2373/// }
2374
Bob Wilson69df7232011-02-03 21:46:10 +00002375bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2376 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002377 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002378 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002379 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002380
2381 return (RegNo == (unsigned)-1);
2382}
2383
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002384/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002385/// and if it is a register name the token is eaten and the register number is
2386/// returned. Otherwise return -1.
2387///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002388int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002389 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002390 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002391
Benjamin Kramer59085362011-11-06 20:37:06 +00002392 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002393 unsigned RegNum = MatchRegisterName(lowerCase);
2394 if (!RegNum) {
2395 RegNum = StringSwitch<unsigned>(lowerCase)
2396 .Case("r13", ARM::SP)
2397 .Case("r14", ARM::LR)
2398 .Case("r15", ARM::PC)
2399 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002400 // Additional register name aliases for 'gas' compatibility.
2401 .Case("a1", ARM::R0)
2402 .Case("a2", ARM::R1)
2403 .Case("a3", ARM::R2)
2404 .Case("a4", ARM::R3)
2405 .Case("v1", ARM::R4)
2406 .Case("v2", ARM::R5)
2407 .Case("v3", ARM::R6)
2408 .Case("v4", ARM::R7)
2409 .Case("v5", ARM::R8)
2410 .Case("v6", ARM::R9)
2411 .Case("v7", ARM::R10)
2412 .Case("v8", ARM::R11)
2413 .Case("sb", ARM::R9)
2414 .Case("sl", ARM::R10)
2415 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002416 .Default(0);
2417 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002418 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002419 // Check for aliases registered via .req. Canonicalize to lower case.
2420 // That's more consistent since register names are case insensitive, and
2421 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2422 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002423 // If no match, return failure.
2424 if (Entry == RegisterReqs.end())
2425 return -1;
2426 Parser.Lex(); // Eat identifier token.
2427 return Entry->getValue();
2428 }
Bob Wilson69df7232011-02-03 21:46:10 +00002429
Chris Lattnere5658fa2010-10-30 04:09:10 +00002430 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002431
Chris Lattnere5658fa2010-10-30 04:09:10 +00002432 return RegNum;
2433}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002434
Jim Grosbach19906722011-07-13 18:49:30 +00002435// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2436// If a recoverable error occurs, return 1. If an irrecoverable error
2437// occurs, return -1. An irrecoverable error is one where tokens have been
2438// consumed in the process of trying to parse the shifter (i.e., when it is
2439// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002440int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002441 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2442 SMLoc S = Parser.getTok().getLoc();
2443 const AsmToken &Tok = Parser.getTok();
2444 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2445
Benjamin Kramer59085362011-11-06 20:37:06 +00002446 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002447 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002448 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002449 .Case("lsl", ARM_AM::lsl)
2450 .Case("lsr", ARM_AM::lsr)
2451 .Case("asr", ARM_AM::asr)
2452 .Case("ror", ARM_AM::ror)
2453 .Case("rrx", ARM_AM::rrx)
2454 .Default(ARM_AM::no_shift);
2455
2456 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002457 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002458
Jim Grosbache8606dc2011-07-13 17:50:29 +00002459 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002460
Jim Grosbache8606dc2011-07-13 17:50:29 +00002461 // The source register for the shift has already been added to the
2462 // operand list, so we need to pop it off and combine it into the shifted
2463 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002464 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002465 if (!PrevOp->isReg())
2466 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2467 int SrcReg = PrevOp->getReg();
2468 int64_t Imm = 0;
2469 int ShiftReg = 0;
2470 if (ShiftTy == ARM_AM::rrx) {
2471 // RRX Doesn't have an explicit shift amount. The encoder expects
2472 // the shift register to be the same as the source register. Seems odd,
2473 // but OK.
2474 ShiftReg = SrcReg;
2475 } else {
2476 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002477 if (Parser.getTok().is(AsmToken::Hash) ||
2478 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002479 Parser.Lex(); // Eat hash.
2480 SMLoc ImmLoc = Parser.getTok().getLoc();
2481 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002482 if (getParser().ParseExpression(ShiftExpr)) {
2483 Error(ImmLoc, "invalid immediate shift value");
2484 return -1;
2485 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002486 // The expression must be evaluatable as an immediate.
2487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002488 if (!CE) {
2489 Error(ImmLoc, "invalid immediate shift value");
2490 return -1;
2491 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002492 // Range check the immediate.
2493 // lsl, ror: 0 <= imm <= 31
2494 // lsr, asr: 0 <= imm <= 32
2495 Imm = CE->getValue();
2496 if (Imm < 0 ||
2497 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2498 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002499 Error(ImmLoc, "immediate shift value out of range");
2500 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002501 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002502 // shift by zero is a nop. Always send it through as lsl.
2503 // ('as' compatibility)
2504 if (Imm == 0)
2505 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002506 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002507 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002508 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002509 if (ShiftReg == -1) {
2510 Error (L, "expected immediate or register in shift operand");
2511 return -1;
2512 }
2513 } else {
2514 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002515 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002516 return -1;
2517 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002518 }
2519
Owen Anderson92a20222011-07-21 18:54:16 +00002520 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2521 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002522 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002523 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002524 else
2525 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2526 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002527
Jim Grosbach19906722011-07-13 18:49:30 +00002528 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002529}
2530
2531
Bill Wendling50d0f582010-11-18 23:43:05 +00002532/// Try to parse a register name. The token must be an Identifier when called.
2533/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2534/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002535///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002536/// TODO this is likely to change to allow different register types and or to
2537/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002538bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002539tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002540 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002541 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002542 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002543 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002544
Bill Wendling50d0f582010-11-18 23:43:05 +00002545 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002546
Chris Lattnere5658fa2010-10-30 04:09:10 +00002547 const AsmToken &ExclaimTok = Parser.getTok();
2548 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002549 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2550 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002551 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002552 return false;
2553 }
2554
2555 // Also check for an index operand. This is only legal for vector registers,
2556 // but that'll get caught OK in operand matching, so we don't need to
2557 // explicitly filter everything else out here.
2558 if (Parser.getTok().is(AsmToken::LBrac)) {
2559 SMLoc SIdx = Parser.getTok().getLoc();
2560 Parser.Lex(); // Eat left bracket token.
2561
2562 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002563 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002564 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002565 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002566 if (!MCE)
2567 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002568
2569 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002570 if (Parser.getTok().isNot(AsmToken::RBrac))
2571 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002572
2573 Parser.Lex(); // Eat right bracket token.
2574
2575 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2576 SIdx, E,
2577 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002578 }
2579
Bill Wendling50d0f582010-11-18 23:43:05 +00002580 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002581}
2582
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002583/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2584/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2585/// "c5", ...
2586static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002587 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2588 // but efficient.
2589 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002590 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002591 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002592 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002593 return -1;
2594 switch (Name[1]) {
2595 default: return -1;
2596 case '0': return 0;
2597 case '1': return 1;
2598 case '2': return 2;
2599 case '3': return 3;
2600 case '4': return 4;
2601 case '5': return 5;
2602 case '6': return 6;
2603 case '7': return 7;
2604 case '8': return 8;
2605 case '9': return 9;
2606 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002607 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002608 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002609 return -1;
2610 switch (Name[2]) {
2611 default: return -1;
2612 case '0': return 10;
2613 case '1': return 11;
2614 case '2': return 12;
2615 case '3': return 13;
2616 case '4': return 14;
2617 case '5': return 15;
2618 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002619 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002620}
2621
Jim Grosbach89df9962011-08-26 21:43:41 +00002622/// parseITCondCode - Try to parse a condition code for an IT instruction.
2623ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2624parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2625 SMLoc S = Parser.getTok().getLoc();
2626 const AsmToken &Tok = Parser.getTok();
2627 if (!Tok.is(AsmToken::Identifier))
2628 return MatchOperand_NoMatch;
2629 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2630 .Case("eq", ARMCC::EQ)
2631 .Case("ne", ARMCC::NE)
2632 .Case("hs", ARMCC::HS)
2633 .Case("cs", ARMCC::HS)
2634 .Case("lo", ARMCC::LO)
2635 .Case("cc", ARMCC::LO)
2636 .Case("mi", ARMCC::MI)
2637 .Case("pl", ARMCC::PL)
2638 .Case("vs", ARMCC::VS)
2639 .Case("vc", ARMCC::VC)
2640 .Case("hi", ARMCC::HI)
2641 .Case("ls", ARMCC::LS)
2642 .Case("ge", ARMCC::GE)
2643 .Case("lt", ARMCC::LT)
2644 .Case("gt", ARMCC::GT)
2645 .Case("le", ARMCC::LE)
2646 .Case("al", ARMCC::AL)
2647 .Default(~0U);
2648 if (CC == ~0U)
2649 return MatchOperand_NoMatch;
2650 Parser.Lex(); // Eat the token.
2651
2652 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2653
2654 return MatchOperand_Success;
2655}
2656
Jim Grosbach43904292011-07-25 20:14:50 +00002657/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002658/// token must be an Identifier when called, and if it is a coprocessor
2659/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002660ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002661parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002662 SMLoc S = Parser.getTok().getLoc();
2663 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002664 if (Tok.isNot(AsmToken::Identifier))
2665 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002666
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002667 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002668 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002669 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002670
2671 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002672 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002673 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002674}
2675
Jim Grosbach43904292011-07-25 20:14:50 +00002676/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002677/// token must be an Identifier when called, and if it is a coprocessor
2678/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002679ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002680parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002681 SMLoc S = Parser.getTok().getLoc();
2682 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002683 if (Tok.isNot(AsmToken::Identifier))
2684 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002685
2686 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2687 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002688 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002689
2690 Parser.Lex(); // Eat identifier token.
2691 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002692 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002693}
2694
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002695/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2696/// coproc_option : '{' imm0_255 '}'
2697ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2698parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2699 SMLoc S = Parser.getTok().getLoc();
2700
2701 // If this isn't a '{', this isn't a coprocessor immediate operand.
2702 if (Parser.getTok().isNot(AsmToken::LCurly))
2703 return MatchOperand_NoMatch;
2704 Parser.Lex(); // Eat the '{'
2705
2706 const MCExpr *Expr;
2707 SMLoc Loc = Parser.getTok().getLoc();
2708 if (getParser().ParseExpression(Expr)) {
2709 Error(Loc, "illegal expression");
2710 return MatchOperand_ParseFail;
2711 }
2712 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2713 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2714 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2715 return MatchOperand_ParseFail;
2716 }
2717 int Val = CE->getValue();
2718
2719 // Check for and consume the closing '}'
2720 if (Parser.getTok().isNot(AsmToken::RCurly))
2721 return MatchOperand_ParseFail;
2722 SMLoc E = Parser.getTok().getLoc();
2723 Parser.Lex(); // Eat the '}'
2724
2725 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2726 return MatchOperand_Success;
2727}
2728
Jim Grosbachd0588e22011-09-14 18:08:35 +00002729// For register list parsing, we need to map from raw GPR register numbering
2730// to the enumeration values. The enumeration values aren't sorted by
2731// register number due to our using "sp", "lr" and "pc" as canonical names.
2732static unsigned getNextRegister(unsigned Reg) {
2733 // If this is a GPR, we need to do it manually, otherwise we can rely
2734 // on the sort ordering of the enumeration since the other reg-classes
2735 // are sane.
2736 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2737 return Reg + 1;
2738 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002739 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002740 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2741 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2742 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2743 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2744 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2745 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2746 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2747 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2748 }
2749}
2750
Jim Grosbachce485e72011-11-11 21:27:40 +00002751// Return the low-subreg of a given Q register.
2752static unsigned getDRegFromQReg(unsigned QReg) {
2753 switch (QReg) {
2754 default: llvm_unreachable("expected a Q register!");
2755 case ARM::Q0: return ARM::D0;
2756 case ARM::Q1: return ARM::D2;
2757 case ARM::Q2: return ARM::D4;
2758 case ARM::Q3: return ARM::D6;
2759 case ARM::Q4: return ARM::D8;
2760 case ARM::Q5: return ARM::D10;
2761 case ARM::Q6: return ARM::D12;
2762 case ARM::Q7: return ARM::D14;
2763 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002764 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002765 case ARM::Q10: return ARM::D20;
2766 case ARM::Q11: return ARM::D22;
2767 case ARM::Q12: return ARM::D24;
2768 case ARM::Q13: return ARM::D26;
2769 case ARM::Q14: return ARM::D28;
2770 case ARM::Q15: return ARM::D30;
2771 }
2772}
2773
Jim Grosbachd0588e22011-09-14 18:08:35 +00002774/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002775bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002776parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002777 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002778 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002779 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002780 Parser.Lex(); // Eat '{' token.
2781 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002782
Jim Grosbachd0588e22011-09-14 18:08:35 +00002783 // Check the first register in the list to see what register class
2784 // this is a list of.
2785 int Reg = tryParseRegister();
2786 if (Reg == -1)
2787 return Error(RegLoc, "register expected");
2788
Jim Grosbachce485e72011-11-11 21:27:40 +00002789 // The reglist instructions have at most 16 registers, so reserve
2790 // space for that many.
2791 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2792
2793 // Allow Q regs and just interpret them as the two D sub-registers.
2794 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2795 Reg = getDRegFromQReg(Reg);
2796 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2797 ++Reg;
2798 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002799 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002800 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2801 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2802 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2803 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2804 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2805 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2806 else
2807 return Error(RegLoc, "invalid register in register list");
2808
Jim Grosbachce485e72011-11-11 21:27:40 +00002809 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002810 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002811
Jim Grosbachd0588e22011-09-14 18:08:35 +00002812 // This starts immediately after the first register token in the list,
2813 // so we can see either a comma or a minus (range separator) as a legal
2814 // next token.
2815 while (Parser.getTok().is(AsmToken::Comma) ||
2816 Parser.getTok().is(AsmToken::Minus)) {
2817 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002818 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002819 SMLoc EndLoc = Parser.getTok().getLoc();
2820 int EndReg = tryParseRegister();
2821 if (EndReg == -1)
2822 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002823 // Allow Q regs and just interpret them as the two D sub-registers.
2824 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2825 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002826 // If the register is the same as the start reg, there's nothing
2827 // more to do.
2828 if (Reg == EndReg)
2829 continue;
2830 // The register must be in the same register class as the first.
2831 if (!RC->contains(EndReg))
2832 return Error(EndLoc, "invalid register in register list");
2833 // Ranges must go from low to high.
2834 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2835 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002836
Jim Grosbachd0588e22011-09-14 18:08:35 +00002837 // Add all the registers in the range to the register list.
2838 while (Reg != EndReg) {
2839 Reg = getNextRegister(Reg);
2840 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2841 }
2842 continue;
2843 }
2844 Parser.Lex(); // Eat the comma.
2845 RegLoc = Parser.getTok().getLoc();
2846 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002847 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002848 Reg = tryParseRegister();
2849 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002850 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002851 // Allow Q regs and just interpret them as the two D sub-registers.
2852 bool isQReg = false;
2853 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2854 Reg = getDRegFromQReg(Reg);
2855 isQReg = true;
2856 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002857 // The register must be in the same register class as the first.
2858 if (!RC->contains(Reg))
2859 return Error(RegLoc, "invalid register in register list");
2860 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002861 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2862 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2863 Warning(RegLoc, "register list not in ascending order");
2864 else
2865 return Error(RegLoc, "register list not in ascending order");
2866 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002867 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2868 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2869 ") in register list");
2870 continue;
2871 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002872 // VFP register lists must also be contiguous.
2873 // It's OK to use the enumeration values directly here rather, as the
2874 // VFP register classes have the enum sorted properly.
2875 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2876 Reg != OldReg + 1)
2877 return Error(RegLoc, "non-contiguous register range");
2878 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002879 if (isQReg)
2880 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002881 }
2882
Jim Grosbachd0588e22011-09-14 18:08:35 +00002883 SMLoc E = Parser.getTok().getLoc();
2884 if (Parser.getTok().isNot(AsmToken::RCurly))
2885 return Error(E, "'}' expected");
2886 Parser.Lex(); // Eat '}' token.
2887
Jim Grosbach27debd62011-12-13 21:48:29 +00002888 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002889 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002890
2891 // The ARM system instruction variants for LDM/STM have a '^' token here.
2892 if (Parser.getTok().is(AsmToken::Caret)) {
2893 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2894 Parser.Lex(); // Eat '^' token.
2895 }
2896
Bill Wendling50d0f582010-11-18 23:43:05 +00002897 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002898}
2899
Jim Grosbach98b05a52011-11-30 01:09:44 +00002900// Helper function to parse the lane index for vector lists.
2901ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002902parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2903 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002904 if (Parser.getTok().is(AsmToken::LBrac)) {
2905 Parser.Lex(); // Eat the '['.
2906 if (Parser.getTok().is(AsmToken::RBrac)) {
2907 // "Dn[]" is the 'all lanes' syntax.
2908 LaneKind = AllLanes;
2909 Parser.Lex(); // Eat the ']'.
2910 return MatchOperand_Success;
2911 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002912
2913 // There's an optional '#' token here. Normally there wouldn't be, but
2914 // inline assemble puts one in, and it's friendly to accept that.
2915 if (Parser.getTok().is(AsmToken::Hash))
2916 Parser.Lex(); // Eat the '#'
2917
Jim Grosbachc9313252011-12-21 01:19:23 +00002918 const MCExpr *LaneIndex;
2919 SMLoc Loc = Parser.getTok().getLoc();
2920 if (getParser().ParseExpression(LaneIndex)) {
2921 Error(Loc, "illegal expression");
2922 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002923 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2925 if (!CE) {
2926 Error(Loc, "lane index must be empty or an integer");
2927 return MatchOperand_ParseFail;
2928 }
2929 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2930 Error(Parser.getTok().getLoc(), "']' expected");
2931 return MatchOperand_ParseFail;
2932 }
2933 Parser.Lex(); // Eat the ']'.
2934 int64_t Val = CE->getValue();
2935
2936 // FIXME: Make this range check context sensitive for .8, .16, .32.
2937 if (Val < 0 || Val > 7) {
2938 Error(Parser.getTok().getLoc(), "lane index out of range");
2939 return MatchOperand_ParseFail;
2940 }
2941 Index = Val;
2942 LaneKind = IndexedLane;
2943 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002944 }
2945 LaneKind = NoLanes;
2946 return MatchOperand_Success;
2947}
2948
Jim Grosbach862019c2011-10-18 23:02:30 +00002949// parse a vector register list
2950ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2951parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002952 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002953 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002954 SMLoc S = Parser.getTok().getLoc();
2955 // As an extension (to match gas), support a plain D register or Q register
2956 // (without encosing curly braces) as a single or double entry list,
2957 // respectively.
2958 if (Parser.getTok().is(AsmToken::Identifier)) {
2959 int Reg = tryParseRegister();
2960 if (Reg == -1)
2961 return MatchOperand_NoMatch;
2962 SMLoc E = Parser.getTok().getLoc();
2963 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002964 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002965 if (Res != MatchOperand_Success)
2966 return Res;
2967 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002968 case NoLanes:
2969 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002970 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002971 break;
2972 case AllLanes:
2973 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002974 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2975 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002976 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002977 case IndexedLane:
2978 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002979 LaneIndex,
2980 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002981 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002982 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002983 return MatchOperand_Success;
2984 }
2985 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2986 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002987 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002988 if (Res != MatchOperand_Success)
2989 return Res;
2990 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002991 case NoLanes:
2992 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00002993 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00002994 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002995 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002996 break;
2997 case AllLanes:
2998 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00002999 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3000 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003001 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3002 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003003 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003004 case IndexedLane:
3005 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003006 LaneIndex,
3007 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003008 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003009 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003010 return MatchOperand_Success;
3011 }
3012 Error(S, "vector register expected");
3013 return MatchOperand_ParseFail;
3014 }
3015
3016 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003017 return MatchOperand_NoMatch;
3018
Jim Grosbach862019c2011-10-18 23:02:30 +00003019 Parser.Lex(); // Eat '{' token.
3020 SMLoc RegLoc = Parser.getTok().getLoc();
3021
3022 int Reg = tryParseRegister();
3023 if (Reg == -1) {
3024 Error(RegLoc, "register expected");
3025 return MatchOperand_ParseFail;
3026 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003027 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003028 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003029 unsigned FirstReg = Reg;
3030 // The list is of D registers, but we also allow Q regs and just interpret
3031 // them as the two D sub-registers.
3032 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3033 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003034 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3035 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003036 ++Reg;
3037 ++Count;
3038 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003039 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003040 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003041
Jim Grosbache43862b2011-11-15 23:19:15 +00003042 while (Parser.getTok().is(AsmToken::Comma) ||
3043 Parser.getTok().is(AsmToken::Minus)) {
3044 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003045 if (!Spacing)
3046 Spacing = 1; // Register range implies a single spaced list.
3047 else if (Spacing == 2) {
3048 Error(Parser.getTok().getLoc(),
3049 "sequential registers in double spaced list");
3050 return MatchOperand_ParseFail;
3051 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003052 Parser.Lex(); // Eat the minus.
3053 SMLoc EndLoc = Parser.getTok().getLoc();
3054 int EndReg = tryParseRegister();
3055 if (EndReg == -1) {
3056 Error(EndLoc, "register expected");
3057 return MatchOperand_ParseFail;
3058 }
3059 // Allow Q regs and just interpret them as the two D sub-registers.
3060 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3061 EndReg = getDRegFromQReg(EndReg) + 1;
3062 // If the register is the same as the start reg, there's nothing
3063 // more to do.
3064 if (Reg == EndReg)
3065 continue;
3066 // The register must be in the same register class as the first.
3067 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3068 Error(EndLoc, "invalid register in register list");
3069 return MatchOperand_ParseFail;
3070 }
3071 // Ranges must go from low to high.
3072 if (Reg > EndReg) {
3073 Error(EndLoc, "bad range in register list");
3074 return MatchOperand_ParseFail;
3075 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003076 // Parse the lane specifier if present.
3077 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003078 unsigned NextLaneIndex;
3079 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003080 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003081 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003082 Error(EndLoc, "mismatched lane index in register list");
3083 return MatchOperand_ParseFail;
3084 }
3085 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003086
3087 // Add all the registers in the range to the register list.
3088 Count += EndReg - Reg;
3089 Reg = EndReg;
3090 continue;
3091 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003092 Parser.Lex(); // Eat the comma.
3093 RegLoc = Parser.getTok().getLoc();
3094 int OldReg = Reg;
3095 Reg = tryParseRegister();
3096 if (Reg == -1) {
3097 Error(RegLoc, "register expected");
3098 return MatchOperand_ParseFail;
3099 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003100 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003101 // It's OK to use the enumeration values directly here rather, as the
3102 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003103 //
3104 // The list is of D registers, but we also allow Q regs and just interpret
3105 // them as the two D sub-registers.
3106 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003107 if (!Spacing)
3108 Spacing = 1; // Register range implies a single spaced list.
3109 else if (Spacing == 2) {
3110 Error(RegLoc,
3111 "invalid register in double-spaced list (must be 'D' register')");
3112 return MatchOperand_ParseFail;
3113 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003114 Reg = getDRegFromQReg(Reg);
3115 if (Reg != OldReg + 1) {
3116 Error(RegLoc, "non-contiguous register range");
3117 return MatchOperand_ParseFail;
3118 }
3119 ++Reg;
3120 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003121 // Parse the lane specifier if present.
3122 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003123 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003124 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003125 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003126 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003127 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003128 Error(EndLoc, "mismatched lane index in register list");
3129 return MatchOperand_ParseFail;
3130 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003131 continue;
3132 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003133 // Normal D register.
3134 // Figure out the register spacing (single or double) of the list if
3135 // we don't know it already.
3136 if (!Spacing)
3137 Spacing = 1 + (Reg == OldReg + 2);
3138
3139 // Just check that it's contiguous and keep going.
3140 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003141 Error(RegLoc, "non-contiguous register range");
3142 return MatchOperand_ParseFail;
3143 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003144 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003145 // Parse the lane specifier if present.
3146 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003147 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003148 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003149 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003150 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003151 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003152 Error(EndLoc, "mismatched lane index in register list");
3153 return MatchOperand_ParseFail;
3154 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003155 }
3156
3157 SMLoc E = Parser.getTok().getLoc();
3158 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3159 Error(E, "'}' expected");
3160 return MatchOperand_ParseFail;
3161 }
3162 Parser.Lex(); // Eat '}' token.
3163
Jim Grosbach98b05a52011-11-30 01:09:44 +00003164 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003165 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003166 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003167 // composite register classes.
3168 if (Count == 2) {
3169 const MCRegisterClass *RC = (Spacing == 1) ?
3170 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3171 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3172 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3173 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003174
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003175 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3176 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003177 break;
3178 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003179 // Two-register operands have been converted to the
3180 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003181 if (Count == 2) {
3182 const MCRegisterClass *RC = (Spacing == 1) ?
3183 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3184 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003185 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3186 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003187 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003188 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003189 S, E));
3190 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003191 case IndexedLane:
3192 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003193 LaneIndex,
3194 (Spacing == 2),
3195 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003196 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003197 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003198 return MatchOperand_Success;
3199}
3200
Jim Grosbach43904292011-07-25 20:14:50 +00003201/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003202ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003203parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003204 SMLoc S = Parser.getTok().getLoc();
3205 const AsmToken &Tok = Parser.getTok();
3206 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3207 StringRef OptStr = Tok.getString();
3208
3209 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3210 .Case("sy", ARM_MB::SY)
3211 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003212 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003213 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003214 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003215 .Case("ishst", ARM_MB::ISHST)
3216 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003217 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003218 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003219 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003220 .Case("osh", ARM_MB::OSH)
3221 .Case("oshst", ARM_MB::OSHST)
3222 .Default(~0U);
3223
3224 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003225 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003226
3227 Parser.Lex(); // Eat identifier token.
3228 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003229 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003230}
3231
Jim Grosbach43904292011-07-25 20:14:50 +00003232/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003233ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003234parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003235 SMLoc S = Parser.getTok().getLoc();
3236 const AsmToken &Tok = Parser.getTok();
3237 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3238 StringRef IFlagsStr = Tok.getString();
3239
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003240 // An iflags string of "none" is interpreted to mean that none of the AIF
3241 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003242 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003243 if (IFlagsStr != "none") {
3244 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3245 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3246 .Case("a", ARM_PROC::A)
3247 .Case("i", ARM_PROC::I)
3248 .Case("f", ARM_PROC::F)
3249 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003250
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003251 // If some specific iflag is already set, it means that some letter is
3252 // present more than once, this is not acceptable.
3253 if (Flag == ~0U || (IFlags & Flag))
3254 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003255
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003256 IFlags |= Flag;
3257 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003258 }
3259
3260 Parser.Lex(); // Eat identifier token.
3261 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3262 return MatchOperand_Success;
3263}
3264
Jim Grosbach43904292011-07-25 20:14:50 +00003265/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003266ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003267parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003268 SMLoc S = Parser.getTok().getLoc();
3269 const AsmToken &Tok = Parser.getTok();
3270 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3271 StringRef Mask = Tok.getString();
3272
James Molloyacad68d2011-09-28 14:21:38 +00003273 if (isMClass()) {
3274 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003275 std::string Name = Mask.lower();
3276 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloyacad68d2011-09-28 14:21:38 +00003277 .Case("apsr", 0)
3278 .Case("iapsr", 1)
3279 .Case("eapsr", 2)
3280 .Case("xpsr", 3)
3281 .Case("ipsr", 5)
3282 .Case("epsr", 6)
3283 .Case("iepsr", 7)
3284 .Case("msp", 8)
3285 .Case("psp", 9)
3286 .Case("primask", 16)
3287 .Case("basepri", 17)
3288 .Case("basepri_max", 18)
3289 .Case("faultmask", 19)
3290 .Case("control", 20)
3291 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003292
James Molloyacad68d2011-09-28 14:21:38 +00003293 if (FlagsVal == ~0U)
3294 return MatchOperand_NoMatch;
3295
3296 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3297 // basepri, basepri_max and faultmask only valid for V7m.
3298 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003299
James Molloyacad68d2011-09-28 14:21:38 +00003300 Parser.Lex(); // Eat identifier token.
3301 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3302 return MatchOperand_Success;
3303 }
3304
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003305 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3306 size_t Start = 0, Next = Mask.find('_');
3307 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003308 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003309 if (Next != StringRef::npos)
3310 Flags = Mask.slice(Next+1, Mask.size());
3311
3312 // FlagsVal contains the complete mask:
3313 // 3-0: Mask
3314 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3315 unsigned FlagsVal = 0;
3316
3317 if (SpecReg == "apsr") {
3318 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003319 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003320 .Case("g", 0x4) // same as CPSR_s
3321 .Case("nzcvqg", 0xc) // same as CPSR_fs
3322 .Default(~0U);
3323
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003324 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003325 if (!Flags.empty())
3326 return MatchOperand_NoMatch;
3327 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003328 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003329 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003330 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbachb657a902012-04-05 03:17:53 +00003331 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3332 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003333 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003334 for (int i = 0, e = Flags.size(); i != e; ++i) {
3335 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3336 .Case("c", 1)
3337 .Case("x", 2)
3338 .Case("s", 4)
3339 .Case("f", 8)
3340 .Default(~0U);
3341
3342 // If some specific flag is already set, it means that some letter is
3343 // present more than once, this is not acceptable.
3344 if (FlagsVal == ~0U || (FlagsVal & Flag))
3345 return MatchOperand_NoMatch;
3346 FlagsVal |= Flag;
3347 }
3348 } else // No match for special register.
3349 return MatchOperand_NoMatch;
3350
Owen Anderson7784f1d2011-10-21 18:43:28 +00003351 // Special register without flags is NOT equivalent to "fc" flags.
3352 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3353 // two lines would enable gas compatibility at the expense of breaking
3354 // round-tripping.
3355 //
3356 // if (!FlagsVal)
3357 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003358
3359 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3360 if (SpecReg == "spsr")
3361 FlagsVal |= 16;
3362
3363 Parser.Lex(); // Eat identifier token.
3364 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3365 return MatchOperand_Success;
3366}
3367
Jim Grosbachf6c05252011-07-21 17:23:04 +00003368ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3369parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3370 int Low, int High) {
3371 const AsmToken &Tok = Parser.getTok();
3372 if (Tok.isNot(AsmToken::Identifier)) {
3373 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3374 return MatchOperand_ParseFail;
3375 }
3376 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003377 std::string LowerOp = Op.lower();
3378 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003379 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3380 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3381 return MatchOperand_ParseFail;
3382 }
3383 Parser.Lex(); // Eat shift type token.
3384
3385 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003386 if (Parser.getTok().isNot(AsmToken::Hash) &&
3387 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003388 Error(Parser.getTok().getLoc(), "'#' expected");
3389 return MatchOperand_ParseFail;
3390 }
3391 Parser.Lex(); // Eat hash token.
3392
3393 const MCExpr *ShiftAmount;
3394 SMLoc Loc = Parser.getTok().getLoc();
3395 if (getParser().ParseExpression(ShiftAmount)) {
3396 Error(Loc, "illegal expression");
3397 return MatchOperand_ParseFail;
3398 }
3399 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3400 if (!CE) {
3401 Error(Loc, "constant expression expected");
3402 return MatchOperand_ParseFail;
3403 }
3404 int Val = CE->getValue();
3405 if (Val < Low || Val > High) {
3406 Error(Loc, "immediate value out of range");
3407 return MatchOperand_ParseFail;
3408 }
3409
3410 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3411
3412 return MatchOperand_Success;
3413}
3414
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003415ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3416parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3417 const AsmToken &Tok = Parser.getTok();
3418 SMLoc S = Tok.getLoc();
3419 if (Tok.isNot(AsmToken::Identifier)) {
3420 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3421 return MatchOperand_ParseFail;
3422 }
3423 int Val = StringSwitch<int>(Tok.getString())
3424 .Case("be", 1)
3425 .Case("le", 0)
3426 .Default(-1);
3427 Parser.Lex(); // Eat the token.
3428
3429 if (Val == -1) {
3430 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3431 return MatchOperand_ParseFail;
3432 }
3433 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3434 getContext()),
3435 S, Parser.getTok().getLoc()));
3436 return MatchOperand_Success;
3437}
3438
Jim Grosbach580f4a92011-07-25 22:20:28 +00003439/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3440/// instructions. Legal values are:
3441/// lsl #n 'n' in [0,31]
3442/// asr #n 'n' in [1,32]
3443/// n == 32 encoded as n == 0.
3444ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3445parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3446 const AsmToken &Tok = Parser.getTok();
3447 SMLoc S = Tok.getLoc();
3448 if (Tok.isNot(AsmToken::Identifier)) {
3449 Error(S, "shift operator 'asr' or 'lsl' expected");
3450 return MatchOperand_ParseFail;
3451 }
3452 StringRef ShiftName = Tok.getString();
3453 bool isASR;
3454 if (ShiftName == "lsl" || ShiftName == "LSL")
3455 isASR = false;
3456 else if (ShiftName == "asr" || ShiftName == "ASR")
3457 isASR = true;
3458 else {
3459 Error(S, "shift operator 'asr' or 'lsl' expected");
3460 return MatchOperand_ParseFail;
3461 }
3462 Parser.Lex(); // Eat the operator.
3463
3464 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003465 if (Parser.getTok().isNot(AsmToken::Hash) &&
3466 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003467 Error(Parser.getTok().getLoc(), "'#' expected");
3468 return MatchOperand_ParseFail;
3469 }
3470 Parser.Lex(); // Eat hash token.
3471
3472 const MCExpr *ShiftAmount;
3473 SMLoc E = Parser.getTok().getLoc();
3474 if (getParser().ParseExpression(ShiftAmount)) {
3475 Error(E, "malformed shift expression");
3476 return MatchOperand_ParseFail;
3477 }
3478 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3479 if (!CE) {
3480 Error(E, "shift amount must be an immediate");
3481 return MatchOperand_ParseFail;
3482 }
3483
3484 int64_t Val = CE->getValue();
3485 if (isASR) {
3486 // Shift amount must be in [1,32]
3487 if (Val < 1 || Val > 32) {
3488 Error(E, "'asr' shift amount must be in range [1,32]");
3489 return MatchOperand_ParseFail;
3490 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003491 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3492 if (isThumb() && Val == 32) {
3493 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3494 return MatchOperand_ParseFail;
3495 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003496 if (Val == 32) Val = 0;
3497 } else {
3498 // Shift amount must be in [1,32]
3499 if (Val < 0 || Val > 31) {
3500 Error(E, "'lsr' shift amount must be in range [0,31]");
3501 return MatchOperand_ParseFail;
3502 }
3503 }
3504
3505 E = Parser.getTok().getLoc();
3506 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3507
3508 return MatchOperand_Success;
3509}
3510
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003511/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3512/// of instructions. Legal values are:
3513/// ror #n 'n' in {0, 8, 16, 24}
3514ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3515parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3516 const AsmToken &Tok = Parser.getTok();
3517 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003518 if (Tok.isNot(AsmToken::Identifier))
3519 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003520 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003521 if (ShiftName != "ror" && ShiftName != "ROR")
3522 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003523 Parser.Lex(); // Eat the operator.
3524
3525 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003526 if (Parser.getTok().isNot(AsmToken::Hash) &&
3527 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003528 Error(Parser.getTok().getLoc(), "'#' expected");
3529 return MatchOperand_ParseFail;
3530 }
3531 Parser.Lex(); // Eat hash token.
3532
3533 const MCExpr *ShiftAmount;
3534 SMLoc E = Parser.getTok().getLoc();
3535 if (getParser().ParseExpression(ShiftAmount)) {
3536 Error(E, "malformed rotate expression");
3537 return MatchOperand_ParseFail;
3538 }
3539 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3540 if (!CE) {
3541 Error(E, "rotate amount must be an immediate");
3542 return MatchOperand_ParseFail;
3543 }
3544
3545 int64_t Val = CE->getValue();
3546 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3547 // normally, zero is represented in asm by omitting the rotate operand
3548 // entirely.
3549 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3550 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3551 return MatchOperand_ParseFail;
3552 }
3553
3554 E = Parser.getTok().getLoc();
3555 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3556
3557 return MatchOperand_Success;
3558}
3559
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003560ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3561parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3562 SMLoc S = Parser.getTok().getLoc();
3563 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003564 if (Parser.getTok().isNot(AsmToken::Hash) &&
3565 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003566 Error(Parser.getTok().getLoc(), "'#' expected");
3567 return MatchOperand_ParseFail;
3568 }
3569 Parser.Lex(); // Eat hash token.
3570
3571 const MCExpr *LSBExpr;
3572 SMLoc E = Parser.getTok().getLoc();
3573 if (getParser().ParseExpression(LSBExpr)) {
3574 Error(E, "malformed immediate expression");
3575 return MatchOperand_ParseFail;
3576 }
3577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3578 if (!CE) {
3579 Error(E, "'lsb' operand must be an immediate");
3580 return MatchOperand_ParseFail;
3581 }
3582
3583 int64_t LSB = CE->getValue();
3584 // The LSB must be in the range [0,31]
3585 if (LSB < 0 || LSB > 31) {
3586 Error(E, "'lsb' operand must be in the range [0,31]");
3587 return MatchOperand_ParseFail;
3588 }
3589 E = Parser.getTok().getLoc();
3590
3591 // Expect another immediate operand.
3592 if (Parser.getTok().isNot(AsmToken::Comma)) {
3593 Error(Parser.getTok().getLoc(), "too few operands");
3594 return MatchOperand_ParseFail;
3595 }
3596 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003597 if (Parser.getTok().isNot(AsmToken::Hash) &&
3598 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003599 Error(Parser.getTok().getLoc(), "'#' expected");
3600 return MatchOperand_ParseFail;
3601 }
3602 Parser.Lex(); // Eat hash token.
3603
3604 const MCExpr *WidthExpr;
3605 if (getParser().ParseExpression(WidthExpr)) {
3606 Error(E, "malformed immediate expression");
3607 return MatchOperand_ParseFail;
3608 }
3609 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3610 if (!CE) {
3611 Error(E, "'width' operand must be an immediate");
3612 return MatchOperand_ParseFail;
3613 }
3614
3615 int64_t Width = CE->getValue();
3616 // The LSB must be in the range [1,32-lsb]
3617 if (Width < 1 || Width > 32 - LSB) {
3618 Error(E, "'width' operand must be in the range [1,32-lsb]");
3619 return MatchOperand_ParseFail;
3620 }
3621 E = Parser.getTok().getLoc();
3622
3623 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3624
3625 return MatchOperand_Success;
3626}
3627
Jim Grosbach7ce05792011-08-03 23:50:40 +00003628ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3629parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3630 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003631 // postidx_reg := '+' register {, shift}
3632 // | '-' register {, shift}
3633 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003634
3635 // This method must return MatchOperand_NoMatch without consuming any tokens
3636 // in the case where there is no match, as other alternatives take other
3637 // parse methods.
3638 AsmToken Tok = Parser.getTok();
3639 SMLoc S = Tok.getLoc();
3640 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003641 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003642 int Reg = -1;
3643 if (Tok.is(AsmToken::Plus)) {
3644 Parser.Lex(); // Eat the '+' token.
3645 haveEaten = true;
3646 } else if (Tok.is(AsmToken::Minus)) {
3647 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003648 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003649 haveEaten = true;
3650 }
3651 if (Parser.getTok().is(AsmToken::Identifier))
3652 Reg = tryParseRegister();
3653 if (Reg == -1) {
3654 if (!haveEaten)
3655 return MatchOperand_NoMatch;
3656 Error(Parser.getTok().getLoc(), "register expected");
3657 return MatchOperand_ParseFail;
3658 }
3659 SMLoc E = Parser.getTok().getLoc();
3660
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003661 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3662 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003663 if (Parser.getTok().is(AsmToken::Comma)) {
3664 Parser.Lex(); // Eat the ','.
3665 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3666 return MatchOperand_ParseFail;
3667 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003668
3669 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3670 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003671
3672 return MatchOperand_Success;
3673}
3674
Jim Grosbach251bf252011-08-10 21:56:18 +00003675ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3676parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3677 // Check for a post-index addressing register operand. Specifically:
3678 // am3offset := '+' register
3679 // | '-' register
3680 // | register
3681 // | # imm
3682 // | # + imm
3683 // | # - imm
3684
3685 // This method must return MatchOperand_NoMatch without consuming any tokens
3686 // in the case where there is no match, as other alternatives take other
3687 // parse methods.
3688 AsmToken Tok = Parser.getTok();
3689 SMLoc S = Tok.getLoc();
3690
3691 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003692 if (Parser.getTok().is(AsmToken::Hash) ||
3693 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003694 Parser.Lex(); // Eat the '#'.
3695 // Explicitly look for a '-', as we need to encode negative zero
3696 // differently.
3697 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3698 const MCExpr *Offset;
3699 if (getParser().ParseExpression(Offset))
3700 return MatchOperand_ParseFail;
3701 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3702 if (!CE) {
3703 Error(S, "constant expression expected");
3704 return MatchOperand_ParseFail;
3705 }
3706 SMLoc E = Tok.getLoc();
3707 // Negative zero is encoded as the flag value INT32_MIN.
3708 int32_t Val = CE->getValue();
3709 if (isNegative && Val == 0)
3710 Val = INT32_MIN;
3711
3712 Operands.push_back(
3713 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3714
3715 return MatchOperand_Success;
3716 }
3717
3718
3719 bool haveEaten = false;
3720 bool isAdd = true;
3721 int Reg = -1;
3722 if (Tok.is(AsmToken::Plus)) {
3723 Parser.Lex(); // Eat the '+' token.
3724 haveEaten = true;
3725 } else if (Tok.is(AsmToken::Minus)) {
3726 Parser.Lex(); // Eat the '-' token.
3727 isAdd = false;
3728 haveEaten = true;
3729 }
3730 if (Parser.getTok().is(AsmToken::Identifier))
3731 Reg = tryParseRegister();
3732 if (Reg == -1) {
3733 if (!haveEaten)
3734 return MatchOperand_NoMatch;
3735 Error(Parser.getTok().getLoc(), "register expected");
3736 return MatchOperand_ParseFail;
3737 }
3738 SMLoc E = Parser.getTok().getLoc();
3739
3740 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3741 0, S, E));
3742
3743 return MatchOperand_Success;
3744}
3745
Jim Grosbacha77295d2011-09-08 22:07:06 +00003746/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3747/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3748/// when they refer multiple MIOperands inside a single one.
3749bool ARMAsmParser::
3750cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3751 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3752 // Rt, Rt2
3753 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3754 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3755 // Create a writeback register dummy placeholder.
3756 Inst.addOperand(MCOperand::CreateReg(0));
3757 // addr
3758 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3759 // pred
3760 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3761 return true;
3762}
3763
3764/// cvtT2StrdPre - Convert parsed operands to MCInst.
3765/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3766/// when they refer multiple MIOperands inside a single one.
3767bool ARMAsmParser::
3768cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3769 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3770 // Create a writeback register dummy placeholder.
3771 Inst.addOperand(MCOperand::CreateReg(0));
3772 // Rt, Rt2
3773 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3774 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3775 // addr
3776 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3777 // pred
3778 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3779 return true;
3780}
3781
Jim Grosbacheeec0252011-09-08 00:39:19 +00003782/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3783/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3784/// when they refer multiple MIOperands inside a single one.
3785bool ARMAsmParser::
3786cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3787 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3788 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3789
3790 // Create a writeback register dummy placeholder.
3791 Inst.addOperand(MCOperand::CreateImm(0));
3792
3793 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3794 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3795 return true;
3796}
3797
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003798/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3799/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3800/// when they refer multiple MIOperands inside a single one.
3801bool ARMAsmParser::
3802cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3803 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3804 // Create a writeback register dummy placeholder.
3805 Inst.addOperand(MCOperand::CreateImm(0));
3806 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3807 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3808 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3809 return true;
3810}
3811
Jim Grosbach1355cf12011-07-26 17:10:22 +00003812/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003813/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3814/// when they refer multiple MIOperands inside a single one.
3815bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003816cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003817 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3818 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3819
3820 // Create a writeback register dummy placeholder.
3821 Inst.addOperand(MCOperand::CreateImm(0));
3822
Jim Grosbach7ce05792011-08-03 23:50:40 +00003823 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3825 return true;
3826}
3827
Owen Anderson9ab0f252011-08-26 20:43:14 +00003828/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3830/// when they refer multiple MIOperands inside a single one.
3831bool ARMAsmParser::
3832cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3834 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3835
3836 // Create a writeback register dummy placeholder.
3837 Inst.addOperand(MCOperand::CreateImm(0));
3838
3839 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3840 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3841 return true;
3842}
3843
3844
Jim Grosbach548340c2011-08-11 19:22:40 +00003845/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3846/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3847/// when they refer multiple MIOperands inside a single one.
3848bool ARMAsmParser::
3849cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3850 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3851 // Create a writeback register dummy placeholder.
3852 Inst.addOperand(MCOperand::CreateImm(0));
3853 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3854 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3855 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3856 return true;
3857}
3858
Jim Grosbach1355cf12011-07-26 17:10:22 +00003859/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003860/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3861/// when they refer multiple MIOperands inside a single one.
3862bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003863cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003864 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3865 // Create a writeback register dummy placeholder.
3866 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003867 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3868 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3869 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003870 return true;
3871}
3872
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003873/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3874/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3875/// when they refer multiple MIOperands inside a single one.
3876bool ARMAsmParser::
3877cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3878 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3879 // Create a writeback register dummy placeholder.
3880 Inst.addOperand(MCOperand::CreateImm(0));
3881 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3882 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3883 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3884 return true;
3885}
3886
Jim Grosbach7ce05792011-08-03 23:50:40 +00003887/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3888/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3889/// when they refer multiple MIOperands inside a single one.
3890bool ARMAsmParser::
3891cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3892 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3893 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003894 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003895 // Create a writeback register dummy placeholder.
3896 Inst.addOperand(MCOperand::CreateImm(0));
3897 // addr
3898 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3899 // offset
3900 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3901 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003902 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3903 return true;
3904}
3905
Jim Grosbach7ce05792011-08-03 23:50:40 +00003906/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003907/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3908/// when they refer multiple MIOperands inside a single one.
3909bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003910cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3911 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3912 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003913 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003914 // Create a writeback register dummy placeholder.
3915 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003916 // addr
3917 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3918 // offset
3919 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3920 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003921 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3922 return true;
3923}
3924
Jim Grosbach7ce05792011-08-03 23:50:40 +00003925/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003926/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3927/// when they refer multiple MIOperands inside a single one.
3928bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003929cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3930 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003931 // Create a writeback register dummy placeholder.
3932 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003933 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003934 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003935 // addr
3936 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3937 // offset
3938 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3939 // pred
3940 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3941 return true;
3942}
3943
3944/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3945/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3946/// when they refer multiple MIOperands inside a single one.
3947bool ARMAsmParser::
3948cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3949 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3950 // Create a writeback register dummy placeholder.
3951 Inst.addOperand(MCOperand::CreateImm(0));
3952 // Rt
3953 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3954 // addr
3955 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3956 // offset
3957 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3958 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003959 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3960 return true;
3961}
3962
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003963/// cvtLdrdPre - Convert parsed operands to MCInst.
3964/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3965/// when they refer multiple MIOperands inside a single one.
3966bool ARMAsmParser::
3967cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3968 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3969 // Rt, Rt2
3970 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3971 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3972 // Create a writeback register dummy placeholder.
3973 Inst.addOperand(MCOperand::CreateImm(0));
3974 // addr
3975 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3976 // pred
3977 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3978 return true;
3979}
3980
Jim Grosbach14605d12011-08-11 20:28:23 +00003981/// cvtStrdPre - Convert parsed operands to MCInst.
3982/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3983/// when they refer multiple MIOperands inside a single one.
3984bool ARMAsmParser::
3985cvtStrdPre(MCInst &Inst, unsigned Opcode,
3986 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3987 // Create a writeback register dummy placeholder.
3988 Inst.addOperand(MCOperand::CreateImm(0));
3989 // Rt, Rt2
3990 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3991 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3992 // addr
3993 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3994 // pred
3995 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3996 return true;
3997}
3998
Jim Grosbach623a4542011-08-10 22:42:16 +00003999/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4000/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4001/// when they refer multiple MIOperands inside a single one.
4002bool ARMAsmParser::
4003cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4004 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4005 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4006 // Create a writeback register dummy placeholder.
4007 Inst.addOperand(MCOperand::CreateImm(0));
4008 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4009 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4010 return true;
4011}
4012
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004013/// cvtThumbMultiple- Convert parsed operands to MCInst.
4014/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4015/// when they refer multiple MIOperands inside a single one.
4016bool ARMAsmParser::
4017cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4018 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4019 // The second source operand must be the same register as the destination
4020 // operand.
4021 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004022 (((ARMOperand*)Operands[3])->getReg() !=
4023 ((ARMOperand*)Operands[5])->getReg()) &&
4024 (((ARMOperand*)Operands[3])->getReg() !=
4025 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004026 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004027 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004028 return false;
4029 }
4030 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4031 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004032 // If we have a three-operand form, make sure to set Rn to be the operand
4033 // that isn't the same as Rd.
4034 unsigned RegOp = 4;
4035 if (Operands.size() == 6 &&
4036 ((ARMOperand*)Operands[4])->getReg() ==
4037 ((ARMOperand*)Operands[3])->getReg())
4038 RegOp = 5;
4039 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4040 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004041 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4042
4043 return true;
4044}
Jim Grosbach623a4542011-08-10 22:42:16 +00004045
Jim Grosbach12431322011-10-24 22:16:58 +00004046bool ARMAsmParser::
4047cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4048 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4049 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004050 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004051 // Create a writeback register dummy placeholder.
4052 Inst.addOperand(MCOperand::CreateImm(0));
4053 // Vn
4054 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4055 // pred
4056 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4057 return true;
4058}
4059
4060bool ARMAsmParser::
4061cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4062 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4063 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004064 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004065 // Create a writeback register dummy placeholder.
4066 Inst.addOperand(MCOperand::CreateImm(0));
4067 // Vn
4068 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4069 // Vm
4070 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4071 // pred
4072 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4073 return true;
4074}
4075
Jim Grosbach4334e032011-10-31 21:50:31 +00004076bool ARMAsmParser::
4077cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4078 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4079 // Create a writeback register dummy placeholder.
4080 Inst.addOperand(MCOperand::CreateImm(0));
4081 // Vn
4082 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4083 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004084 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004085 // pred
4086 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4087 return true;
4088}
4089
4090bool ARMAsmParser::
4091cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4092 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4093 // Create a writeback register dummy placeholder.
4094 Inst.addOperand(MCOperand::CreateImm(0));
4095 // Vn
4096 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4097 // Vm
4098 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4099 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004100 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004101 // pred
4102 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4103 return true;
4104}
4105
Bill Wendlinge7176102010-11-06 22:36:58 +00004106/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004107/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004108bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004109parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004110 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004111 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004112 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004113 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004114 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004115
Sean Callanan18b83232010-01-19 21:44:56 +00004116 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004117 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004118 if (BaseRegNum == -1)
4119 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004120
Daniel Dunbar05710932011-01-18 05:34:17 +00004121 // The next token must either be a comma or a closing bracket.
4122 const AsmToken &Tok = Parser.getTok();
4123 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004124 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004125
Jim Grosbach7ce05792011-08-03 23:50:40 +00004126 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004127 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004128 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004129
Jim Grosbach7ce05792011-08-03 23:50:40 +00004130 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004131 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004132
Jim Grosbachfb12f352011-09-19 18:42:21 +00004133 // If there's a pre-indexing writeback marker, '!', just add it as a token
4134 // operand. It's rather odd, but syntactically valid.
4135 if (Parser.getTok().is(AsmToken::Exclaim)) {
4136 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4137 Parser.Lex(); // Eat the '!'.
4138 }
4139
Jim Grosbach7ce05792011-08-03 23:50:40 +00004140 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004141 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004142
Jim Grosbach7ce05792011-08-03 23:50:40 +00004143 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4144 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004145
Jim Grosbach57dcb852011-10-11 17:29:55 +00004146 // If we have a ':', it's an alignment specifier.
4147 if (Parser.getTok().is(AsmToken::Colon)) {
4148 Parser.Lex(); // Eat the ':'.
4149 E = Parser.getTok().getLoc();
4150
4151 const MCExpr *Expr;
4152 if (getParser().ParseExpression(Expr))
4153 return true;
4154
4155 // The expression has to be a constant. Memory references with relocations
4156 // don't come through here, as they use the <label> forms of the relevant
4157 // instructions.
4158 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4159 if (!CE)
4160 return Error (E, "constant expression expected");
4161
4162 unsigned Align = 0;
4163 switch (CE->getValue()) {
4164 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004165 return Error(E,
4166 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4167 case 16: Align = 2; break;
4168 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004169 case 64: Align = 8; break;
4170 case 128: Align = 16; break;
4171 case 256: Align = 32; break;
4172 }
4173
4174 // Now we should have the closing ']'
4175 E = Parser.getTok().getLoc();
4176 if (Parser.getTok().isNot(AsmToken::RBrac))
4177 return Error(E, "']' expected");
4178 Parser.Lex(); // Eat right bracket token.
4179
4180 // Don't worry about range checking the value here. That's handled by
4181 // the is*() predicates.
4182 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4183 ARM_AM::no_shift, 0, Align,
4184 false, S, E));
4185
4186 // If there's a pre-indexing writeback marker, '!', just add it as a token
4187 // operand.
4188 if (Parser.getTok().is(AsmToken::Exclaim)) {
4189 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4190 Parser.Lex(); // Eat the '!'.
4191 }
4192
4193 return false;
4194 }
4195
4196 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004197 // offset. Be friendly and also accept a plain integer (without a leading
4198 // hash) for gas compatibility.
4199 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004200 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004201 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004202 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004203 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004204 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004205
Owen Anderson0da10cf2011-08-29 19:36:44 +00004206 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004207 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004208 if (getParser().ParseExpression(Offset))
4209 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004210
4211 // The expression has to be a constant. Memory references with relocations
4212 // don't come through here, as they use the <label> forms of the relevant
4213 // instructions.
4214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4215 if (!CE)
4216 return Error (E, "constant expression expected");
4217
Owen Anderson0da10cf2011-08-29 19:36:44 +00004218 // If the constant was #-0, represent it as INT32_MIN.
4219 int32_t Val = CE->getValue();
4220 if (isNegative && Val == 0)
4221 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4222
Jim Grosbach7ce05792011-08-03 23:50:40 +00004223 // Now we should have the closing ']'
4224 E = Parser.getTok().getLoc();
4225 if (Parser.getTok().isNot(AsmToken::RBrac))
4226 return Error(E, "']' expected");
4227 Parser.Lex(); // Eat right bracket token.
4228
4229 // Don't worry about range checking the value here. That's handled by
4230 // the is*() predicates.
4231 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004232 ARM_AM::no_shift, 0, 0,
4233 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004234
4235 // If there's a pre-indexing writeback marker, '!', just add it as a token
4236 // operand.
4237 if (Parser.getTok().is(AsmToken::Exclaim)) {
4238 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4239 Parser.Lex(); // Eat the '!'.
4240 }
4241
4242 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004243 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004244
4245 // The register offset is optionally preceded by a '+' or '-'
4246 bool isNegative = false;
4247 if (Parser.getTok().is(AsmToken::Minus)) {
4248 isNegative = true;
4249 Parser.Lex(); // Eat the '-'.
4250 } else if (Parser.getTok().is(AsmToken::Plus)) {
4251 // Nothing to do.
4252 Parser.Lex(); // Eat the '+'.
4253 }
4254
4255 E = Parser.getTok().getLoc();
4256 int OffsetRegNum = tryParseRegister();
4257 if (OffsetRegNum == -1)
4258 return Error(E, "register expected");
4259
4260 // If there's a shift operator, handle it.
4261 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004262 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004263 if (Parser.getTok().is(AsmToken::Comma)) {
4264 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004265 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004266 return true;
4267 }
4268
4269 // Now we should have the closing ']'
4270 E = Parser.getTok().getLoc();
4271 if (Parser.getTok().isNot(AsmToken::RBrac))
4272 return Error(E, "']' expected");
4273 Parser.Lex(); // Eat right bracket token.
4274
4275 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004276 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004277 S, E));
4278
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004279 // If there's a pre-indexing writeback marker, '!', just add it as a token
4280 // operand.
4281 if (Parser.getTok().is(AsmToken::Exclaim)) {
4282 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4283 Parser.Lex(); // Eat the '!'.
4284 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004285
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004286 return false;
4287}
4288
Jim Grosbach7ce05792011-08-03 23:50:40 +00004289/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004290/// ( lsl | lsr | asr | ror ) , # shift_amount
4291/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004292/// return true if it parses a shift otherwise it returns false.
4293bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4294 unsigned &Amount) {
4295 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004296 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004297 if (Tok.isNot(AsmToken::Identifier))
4298 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004299 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004300 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4301 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004302 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004303 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004304 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004305 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004306 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004307 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004308 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004309 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004310 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004311 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004312 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004313 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004314
Jim Grosbach7ce05792011-08-03 23:50:40 +00004315 // rrx stands alone.
4316 Amount = 0;
4317 if (St != ARM_AM::rrx) {
4318 Loc = Parser.getTok().getLoc();
4319 // A '#' and a shift amount.
4320 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004321 if (HashTok.isNot(AsmToken::Hash) &&
4322 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004323 return Error(HashTok.getLoc(), "'#' expected");
4324 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004325
Jim Grosbach7ce05792011-08-03 23:50:40 +00004326 const MCExpr *Expr;
4327 if (getParser().ParseExpression(Expr))
4328 return true;
4329 // Range check the immediate.
4330 // lsl, ror: 0 <= imm <= 31
4331 // lsr, asr: 0 <= imm <= 32
4332 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4333 if (!CE)
4334 return Error(Loc, "shift amount must be an immediate");
4335 int64_t Imm = CE->getValue();
4336 if (Imm < 0 ||
4337 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4338 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4339 return Error(Loc, "immediate shift value out of range");
4340 Amount = Imm;
4341 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004342
4343 return false;
4344}
4345
Jim Grosbach9d390362011-10-03 23:38:36 +00004346/// parseFPImm - A floating point immediate expression operand.
4347ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4348parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004349 // Anything that can accept a floating point constant as an operand
4350 // needs to go through here, as the regular ParseExpression is
4351 // integer only.
4352 //
4353 // This routine still creates a generic Immediate operand, containing
4354 // a bitcast of the 64-bit floating point value. The various operands
4355 // that accept floats can check whether the value is valid for them
4356 // via the standard is*() predicates.
4357
Jim Grosbach9d390362011-10-03 23:38:36 +00004358 SMLoc S = Parser.getTok().getLoc();
4359
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004360 if (Parser.getTok().isNot(AsmToken::Hash) &&
4361 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004362 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004363
4364 // Disambiguate the VMOV forms that can accept an FP immediate.
4365 // vmov.f32 <sreg>, #imm
4366 // vmov.f64 <dreg>, #imm
4367 // vmov.f32 <dreg>, #imm @ vector f32x2
4368 // vmov.f32 <qreg>, #imm @ vector f32x4
4369 //
4370 // There are also the NEON VMOV instructions which expect an
4371 // integer constant. Make sure we don't try to parse an FPImm
4372 // for these:
4373 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4374 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4375 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4376 TyOp->getToken() != ".f64"))
4377 return MatchOperand_NoMatch;
4378
Jim Grosbach9d390362011-10-03 23:38:36 +00004379 Parser.Lex(); // Eat the '#'.
4380
4381 // Handle negation, as that still comes through as a separate token.
4382 bool isNegative = false;
4383 if (Parser.getTok().is(AsmToken::Minus)) {
4384 isNegative = true;
4385 Parser.Lex();
4386 }
4387 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004388 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004389 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004390 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004391 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4392 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004393 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004394 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004395 Operands.push_back(ARMOperand::CreateImm(
4396 MCConstantExpr::Create(IntVal, getContext()),
4397 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004398 return MatchOperand_Success;
4399 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004400 // Also handle plain integers. Instructions which allow floating point
4401 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004402 if (Tok.is(AsmToken::Integer)) {
4403 int64_t Val = Tok.getIntVal();
4404 Parser.Lex(); // Eat the token.
4405 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004406 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004407 return MatchOperand_ParseFail;
4408 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004409 double RealVal = ARM_AM::getFPImmFloat(Val);
4410 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4411 Operands.push_back(ARMOperand::CreateImm(
4412 MCConstantExpr::Create(Val, getContext()), S,
4413 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004414 return MatchOperand_Success;
4415 }
4416
Jim Grosbachae69f702012-01-19 02:47:30 +00004417 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004418 return MatchOperand_ParseFail;
4419}
Jim Grosbach51222d12012-01-20 18:09:51 +00004420
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004421/// Parse a arm instruction operand. For now this parses the operand regardless
4422/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004423bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004424 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004425 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004426
4427 // Check if the current operand has a custom associated parser, if so, try to
4428 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004429 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4430 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004431 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004432 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4433 // there was a match, but an error occurred, in which case, just return that
4434 // the operand parsing failed.
4435 if (ResTy == MatchOperand_ParseFail)
4436 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004437
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004438 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004439 default:
4440 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004441 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004442 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004443 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004444 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004445 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004446 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004447 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004448 else if (Res == -1) // irrecoverable error
4449 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004450 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004451 if (Mnemonic == "vmrs" &&
4452 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004453 S = Parser.getTok().getLoc();
4454 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004455 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004456 return false;
4457 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004458
4459 // Fall though for the Identifier case that is not a register or a
4460 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004461 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004462 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004463 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004464 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004465 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004466 // This was not a register so parse other operands that start with an
4467 // identifier (like labels) as expressions and create them as immediates.
4468 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004469 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004470 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004471 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004472 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004473 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4474 return false;
4475 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004476 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004477 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004478 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004479 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004480 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004481 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004482 // #42 -> immediate.
4483 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004484 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004485 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004486 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004487 const MCExpr *ImmVal;
4488 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004489 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004491 if (CE) {
4492 int32_t Val = CE->getValue();
4493 if (isNegative && Val == 0)
4494 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004495 }
Sean Callanan76264762010-04-02 22:27:05 +00004496 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004497 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4498 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004499 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004500 case AsmToken::Colon: {
4501 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004502 // FIXME: Check it's an expression prefix,
4503 // e.g. (FOO - :lower16:BAR) isn't legal.
4504 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004505 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004506 return true;
4507
Evan Cheng75972122011-01-13 07:58:56 +00004508 const MCExpr *SubExprVal;
4509 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004510 return true;
4511
Evan Cheng75972122011-01-13 07:58:56 +00004512 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4513 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004514 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004515 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004516 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004517 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004518 }
4519}
4520
Jim Grosbach1355cf12011-07-26 17:10:22 +00004521// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004522// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004523bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004524 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004525
4526 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004527 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004528 Parser.Lex(); // Eat ':'
4529
4530 if (getLexer().isNot(AsmToken::Identifier)) {
4531 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4532 return true;
4533 }
4534
4535 StringRef IDVal = Parser.getTok().getIdentifier();
4536 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004537 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004538 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004539 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004540 } else {
4541 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4542 return true;
4543 }
4544 Parser.Lex();
4545
4546 if (getLexer().isNot(AsmToken::Colon)) {
4547 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4548 return true;
4549 }
4550 Parser.Lex(); // Eat the last ':'
4551 return false;
4552}
4553
Daniel Dunbar352e1482011-01-11 15:59:50 +00004554/// \brief Given a mnemonic, split out possible predication code and carry
4555/// setting letters to form a canonical mnemonic and flags.
4556//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004557// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004558// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004559StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004560 unsigned &PredicationCode,
4561 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004562 unsigned &ProcessorIMod,
4563 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004564 PredicationCode = ARMCC::AL;
4565 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004566 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004567
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004568 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004569 //
4570 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004571 if ((Mnemonic == "movs" && isThumb()) ||
4572 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4573 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4574 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4575 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4576 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4577 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004578 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4579 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004580 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004581
Jim Grosbach3f00e312011-07-11 17:09:57 +00004582 // First, split out any predication code. Ignore mnemonics we know aren't
4583 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004584 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004585 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004586 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004587 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004588 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4589 .Case("eq", ARMCC::EQ)
4590 .Case("ne", ARMCC::NE)
4591 .Case("hs", ARMCC::HS)
4592 .Case("cs", ARMCC::HS)
4593 .Case("lo", ARMCC::LO)
4594 .Case("cc", ARMCC::LO)
4595 .Case("mi", ARMCC::MI)
4596 .Case("pl", ARMCC::PL)
4597 .Case("vs", ARMCC::VS)
4598 .Case("vc", ARMCC::VC)
4599 .Case("hi", ARMCC::HI)
4600 .Case("ls", ARMCC::LS)
4601 .Case("ge", ARMCC::GE)
4602 .Case("lt", ARMCC::LT)
4603 .Case("gt", ARMCC::GT)
4604 .Case("le", ARMCC::LE)
4605 .Case("al", ARMCC::AL)
4606 .Default(~0U);
4607 if (CC != ~0U) {
4608 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4609 PredicationCode = CC;
4610 }
Bill Wendling52925b62010-10-29 23:50:21 +00004611 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004612
Daniel Dunbar352e1482011-01-11 15:59:50 +00004613 // Next, determine if we have a carry setting bit. We explicitly ignore all
4614 // the instructions we know end in 's'.
4615 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004616 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004617 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4618 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4619 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004620 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004621 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004622 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004623 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004624 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004625 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4626 CarrySetting = true;
4627 }
4628
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004629 // The "cps" instruction can have a interrupt mode operand which is glued into
4630 // the mnemonic. Check if this is the case, split it and parse the imod op
4631 if (Mnemonic.startswith("cps")) {
4632 // Split out any imod code.
4633 unsigned IMod =
4634 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4635 .Case("ie", ARM_PROC::IE)
4636 .Case("id", ARM_PROC::ID)
4637 .Default(~0U);
4638 if (IMod != ~0U) {
4639 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4640 ProcessorIMod = IMod;
4641 }
4642 }
4643
Jim Grosbach89df9962011-08-26 21:43:41 +00004644 // The "it" instruction has the condition mask on the end of the mnemonic.
4645 if (Mnemonic.startswith("it")) {
4646 ITMask = Mnemonic.slice(2, Mnemonic.size());
4647 Mnemonic = Mnemonic.slice(0, 2);
4648 }
4649
Daniel Dunbar352e1482011-01-11 15:59:50 +00004650 return Mnemonic;
4651}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004652
4653/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4654/// inclusion of carry set or predication code operands.
4655//
4656// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004657void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004658getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004659 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004660 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4661 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004662 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004663 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004664 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004665 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004666 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004667 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004668 Mnemonic == "mla" || Mnemonic == "smlal" ||
4669 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004670 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004671 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004672 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004673
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004674 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4675 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4676 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4677 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004678 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4679 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004680 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004681 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4682 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4683 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004684 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4685 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004686 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004687 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004688 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004689 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004690
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004691 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004692 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004693 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004694 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004695 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004696}
4697
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004698bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4699 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004700 // FIXME: This is all horribly hacky. We really need a better way to deal
4701 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004702
4703 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4704 // another does not. Specifically, the MOVW instruction does not. So we
4705 // special case it here and remove the defaulted (non-setting) cc_out
4706 // operand if that's the instruction we're trying to match.
4707 //
4708 // We do this as post-processing of the explicit operands rather than just
4709 // conditionally adding the cc_out in the first place because we need
4710 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004711 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004712 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4713 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4714 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4715 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004716
4717 // Register-register 'add' for thumb does not have a cc_out operand
4718 // when there are only two register operands.
4719 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4720 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4721 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4722 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4723 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004724 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004725 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4726 // have to check the immediate range here since Thumb2 has a variant
4727 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004728 if (((isThumb() && Mnemonic == "add") ||
4729 (isThumbTwo() && Mnemonic == "sub")) &&
4730 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004731 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4732 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4733 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004734 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4735 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4736 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004737 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004738 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4739 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004740 // selecting via the generic "add" mnemonic, so to know that we
4741 // should remove the cc_out operand, we have to explicitly check that
4742 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004743 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4744 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004745 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4746 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4747 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4748 // Nest conditions rather than one big 'if' statement for readability.
4749 //
4750 // If either register is a high reg, it's either one of the SP
4751 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004752 // check against T3. If the second register is the PC, this is an
4753 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004754 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4755 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004756 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004757 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4758 return false;
4759 // If both registers are low, we're in an IT block, and the immediate is
4760 // in range, we should use encoding T1 instead, which has a cc_out.
4761 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004762 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004763 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4764 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4765 return false;
4766
4767 // Otherwise, we use encoding T4, which does not have a cc_out
4768 // operand.
4769 return true;
4770 }
4771
Jim Grosbach64944f42011-09-14 21:00:40 +00004772 // The thumb2 multiply instruction doesn't have a CCOut register, so
4773 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4774 // use the 16-bit encoding or not.
4775 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4776 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4777 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4778 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4779 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4780 // If the registers aren't low regs, the destination reg isn't the
4781 // same as one of the source regs, or the cc_out operand is zero
4782 // outside of an IT block, we have to use the 32-bit encoding, so
4783 // remove the cc_out operand.
4784 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4785 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004786 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004787 !inITBlock() ||
4788 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4789 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4790 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4791 static_cast<ARMOperand*>(Operands[4])->getReg())))
4792 return true;
4793
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004794 // Also check the 'mul' syntax variant that doesn't specify an explicit
4795 // destination register.
4796 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4797 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4798 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4799 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4800 // If the registers aren't low regs or the cc_out operand is zero
4801 // outside of an IT block, we have to use the 32-bit encoding, so
4802 // remove the cc_out operand.
4803 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4804 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4805 !inITBlock()))
4806 return true;
4807
Jim Grosbach64944f42011-09-14 21:00:40 +00004808
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004809
Jim Grosbachf69c8042011-08-24 21:42:27 +00004810 // Register-register 'add/sub' for thumb does not have a cc_out operand
4811 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4812 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4813 // right, this will result in better diagnostics (which operand is off)
4814 // anyway.
4815 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4816 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004817 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4818 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4819 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4820 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004821
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004822 return false;
4823}
4824
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004825static bool isDataTypeToken(StringRef Tok) {
4826 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4827 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4828 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4829 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4830 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4831 Tok == ".f" || Tok == ".d";
4832}
4833
4834// FIXME: This bit should probably be handled via an explicit match class
4835// in the .td files that matches the suffix instead of having it be
4836// a literal string token the way it is now.
4837static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4838 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4839}
4840
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004841static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004842/// Parse an arm instruction mnemonic followed by its operands.
4843bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4844 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004845 // Apply mnemonic aliases before doing anything else, as the destination
4846 // mnemnonic may include suffices and we want to handle them normally.
4847 // The generic tblgen'erated code does this later, at the start of
4848 // MatchInstructionImpl(), but that's too late for aliases that include
4849 // any sort of suffix.
4850 unsigned AvailableFeatures = getAvailableFeatures();
4851 applyMnemonicAliases(Name, AvailableFeatures);
4852
Jim Grosbacha39cda72011-12-14 02:16:11 +00004853 // First check for the ARM-specific .req directive.
4854 if (Parser.getTok().is(AsmToken::Identifier) &&
4855 Parser.getTok().getIdentifier() == ".req") {
4856 parseDirectiveReq(Name, NameLoc);
4857 // We always return 'error' for this, as we're done with this
4858 // statement and don't need to match the 'instruction."
4859 return true;
4860 }
4861
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004862 // Create the leading tokens for the mnemonic, split by '.' characters.
4863 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004864 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004865
Daniel Dunbar352e1482011-01-11 15:59:50 +00004866 // Split out the predication code and carry setting flag from the mnemonic.
4867 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004868 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004869 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004870 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004871 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004872 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004873
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004874 // In Thumb1, only the branch (B) instruction can be predicated.
4875 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4876 Parser.EatToEndOfStatement();
4877 return Error(NameLoc, "conditional execution not supported in Thumb1");
4878 }
4879
Jim Grosbachffa32252011-07-19 19:13:28 +00004880 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4881
Jim Grosbach89df9962011-08-26 21:43:41 +00004882 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4883 // is the mask as it will be for the IT encoding if the conditional
4884 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4885 // where the conditional bit0 is zero, the instruction post-processing
4886 // will adjust the mask accordingly.
4887 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004888 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4889 if (ITMask.size() > 3) {
4890 Parser.EatToEndOfStatement();
4891 return Error(Loc, "too many conditions on IT instruction");
4892 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004893 unsigned Mask = 8;
4894 for (unsigned i = ITMask.size(); i != 0; --i) {
4895 char pos = ITMask[i - 1];
4896 if (pos != 't' && pos != 'e') {
4897 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004898 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004899 }
4900 Mask >>= 1;
4901 if (ITMask[i - 1] == 't')
4902 Mask |= 8;
4903 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004904 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004905 }
4906
Jim Grosbachffa32252011-07-19 19:13:28 +00004907 // FIXME: This is all a pretty gross hack. We should automatically handle
4908 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004909
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004910 // Next, add the CCOut and ConditionCode operands, if needed.
4911 //
4912 // For mnemonics which can ever incorporate a carry setting bit or predication
4913 // code, our matching model involves us always generating CCOut and
4914 // ConditionCode operands to match the mnemonic "as written" and then we let
4915 // the matcher deal with finding the right instruction or generating an
4916 // appropriate error.
4917 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004918 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004919
Jim Grosbach33c16a22011-07-14 22:04:21 +00004920 // If we had a carry-set on an instruction that can't do that, issue an
4921 // error.
4922 if (!CanAcceptCarrySet && CarrySetting) {
4923 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004924 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004925 "' can not set flags, but 's' suffix specified");
4926 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004927 // If we had a predication code on an instruction that can't do that, issue an
4928 // error.
4929 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4930 Parser.EatToEndOfStatement();
4931 return Error(NameLoc, "instruction '" + Mnemonic +
4932 "' is not predicable, but condition code specified");
4933 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004934
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004935 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004936 if (CanAcceptCarrySet) {
4937 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004938 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004939 Loc));
4940 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004941
4942 // Add the predication code operand, if necessary.
4943 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004944 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4945 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004946 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004947 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004948 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004949
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004950 // Add the processor imod operand, if necessary.
4951 if (ProcessorIMod) {
4952 Operands.push_back(ARMOperand::CreateImm(
4953 MCConstantExpr::Create(ProcessorIMod, getContext()),
4954 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004955 }
4956
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004957 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004958 while (Next != StringRef::npos) {
4959 Start = Next;
4960 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004961 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004962
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004963 // Some NEON instructions have an optional datatype suffix that is
4964 // completely ignored. Check for that.
4965 if (isDataTypeToken(ExtraToken) &&
4966 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4967 continue;
4968
Jim Grosbach81d2e392011-09-07 16:06:04 +00004969 if (ExtraToken != ".n") {
4970 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4971 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4972 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004973 }
4974
4975 // Read the remaining operands.
4976 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004977 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004978 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004979 Parser.EatToEndOfStatement();
4980 return true;
4981 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004982
4983 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004984 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004985
4986 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004987 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004988 Parser.EatToEndOfStatement();
4989 return true;
4990 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004991 }
4992 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004993
Chris Lattnercbf8a982010-09-11 16:18:25 +00004994 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004995 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004996 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004997 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004998 }
Bill Wendling146018f2010-11-06 21:42:12 +00004999
Chris Lattner34e53142010-09-08 05:10:46 +00005000 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00005001
Jim Grosbachd54b4e62011-08-16 21:12:37 +00005002 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5003 // do and don't have a cc_out optional-def operand. With some spot-checks
5004 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005005 // parse and adjust accordingly before actually matching. We shouldn't ever
5006 // try to remove a cc_out operand that was explicitly set on the the
5007 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5008 // table driven matcher doesn't fit well with the ARM instruction set.
5009 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005010 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5011 Operands.erase(Operands.begin() + 1);
5012 delete Op;
5013 }
5014
Jim Grosbachcf121c32011-07-28 21:57:55 +00005015 // ARM mode 'blx' need special handling, as the register operand version
5016 // is predicable, but the label operand version is not. So, we can't rely
5017 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005018 // a k_CondCode operand in the list. If we're trying to match the label
5019 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005020 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5021 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5022 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5023 Operands.erase(Operands.begin() + 1);
5024 delete Op;
5025 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005026
5027 // The vector-compare-to-zero instructions have a literal token "#0" at
5028 // the end that comes to here as an immediate operand. Convert it to a
5029 // token to play nicely with the matcher.
5030 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5031 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5032 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5033 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5034 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5035 if (CE && CE->getValue() == 0) {
5036 Operands.erase(Operands.begin() + 5);
5037 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5038 delete Op;
5039 }
5040 }
Jim Grosbach68259142011-10-03 22:30:24 +00005041 // VCMP{E} does the same thing, but with a different operand count.
5042 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5043 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5044 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5046 if (CE && CE->getValue() == 0) {
5047 Operands.erase(Operands.begin() + 4);
5048 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5049 delete Op;
5050 }
5051 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005052 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005053 // end. Convert it to a token here. Take care not to convert those
5054 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005055 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005056 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5057 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005058 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5059 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5060 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005061 if (CE && CE->getValue() == 0 &&
5062 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005063 // The cc_out operand matches the IT block.
5064 ((inITBlock() != CarrySetting) &&
5065 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005066 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005067 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005068 Operands.erase(Operands.begin() + 5);
5069 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5070 delete Op;
5071 }
5072 }
5073
Chris Lattner98986712010-01-14 22:21:20 +00005074 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005075}
5076
Jim Grosbach189610f2011-07-26 18:25:39 +00005077// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005078
5079// return 'true' if register list contains non-low GPR registers,
5080// 'false' otherwise. If Reg is in the register list or is HiReg, set
5081// 'containsReg' to true.
5082static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5083 unsigned HiReg, bool &containsReg) {
5084 containsReg = false;
5085 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5086 unsigned OpReg = Inst.getOperand(i).getReg();
5087 if (OpReg == Reg)
5088 containsReg = true;
5089 // Anything other than a low register isn't legal here.
5090 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5091 return true;
5092 }
5093 return false;
5094}
5095
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005096// Check if the specified regisgter is in the register list of the inst,
5097// starting at the indicated operand number.
5098static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5099 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5100 unsigned OpReg = Inst.getOperand(i).getReg();
5101 if (OpReg == Reg)
5102 return true;
5103 }
5104 return false;
5105}
5106
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005107// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5108// the ARMInsts array) instead. Getting that here requires awkward
5109// API changes, though. Better way?
5110namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005111extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005112}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005113static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005114 return ARMInsts[Opcode];
5115}
5116
Jim Grosbach189610f2011-07-26 18:25:39 +00005117// FIXME: We would really like to be able to tablegen'erate this.
5118bool ARMAsmParser::
5119validateInstruction(MCInst &Inst,
5120 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005121 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005122 SMLoc Loc = Operands[0]->getStartLoc();
5123 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005124 // NOTE: BKPT instruction has the interesting property of being
5125 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005126 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005127 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5128 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005129 unsigned bit = 1;
5130 if (ITState.FirstCond)
5131 ITState.FirstCond = false;
5132 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005133 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005134 // The instruction must be predicable.
5135 if (!MCID.isPredicable())
5136 return Error(Loc, "instructions in IT block must be predicable");
5137 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5138 unsigned ITCond = bit ? ITState.Cond :
5139 ARMCC::getOppositeCondition(ITState.Cond);
5140 if (Cond != ITCond) {
5141 // Find the condition code Operand to get its SMLoc information.
5142 SMLoc CondLoc;
5143 for (unsigned i = 1; i < Operands.size(); ++i)
5144 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5145 CondLoc = Operands[i]->getStartLoc();
5146 return Error(CondLoc, "incorrect condition in IT block; got '" +
5147 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5148 "', but expected '" +
5149 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5150 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005151 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005152 } else if (isThumbTwo() && MCID.isPredicable() &&
5153 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005154 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5155 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005156 return Error(Loc, "predicated instructions must be in IT block");
5157
Jim Grosbach189610f2011-07-26 18:25:39 +00005158 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005159 case ARM::LDRD:
5160 case ARM::LDRD_PRE:
5161 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005162 case ARM::LDREXD: {
5163 // Rt2 must be Rt + 1.
5164 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5165 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5166 if (Rt2 != Rt + 1)
5167 return Error(Operands[3]->getStartLoc(),
5168 "destination operands must be sequential");
5169 return false;
5170 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005171 case ARM::STRD: {
5172 // Rt2 must be Rt + 1.
5173 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5174 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5175 if (Rt2 != Rt + 1)
5176 return Error(Operands[3]->getStartLoc(),
5177 "source operands must be sequential");
5178 return false;
5179 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005180 case ARM::STRD_PRE:
5181 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005182 case ARM::STREXD: {
5183 // Rt2 must be Rt + 1.
5184 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5185 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5186 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005187 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005188 "source operands must be sequential");
5189 return false;
5190 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005191 case ARM::SBFX:
5192 case ARM::UBFX: {
5193 // width must be in range [1, 32-lsb]
5194 unsigned lsb = Inst.getOperand(2).getImm();
5195 unsigned widthm1 = Inst.getOperand(3).getImm();
5196 if (widthm1 >= 32 - lsb)
5197 return Error(Operands[5]->getStartLoc(),
5198 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005199 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005200 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005201 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005202 // If we're parsing Thumb2, the .w variant is available and handles
5203 // most cases that are normally illegal for a Thumb1 LDM
5204 // instruction. We'll make the transformation in processInstruction()
5205 // if necessary.
5206 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005207 // Thumb LDM instructions are writeback iff the base register is not
5208 // in the register list.
5209 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005210 bool hasWritebackToken =
5211 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5212 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005213 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005214 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005215 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5216 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005217 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005218 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005219 return Error(Operands[2]->getStartLoc(),
5220 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005221 // If we should not have writeback, there must not be a '!'. This is
5222 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005223 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005224 return Error(Operands[3]->getStartLoc(),
5225 "writeback operator '!' not allowed when base register "
5226 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005227
5228 break;
5229 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005230 case ARM::t2LDMIA_UPD: {
5231 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5232 return Error(Operands[4]->getStartLoc(),
5233 "writeback operator '!' not allowed when base register "
5234 "in register list");
5235 break;
5236 }
Jim Grosbach54026372011-11-10 23:17:11 +00005237 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5238 // so only issue a diagnostic for thumb1. The instructions will be
5239 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005240 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005241 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005242 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5243 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005244 return Error(Operands[2]->getStartLoc(),
5245 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005246 break;
5247 }
5248 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005249 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005250 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5251 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005252 return Error(Operands[2]->getStartLoc(),
5253 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005254 break;
5255 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005256 case ARM::tSTMIA_UPD: {
5257 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005258 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005259 return Error(Operands[4]->getStartLoc(),
5260 "registers must be in range r0-r7");
5261 break;
5262 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005263 }
5264
5265 return false;
5266}
5267
Jim Grosbachd7433e22012-01-23 23:45:44 +00005268static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005269 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005270 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005271 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005272 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5273 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5274 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5275 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5276 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5277 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5278 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5279 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5280 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005281
5282 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005283 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5284 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5285 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5286 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5287 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005288
Jim Grosbach7945ead2012-01-24 00:43:12 +00005289 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5290 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5291 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5292 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5293 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005294
Jim Grosbach7945ead2012-01-24 00:43:12 +00005295 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5296 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5297 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5298 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5299 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005300
Jim Grosbach4adb1822012-01-24 00:07:41 +00005301 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005302 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5303 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5304 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5305 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5306 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5307 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5308 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5309 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5310 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5311 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5312 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5313 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5314 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5315 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5316 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005317
Jim Grosbachd7433e22012-01-23 23:45:44 +00005318 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005319 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5320 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5321 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5322 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5323 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5324 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5325 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5326 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5327 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5328 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5329 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5330 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5331 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5332 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5333 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5334 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5335 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5336 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005337
Jim Grosbach88a54de2012-01-24 18:53:13 +00005338 // VST4LN
5339 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5340 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5341 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5342 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5343 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5344 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5345 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5346 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5347 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5348 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5349 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5350 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5351 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5352 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5353 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5354
Jim Grosbach539aab72012-01-24 00:58:13 +00005355 // VST4
5356 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5357 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5358 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5359 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5360 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5361 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5362 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5363 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5364 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5365 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5366 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5367 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5368 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5369 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5370 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5371 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5372 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5373 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005374 }
5375}
5376
Jim Grosbachd7433e22012-01-23 23:45:44 +00005377static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005378 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005379 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005380 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005381 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5382 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5383 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5384 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5385 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5386 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5387 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5388 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5389 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005390
5391 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005392 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5393 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5394 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5395 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5396 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5397 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5398 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5399 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5400 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5401 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5402 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5403 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5404 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5405 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5406 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005407
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005408 // VLD3DUP
5409 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5410 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5411 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5412 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5413 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5414 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5415 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5416 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5417 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5418 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5419 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5420 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5421 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5422 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5423 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5424 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5425 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5426 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5427
Jim Grosbach3a678af2012-01-23 21:53:26 +00005428 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005429 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5430 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5431 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5432 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5433 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5434 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5435 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5436 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5437 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5438 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5439 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5440 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5441 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5442 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5443 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005444
5445 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005446 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5447 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5448 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5449 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5450 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5451 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5452 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5453 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5454 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5455 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5456 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5457 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5458 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5459 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5460 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5461 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5462 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5463 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005464
Jim Grosbache983a132012-01-24 18:37:25 +00005465 // VLD4LN
5466 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5467 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5468 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5469 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5470 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5471 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5472 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5473 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5474 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5475 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5476 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5477 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5478 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5479 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5480 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5481
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005482 // VLD4DUP
5483 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5484 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5485 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5486 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5487 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5488 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5489 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5490 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5491 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5492 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5493 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5494 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5495 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5496 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5497 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5498 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5499 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5500 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5501
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005502 // VLD4
5503 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5504 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5505 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5506 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5507 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5508 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5509 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5510 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5511 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5512 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5513 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5514 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5515 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5516 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5517 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5518 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5519 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5520 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005521 }
5522}
5523
Jim Grosbach83ec8772011-11-10 23:42:14 +00005524bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005525processInstruction(MCInst &Inst,
5526 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5527 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005528 // Aliases for alternate PC+imm syntax of LDR instructions.
5529 case ARM::t2LDRpcrel:
5530 Inst.setOpcode(ARM::t2LDRpci);
5531 return true;
5532 case ARM::t2LDRBpcrel:
5533 Inst.setOpcode(ARM::t2LDRBpci);
5534 return true;
5535 case ARM::t2LDRHpcrel:
5536 Inst.setOpcode(ARM::t2LDRHpci);
5537 return true;
5538 case ARM::t2LDRSBpcrel:
5539 Inst.setOpcode(ARM::t2LDRSBpci);
5540 return true;
5541 case ARM::t2LDRSHpcrel:
5542 Inst.setOpcode(ARM::t2LDRSHpci);
5543 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005544 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005545 case ARM::VST1LNdWB_register_Asm_8:
5546 case ARM::VST1LNdWB_register_Asm_16:
5547 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005548 MCInst TmpInst;
5549 // Shuffle the operands around so the lane index operand is in the
5550 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005551 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005552 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005553 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5554 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5555 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5556 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5557 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5558 TmpInst.addOperand(Inst.getOperand(1)); // lane
5559 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5560 TmpInst.addOperand(Inst.getOperand(6));
5561 Inst = TmpInst;
5562 return true;
5563 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005564
Jim Grosbach8b31f952012-01-23 19:39:08 +00005565 case ARM::VST2LNdWB_register_Asm_8:
5566 case ARM::VST2LNdWB_register_Asm_16:
5567 case ARM::VST2LNdWB_register_Asm_32:
5568 case ARM::VST2LNqWB_register_Asm_16:
5569 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005570 MCInst TmpInst;
5571 // Shuffle the operands around so the lane index operand is in the
5572 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005573 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005574 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005575 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5576 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5577 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5578 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5579 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005580 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5581 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005582 TmpInst.addOperand(Inst.getOperand(1)); // lane
5583 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5584 TmpInst.addOperand(Inst.getOperand(6));
5585 Inst = TmpInst;
5586 return true;
5587 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005588
5589 case ARM::VST3LNdWB_register_Asm_8:
5590 case ARM::VST3LNdWB_register_Asm_16:
5591 case ARM::VST3LNdWB_register_Asm_32:
5592 case ARM::VST3LNqWB_register_Asm_16:
5593 case ARM::VST3LNqWB_register_Asm_32: {
5594 MCInst TmpInst;
5595 // Shuffle the operands around so the lane index operand is in the
5596 // right place.
5597 unsigned Spacing;
5598 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5599 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5600 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5601 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5602 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5603 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5604 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5605 Spacing));
5606 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5607 Spacing * 2));
5608 TmpInst.addOperand(Inst.getOperand(1)); // lane
5609 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5610 TmpInst.addOperand(Inst.getOperand(6));
5611 Inst = TmpInst;
5612 return true;
5613 }
5614
Jim Grosbach88a54de2012-01-24 18:53:13 +00005615 case ARM::VST4LNdWB_register_Asm_8:
5616 case ARM::VST4LNdWB_register_Asm_16:
5617 case ARM::VST4LNdWB_register_Asm_32:
5618 case ARM::VST4LNqWB_register_Asm_16:
5619 case ARM::VST4LNqWB_register_Asm_32: {
5620 MCInst TmpInst;
5621 // Shuffle the operands around so the lane index operand is in the
5622 // right place.
5623 unsigned Spacing;
5624 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5625 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5626 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5627 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5628 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5629 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5630 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5631 Spacing));
5632 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5633 Spacing * 2));
5634 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5635 Spacing * 3));
5636 TmpInst.addOperand(Inst.getOperand(1)); // lane
5637 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5638 TmpInst.addOperand(Inst.getOperand(6));
5639 Inst = TmpInst;
5640 return true;
5641 }
5642
Jim Grosbach8b31f952012-01-23 19:39:08 +00005643 case ARM::VST1LNdWB_fixed_Asm_8:
5644 case ARM::VST1LNdWB_fixed_Asm_16:
5645 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005646 MCInst TmpInst;
5647 // Shuffle the operands around so the lane index operand is in the
5648 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005649 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005650 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005651 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5652 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5653 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5654 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5655 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5656 TmpInst.addOperand(Inst.getOperand(1)); // lane
5657 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5658 TmpInst.addOperand(Inst.getOperand(5));
5659 Inst = TmpInst;
5660 return true;
5661 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005662
Jim Grosbach8b31f952012-01-23 19:39:08 +00005663 case ARM::VST2LNdWB_fixed_Asm_8:
5664 case ARM::VST2LNdWB_fixed_Asm_16:
5665 case ARM::VST2LNdWB_fixed_Asm_32:
5666 case ARM::VST2LNqWB_fixed_Asm_16:
5667 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005668 MCInst TmpInst;
5669 // Shuffle the operands around so the lane index operand is in the
5670 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005671 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005672 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005673 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5674 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5675 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5676 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5677 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005678 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5679 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005680 TmpInst.addOperand(Inst.getOperand(1)); // lane
5681 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5682 TmpInst.addOperand(Inst.getOperand(5));
5683 Inst = TmpInst;
5684 return true;
5685 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005686
5687 case ARM::VST3LNdWB_fixed_Asm_8:
5688 case ARM::VST3LNdWB_fixed_Asm_16:
5689 case ARM::VST3LNdWB_fixed_Asm_32:
5690 case ARM::VST3LNqWB_fixed_Asm_16:
5691 case ARM::VST3LNqWB_fixed_Asm_32: {
5692 MCInst TmpInst;
5693 // Shuffle the operands around so the lane index operand is in the
5694 // right place.
5695 unsigned Spacing;
5696 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5697 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5698 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5699 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5700 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5701 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5702 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5703 Spacing));
5704 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5705 Spacing * 2));
5706 TmpInst.addOperand(Inst.getOperand(1)); // lane
5707 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5708 TmpInst.addOperand(Inst.getOperand(5));
5709 Inst = TmpInst;
5710 return true;
5711 }
5712
Jim Grosbach88a54de2012-01-24 18:53:13 +00005713 case ARM::VST4LNdWB_fixed_Asm_8:
5714 case ARM::VST4LNdWB_fixed_Asm_16:
5715 case ARM::VST4LNdWB_fixed_Asm_32:
5716 case ARM::VST4LNqWB_fixed_Asm_16:
5717 case ARM::VST4LNqWB_fixed_Asm_32: {
5718 MCInst TmpInst;
5719 // Shuffle the operands around so the lane index operand is in the
5720 // right place.
5721 unsigned Spacing;
5722 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5723 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5724 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5725 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5726 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5727 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5728 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5729 Spacing));
5730 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5731 Spacing * 2));
5732 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5733 Spacing * 3));
5734 TmpInst.addOperand(Inst.getOperand(1)); // lane
5735 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5736 TmpInst.addOperand(Inst.getOperand(5));
5737 Inst = TmpInst;
5738 return true;
5739 }
5740
Jim Grosbach8b31f952012-01-23 19:39:08 +00005741 case ARM::VST1LNdAsm_8:
5742 case ARM::VST1LNdAsm_16:
5743 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005744 MCInst TmpInst;
5745 // Shuffle the operands around so the lane index operand is in the
5746 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005747 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005748 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005749 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5750 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5751 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5752 TmpInst.addOperand(Inst.getOperand(1)); // lane
5753 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5754 TmpInst.addOperand(Inst.getOperand(5));
5755 Inst = TmpInst;
5756 return true;
5757 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005758
Jim Grosbach8b31f952012-01-23 19:39:08 +00005759 case ARM::VST2LNdAsm_8:
5760 case ARM::VST2LNdAsm_16:
5761 case ARM::VST2LNdAsm_32:
5762 case ARM::VST2LNqAsm_16:
5763 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005764 MCInst TmpInst;
5765 // Shuffle the operands around so the lane index operand is in the
5766 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005767 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005768 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005769 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5770 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5771 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005772 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5773 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005774 TmpInst.addOperand(Inst.getOperand(1)); // lane
5775 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5776 TmpInst.addOperand(Inst.getOperand(5));
5777 Inst = TmpInst;
5778 return true;
5779 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005780
5781 case ARM::VST3LNdAsm_8:
5782 case ARM::VST3LNdAsm_16:
5783 case ARM::VST3LNdAsm_32:
5784 case ARM::VST3LNqAsm_16:
5785 case ARM::VST3LNqAsm_32: {
5786 MCInst TmpInst;
5787 // Shuffle the operands around so the lane index operand is in the
5788 // right place.
5789 unsigned Spacing;
5790 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5791 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5792 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5793 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5794 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5795 Spacing));
5796 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5797 Spacing * 2));
5798 TmpInst.addOperand(Inst.getOperand(1)); // lane
5799 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5800 TmpInst.addOperand(Inst.getOperand(5));
5801 Inst = TmpInst;
5802 return true;
5803 }
5804
Jim Grosbach88a54de2012-01-24 18:53:13 +00005805 case ARM::VST4LNdAsm_8:
5806 case ARM::VST4LNdAsm_16:
5807 case ARM::VST4LNdAsm_32:
5808 case ARM::VST4LNqAsm_16:
5809 case ARM::VST4LNqAsm_32: {
5810 MCInst TmpInst;
5811 // Shuffle the operands around so the lane index operand is in the
5812 // right place.
5813 unsigned Spacing;
5814 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5815 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5816 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5817 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5818 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5819 Spacing));
5820 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5821 Spacing * 2));
5822 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5823 Spacing * 3));
5824 TmpInst.addOperand(Inst.getOperand(1)); // lane
5825 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5826 TmpInst.addOperand(Inst.getOperand(5));
5827 Inst = TmpInst;
5828 return true;
5829 }
5830
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005831 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005832 case ARM::VLD1LNdWB_register_Asm_8:
5833 case ARM::VLD1LNdWB_register_Asm_16:
5834 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005835 MCInst TmpInst;
5836 // Shuffle the operands around so the lane index operand is in the
5837 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005838 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005839 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005840 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5841 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5842 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5843 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5844 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5845 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5846 TmpInst.addOperand(Inst.getOperand(1)); // lane
5847 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5848 TmpInst.addOperand(Inst.getOperand(6));
5849 Inst = TmpInst;
5850 return true;
5851 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005852
Jim Grosbach8b31f952012-01-23 19:39:08 +00005853 case ARM::VLD2LNdWB_register_Asm_8:
5854 case ARM::VLD2LNdWB_register_Asm_16:
5855 case ARM::VLD2LNdWB_register_Asm_32:
5856 case ARM::VLD2LNqWB_register_Asm_16:
5857 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005858 MCInst TmpInst;
5859 // Shuffle the operands around so the lane index operand is in the
5860 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005861 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005862 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005863 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005864 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5865 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005866 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5867 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5868 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5869 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5870 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005871 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5872 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005873 TmpInst.addOperand(Inst.getOperand(1)); // lane
5874 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5875 TmpInst.addOperand(Inst.getOperand(6));
5876 Inst = TmpInst;
5877 return true;
5878 }
5879
Jim Grosbach3a678af2012-01-23 21:53:26 +00005880 case ARM::VLD3LNdWB_register_Asm_8:
5881 case ARM::VLD3LNdWB_register_Asm_16:
5882 case ARM::VLD3LNdWB_register_Asm_32:
5883 case ARM::VLD3LNqWB_register_Asm_16:
5884 case ARM::VLD3LNqWB_register_Asm_32: {
5885 MCInst TmpInst;
5886 // Shuffle the operands around so the lane index operand is in the
5887 // right place.
5888 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005889 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005890 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5891 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5892 Spacing));
5893 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005894 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005895 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5896 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5897 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5898 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5899 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5900 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5901 Spacing));
5902 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005903 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005904 TmpInst.addOperand(Inst.getOperand(1)); // lane
5905 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5906 TmpInst.addOperand(Inst.getOperand(6));
5907 Inst = TmpInst;
5908 return true;
5909 }
5910
Jim Grosbache983a132012-01-24 18:37:25 +00005911 case ARM::VLD4LNdWB_register_Asm_8:
5912 case ARM::VLD4LNdWB_register_Asm_16:
5913 case ARM::VLD4LNdWB_register_Asm_32:
5914 case ARM::VLD4LNqWB_register_Asm_16:
5915 case ARM::VLD4LNqWB_register_Asm_32: {
5916 MCInst TmpInst;
5917 // Shuffle the operands around so the lane index operand is in the
5918 // right place.
5919 unsigned Spacing;
5920 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5921 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5922 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5923 Spacing));
5924 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5925 Spacing * 2));
5926 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5927 Spacing * 3));
5928 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5929 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5930 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5931 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5932 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5933 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5934 Spacing));
5935 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5936 Spacing * 2));
5937 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5938 Spacing * 3));
5939 TmpInst.addOperand(Inst.getOperand(1)); // lane
5940 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5941 TmpInst.addOperand(Inst.getOperand(6));
5942 Inst = TmpInst;
5943 return true;
5944 }
5945
Jim Grosbach8b31f952012-01-23 19:39:08 +00005946 case ARM::VLD1LNdWB_fixed_Asm_8:
5947 case ARM::VLD1LNdWB_fixed_Asm_16:
5948 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005949 MCInst TmpInst;
5950 // Shuffle the operands around so the lane index operand is in the
5951 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005952 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005953 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005954 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5955 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5956 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5957 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5958 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5959 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5960 TmpInst.addOperand(Inst.getOperand(1)); // lane
5961 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5962 TmpInst.addOperand(Inst.getOperand(5));
5963 Inst = TmpInst;
5964 return true;
5965 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005966
Jim Grosbach8b31f952012-01-23 19:39:08 +00005967 case ARM::VLD2LNdWB_fixed_Asm_8:
5968 case ARM::VLD2LNdWB_fixed_Asm_16:
5969 case ARM::VLD2LNdWB_fixed_Asm_32:
5970 case ARM::VLD2LNqWB_fixed_Asm_16:
5971 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005972 MCInst TmpInst;
5973 // Shuffle the operands around so the lane index operand is in the
5974 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005975 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005976 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005977 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005978 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5979 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005980 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5981 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5982 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5983 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5984 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005985 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5986 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005987 TmpInst.addOperand(Inst.getOperand(1)); // lane
5988 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5989 TmpInst.addOperand(Inst.getOperand(5));
5990 Inst = TmpInst;
5991 return true;
5992 }
5993
Jim Grosbach3a678af2012-01-23 21:53:26 +00005994 case ARM::VLD3LNdWB_fixed_Asm_8:
5995 case ARM::VLD3LNdWB_fixed_Asm_16:
5996 case ARM::VLD3LNdWB_fixed_Asm_32:
5997 case ARM::VLD3LNqWB_fixed_Asm_16:
5998 case ARM::VLD3LNqWB_fixed_Asm_32: {
5999 MCInst TmpInst;
6000 // Shuffle the operands around so the lane index operand is in the
6001 // right place.
6002 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006003 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006004 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6005 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6006 Spacing));
6007 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006008 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006009 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6010 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6011 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6012 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6013 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6014 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6015 Spacing));
6016 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006017 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006018 TmpInst.addOperand(Inst.getOperand(1)); // lane
6019 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6020 TmpInst.addOperand(Inst.getOperand(5));
6021 Inst = TmpInst;
6022 return true;
6023 }
6024
Jim Grosbache983a132012-01-24 18:37:25 +00006025 case ARM::VLD4LNdWB_fixed_Asm_8:
6026 case ARM::VLD4LNdWB_fixed_Asm_16:
6027 case ARM::VLD4LNdWB_fixed_Asm_32:
6028 case ARM::VLD4LNqWB_fixed_Asm_16:
6029 case ARM::VLD4LNqWB_fixed_Asm_32: {
6030 MCInst TmpInst;
6031 // Shuffle the operands around so the lane index operand is in the
6032 // right place.
6033 unsigned Spacing;
6034 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6035 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6036 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6037 Spacing));
6038 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6039 Spacing * 2));
6040 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6041 Spacing * 3));
6042 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6043 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6044 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6045 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6046 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6047 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6048 Spacing));
6049 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6050 Spacing * 2));
6051 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6052 Spacing * 3));
6053 TmpInst.addOperand(Inst.getOperand(1)); // lane
6054 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6055 TmpInst.addOperand(Inst.getOperand(5));
6056 Inst = TmpInst;
6057 return true;
6058 }
6059
Jim Grosbach8b31f952012-01-23 19:39:08 +00006060 case ARM::VLD1LNdAsm_8:
6061 case ARM::VLD1LNdAsm_16:
6062 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006063 MCInst TmpInst;
6064 // Shuffle the operands around so the lane index operand is in the
6065 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006066 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006067 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006068 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6069 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6070 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6071 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6072 TmpInst.addOperand(Inst.getOperand(1)); // lane
6073 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6074 TmpInst.addOperand(Inst.getOperand(5));
6075 Inst = TmpInst;
6076 return true;
6077 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006078
Jim Grosbach8b31f952012-01-23 19:39:08 +00006079 case ARM::VLD2LNdAsm_8:
6080 case ARM::VLD2LNdAsm_16:
6081 case ARM::VLD2LNdAsm_32:
6082 case ARM::VLD2LNqAsm_16:
6083 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006084 MCInst TmpInst;
6085 // Shuffle the operands around so the lane index operand is in the
6086 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006087 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006088 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006089 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006090 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6091 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006092 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6093 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6094 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006095 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6096 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006097 TmpInst.addOperand(Inst.getOperand(1)); // lane
6098 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6099 TmpInst.addOperand(Inst.getOperand(5));
6100 Inst = TmpInst;
6101 return true;
6102 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006103
6104 case ARM::VLD3LNdAsm_8:
6105 case ARM::VLD3LNdAsm_16:
6106 case ARM::VLD3LNdAsm_32:
6107 case ARM::VLD3LNqAsm_16:
6108 case ARM::VLD3LNqAsm_32: {
6109 MCInst TmpInst;
6110 // Shuffle the operands around so the lane index operand is in the
6111 // right place.
6112 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006113 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006114 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6115 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6116 Spacing));
6117 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006118 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006119 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6120 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6121 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6122 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6123 Spacing));
6124 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006125 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006126 TmpInst.addOperand(Inst.getOperand(1)); // lane
6127 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6128 TmpInst.addOperand(Inst.getOperand(5));
6129 Inst = TmpInst;
6130 return true;
6131 }
6132
Jim Grosbache983a132012-01-24 18:37:25 +00006133 case ARM::VLD4LNdAsm_8:
6134 case ARM::VLD4LNdAsm_16:
6135 case ARM::VLD4LNdAsm_32:
6136 case ARM::VLD4LNqAsm_16:
6137 case ARM::VLD4LNqAsm_32: {
6138 MCInst TmpInst;
6139 // Shuffle the operands around so the lane index operand is in the
6140 // right place.
6141 unsigned Spacing;
6142 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6143 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6144 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6145 Spacing));
6146 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6147 Spacing * 2));
6148 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6149 Spacing * 3));
6150 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6151 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6152 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6153 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6154 Spacing));
6155 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6156 Spacing * 2));
6157 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6158 Spacing * 3));
6159 TmpInst.addOperand(Inst.getOperand(1)); // lane
6160 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6161 TmpInst.addOperand(Inst.getOperand(5));
6162 Inst = TmpInst;
6163 return true;
6164 }
6165
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006166 // VLD3DUP single 3-element structure to all lanes instructions.
6167 case ARM::VLD3DUPdAsm_8:
6168 case ARM::VLD3DUPdAsm_16:
6169 case ARM::VLD3DUPdAsm_32:
6170 case ARM::VLD3DUPqAsm_8:
6171 case ARM::VLD3DUPqAsm_16:
6172 case ARM::VLD3DUPqAsm_32: {
6173 MCInst TmpInst;
6174 unsigned Spacing;
6175 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6176 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6177 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6178 Spacing));
6179 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6180 Spacing * 2));
6181 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6182 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6183 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6184 TmpInst.addOperand(Inst.getOperand(4));
6185 Inst = TmpInst;
6186 return true;
6187 }
6188
6189 case ARM::VLD3DUPdWB_fixed_Asm_8:
6190 case ARM::VLD3DUPdWB_fixed_Asm_16:
6191 case ARM::VLD3DUPdWB_fixed_Asm_32:
6192 case ARM::VLD3DUPqWB_fixed_Asm_8:
6193 case ARM::VLD3DUPqWB_fixed_Asm_16:
6194 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6195 MCInst TmpInst;
6196 unsigned Spacing;
6197 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6198 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6199 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6200 Spacing));
6201 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6202 Spacing * 2));
6203 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6204 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6205 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6206 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6207 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6208 TmpInst.addOperand(Inst.getOperand(4));
6209 Inst = TmpInst;
6210 return true;
6211 }
6212
6213 case ARM::VLD3DUPdWB_register_Asm_8:
6214 case ARM::VLD3DUPdWB_register_Asm_16:
6215 case ARM::VLD3DUPdWB_register_Asm_32:
6216 case ARM::VLD3DUPqWB_register_Asm_8:
6217 case ARM::VLD3DUPqWB_register_Asm_16:
6218 case ARM::VLD3DUPqWB_register_Asm_32: {
6219 MCInst TmpInst;
6220 unsigned Spacing;
6221 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6222 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6223 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6224 Spacing));
6225 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6226 Spacing * 2));
6227 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6228 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6229 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6230 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6231 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6232 TmpInst.addOperand(Inst.getOperand(5));
6233 Inst = TmpInst;
6234 return true;
6235 }
6236
Jim Grosbachc387fc62012-01-23 23:20:46 +00006237 // VLD3 multiple 3-element structure instructions.
6238 case ARM::VLD3dAsm_8:
6239 case ARM::VLD3dAsm_16:
6240 case ARM::VLD3dAsm_32:
6241 case ARM::VLD3qAsm_8:
6242 case ARM::VLD3qAsm_16:
6243 case ARM::VLD3qAsm_32: {
6244 MCInst TmpInst;
6245 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006246 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006247 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6248 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6249 Spacing));
6250 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6251 Spacing * 2));
6252 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6253 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6254 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6255 TmpInst.addOperand(Inst.getOperand(4));
6256 Inst = TmpInst;
6257 return true;
6258 }
6259
6260 case ARM::VLD3dWB_fixed_Asm_8:
6261 case ARM::VLD3dWB_fixed_Asm_16:
6262 case ARM::VLD3dWB_fixed_Asm_32:
6263 case ARM::VLD3qWB_fixed_Asm_8:
6264 case ARM::VLD3qWB_fixed_Asm_16:
6265 case ARM::VLD3qWB_fixed_Asm_32: {
6266 MCInst TmpInst;
6267 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006268 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006269 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6270 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6271 Spacing));
6272 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6273 Spacing * 2));
6274 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6275 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6276 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6277 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6278 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6279 TmpInst.addOperand(Inst.getOperand(4));
6280 Inst = TmpInst;
6281 return true;
6282 }
6283
6284 case ARM::VLD3dWB_register_Asm_8:
6285 case ARM::VLD3dWB_register_Asm_16:
6286 case ARM::VLD3dWB_register_Asm_32:
6287 case ARM::VLD3qWB_register_Asm_8:
6288 case ARM::VLD3qWB_register_Asm_16:
6289 case ARM::VLD3qWB_register_Asm_32: {
6290 MCInst TmpInst;
6291 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006292 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006293 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6294 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6295 Spacing));
6296 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6297 Spacing * 2));
6298 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6299 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6300 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6301 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6302 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6303 TmpInst.addOperand(Inst.getOperand(5));
6304 Inst = TmpInst;
6305 return true;
6306 }
6307
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006308 // VLD4DUP single 3-element structure to all lanes instructions.
6309 case ARM::VLD4DUPdAsm_8:
6310 case ARM::VLD4DUPdAsm_16:
6311 case ARM::VLD4DUPdAsm_32:
6312 case ARM::VLD4DUPqAsm_8:
6313 case ARM::VLD4DUPqAsm_16:
6314 case ARM::VLD4DUPqAsm_32: {
6315 MCInst TmpInst;
6316 unsigned Spacing;
6317 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6318 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6319 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6320 Spacing));
6321 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6322 Spacing * 2));
6323 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6324 Spacing * 3));
6325 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6326 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6327 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6328 TmpInst.addOperand(Inst.getOperand(4));
6329 Inst = TmpInst;
6330 return true;
6331 }
6332
6333 case ARM::VLD4DUPdWB_fixed_Asm_8:
6334 case ARM::VLD4DUPdWB_fixed_Asm_16:
6335 case ARM::VLD4DUPdWB_fixed_Asm_32:
6336 case ARM::VLD4DUPqWB_fixed_Asm_8:
6337 case ARM::VLD4DUPqWB_fixed_Asm_16:
6338 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6339 MCInst TmpInst;
6340 unsigned Spacing;
6341 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6342 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6343 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6344 Spacing));
6345 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6346 Spacing * 2));
6347 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6348 Spacing * 3));
6349 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6350 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6351 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6352 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6353 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6354 TmpInst.addOperand(Inst.getOperand(4));
6355 Inst = TmpInst;
6356 return true;
6357 }
6358
6359 case ARM::VLD4DUPdWB_register_Asm_8:
6360 case ARM::VLD4DUPdWB_register_Asm_16:
6361 case ARM::VLD4DUPdWB_register_Asm_32:
6362 case ARM::VLD4DUPqWB_register_Asm_8:
6363 case ARM::VLD4DUPqWB_register_Asm_16:
6364 case ARM::VLD4DUPqWB_register_Asm_32: {
6365 MCInst TmpInst;
6366 unsigned Spacing;
6367 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6368 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6369 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6370 Spacing));
6371 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6372 Spacing * 2));
6373 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6374 Spacing * 3));
6375 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6376 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6377 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6378 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6379 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6380 TmpInst.addOperand(Inst.getOperand(5));
6381 Inst = TmpInst;
6382 return true;
6383 }
6384
6385 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006386 case ARM::VLD4dAsm_8:
6387 case ARM::VLD4dAsm_16:
6388 case ARM::VLD4dAsm_32:
6389 case ARM::VLD4qAsm_8:
6390 case ARM::VLD4qAsm_16:
6391 case ARM::VLD4qAsm_32: {
6392 MCInst TmpInst;
6393 unsigned Spacing;
6394 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6395 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6396 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6397 Spacing));
6398 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6399 Spacing * 2));
6400 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6401 Spacing * 3));
6402 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6403 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6404 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6405 TmpInst.addOperand(Inst.getOperand(4));
6406 Inst = TmpInst;
6407 return true;
6408 }
6409
6410 case ARM::VLD4dWB_fixed_Asm_8:
6411 case ARM::VLD4dWB_fixed_Asm_16:
6412 case ARM::VLD4dWB_fixed_Asm_32:
6413 case ARM::VLD4qWB_fixed_Asm_8:
6414 case ARM::VLD4qWB_fixed_Asm_16:
6415 case ARM::VLD4qWB_fixed_Asm_32: {
6416 MCInst TmpInst;
6417 unsigned Spacing;
6418 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6419 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6420 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6421 Spacing));
6422 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6423 Spacing * 2));
6424 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6425 Spacing * 3));
6426 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6427 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6428 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6429 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6430 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6431 TmpInst.addOperand(Inst.getOperand(4));
6432 Inst = TmpInst;
6433 return true;
6434 }
6435
6436 case ARM::VLD4dWB_register_Asm_8:
6437 case ARM::VLD4dWB_register_Asm_16:
6438 case ARM::VLD4dWB_register_Asm_32:
6439 case ARM::VLD4qWB_register_Asm_8:
6440 case ARM::VLD4qWB_register_Asm_16:
6441 case ARM::VLD4qWB_register_Asm_32: {
6442 MCInst TmpInst;
6443 unsigned Spacing;
6444 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6445 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6446 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6447 Spacing));
6448 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6449 Spacing * 2));
6450 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6451 Spacing * 3));
6452 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6453 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6454 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6455 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6456 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6457 TmpInst.addOperand(Inst.getOperand(5));
6458 Inst = TmpInst;
6459 return true;
6460 }
6461
Jim Grosbachd7433e22012-01-23 23:45:44 +00006462 // VST3 multiple 3-element structure instructions.
6463 case ARM::VST3dAsm_8:
6464 case ARM::VST3dAsm_16:
6465 case ARM::VST3dAsm_32:
6466 case ARM::VST3qAsm_8:
6467 case ARM::VST3qAsm_16:
6468 case ARM::VST3qAsm_32: {
6469 MCInst TmpInst;
6470 unsigned Spacing;
6471 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6472 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6473 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6474 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6475 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6476 Spacing));
6477 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6478 Spacing * 2));
6479 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6480 TmpInst.addOperand(Inst.getOperand(4));
6481 Inst = TmpInst;
6482 return true;
6483 }
6484
6485 case ARM::VST3dWB_fixed_Asm_8:
6486 case ARM::VST3dWB_fixed_Asm_16:
6487 case ARM::VST3dWB_fixed_Asm_32:
6488 case ARM::VST3qWB_fixed_Asm_8:
6489 case ARM::VST3qWB_fixed_Asm_16:
6490 case ARM::VST3qWB_fixed_Asm_32: {
6491 MCInst TmpInst;
6492 unsigned Spacing;
6493 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6494 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6495 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6496 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6497 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6498 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6499 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6500 Spacing));
6501 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6502 Spacing * 2));
6503 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6504 TmpInst.addOperand(Inst.getOperand(4));
6505 Inst = TmpInst;
6506 return true;
6507 }
6508
6509 case ARM::VST3dWB_register_Asm_8:
6510 case ARM::VST3dWB_register_Asm_16:
6511 case ARM::VST3dWB_register_Asm_32:
6512 case ARM::VST3qWB_register_Asm_8:
6513 case ARM::VST3qWB_register_Asm_16:
6514 case ARM::VST3qWB_register_Asm_32: {
6515 MCInst TmpInst;
6516 unsigned Spacing;
6517 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6518 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6519 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6520 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6521 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6522 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6523 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6524 Spacing));
6525 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6526 Spacing * 2));
6527 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6528 TmpInst.addOperand(Inst.getOperand(5));
6529 Inst = TmpInst;
6530 return true;
6531 }
6532
Jim Grosbach539aab72012-01-24 00:58:13 +00006533 // VST4 multiple 3-element structure instructions.
6534 case ARM::VST4dAsm_8:
6535 case ARM::VST4dAsm_16:
6536 case ARM::VST4dAsm_32:
6537 case ARM::VST4qAsm_8:
6538 case ARM::VST4qAsm_16:
6539 case ARM::VST4qAsm_32: {
6540 MCInst TmpInst;
6541 unsigned Spacing;
6542 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6543 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6544 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6545 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6546 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6547 Spacing));
6548 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6549 Spacing * 2));
6550 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6551 Spacing * 3));
6552 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6553 TmpInst.addOperand(Inst.getOperand(4));
6554 Inst = TmpInst;
6555 return true;
6556 }
6557
6558 case ARM::VST4dWB_fixed_Asm_8:
6559 case ARM::VST4dWB_fixed_Asm_16:
6560 case ARM::VST4dWB_fixed_Asm_32:
6561 case ARM::VST4qWB_fixed_Asm_8:
6562 case ARM::VST4qWB_fixed_Asm_16:
6563 case ARM::VST4qWB_fixed_Asm_32: {
6564 MCInst TmpInst;
6565 unsigned Spacing;
6566 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6567 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6568 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6569 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6570 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6571 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6572 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6573 Spacing));
6574 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6575 Spacing * 2));
6576 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6577 Spacing * 3));
6578 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6579 TmpInst.addOperand(Inst.getOperand(4));
6580 Inst = TmpInst;
6581 return true;
6582 }
6583
6584 case ARM::VST4dWB_register_Asm_8:
6585 case ARM::VST4dWB_register_Asm_16:
6586 case ARM::VST4dWB_register_Asm_32:
6587 case ARM::VST4qWB_register_Asm_8:
6588 case ARM::VST4qWB_register_Asm_16:
6589 case ARM::VST4qWB_register_Asm_32: {
6590 MCInst TmpInst;
6591 unsigned Spacing;
6592 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6593 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6594 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6595 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6596 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6597 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6598 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6599 Spacing));
6600 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6601 Spacing * 2));
6602 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6603 Spacing * 3));
6604 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6605 TmpInst.addOperand(Inst.getOperand(5));
6606 Inst = TmpInst;
6607 return true;
6608 }
6609
Jim Grosbach863d2af2011-12-13 22:45:11 +00006610 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006611 case ARM::t2MOVsr:
6612 case ARM::t2MOVSsr: {
6613 // Which instruction to expand to depends on the CCOut operand and
6614 // whether we're in an IT block if the register operands are low
6615 // registers.
6616 bool isNarrow = false;
6617 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6618 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6619 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6620 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6621 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6622 isNarrow = true;
6623 MCInst TmpInst;
6624 unsigned newOpc;
6625 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6626 default: llvm_unreachable("unexpected opcode!");
6627 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6628 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6629 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6630 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6631 }
6632 TmpInst.setOpcode(newOpc);
6633 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6634 if (isNarrow)
6635 TmpInst.addOperand(MCOperand::CreateReg(
6636 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6637 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6638 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6639 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6640 TmpInst.addOperand(Inst.getOperand(5));
6641 if (!isNarrow)
6642 TmpInst.addOperand(MCOperand::CreateReg(
6643 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6644 Inst = TmpInst;
6645 return true;
6646 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006647 case ARM::t2MOVsi:
6648 case ARM::t2MOVSsi: {
6649 // Which instruction to expand to depends on the CCOut operand and
6650 // whether we're in an IT block if the register operands are low
6651 // registers.
6652 bool isNarrow = false;
6653 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6654 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6655 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6656 isNarrow = true;
6657 MCInst TmpInst;
6658 unsigned newOpc;
6659 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6660 default: llvm_unreachable("unexpected opcode!");
6661 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6662 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6663 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6664 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006665 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006666 }
6667 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6668 if (Ammount == 32) Ammount = 0;
6669 TmpInst.setOpcode(newOpc);
6670 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6671 if (isNarrow)
6672 TmpInst.addOperand(MCOperand::CreateReg(
6673 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6674 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006675 if (newOpc != ARM::t2RRX)
6676 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006677 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6678 TmpInst.addOperand(Inst.getOperand(4));
6679 if (!isNarrow)
6680 TmpInst.addOperand(MCOperand::CreateReg(
6681 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6682 Inst = TmpInst;
6683 return true;
6684 }
6685 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006686 case ARM::ASRr:
6687 case ARM::LSRr:
6688 case ARM::LSLr:
6689 case ARM::RORr: {
6690 ARM_AM::ShiftOpc ShiftTy;
6691 switch(Inst.getOpcode()) {
6692 default: llvm_unreachable("unexpected opcode!");
6693 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6694 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6695 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6696 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6697 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006698 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6699 MCInst TmpInst;
6700 TmpInst.setOpcode(ARM::MOVsr);
6701 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6702 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6703 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6704 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6705 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6706 TmpInst.addOperand(Inst.getOperand(4));
6707 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6708 Inst = TmpInst;
6709 return true;
6710 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006711 case ARM::ASRi:
6712 case ARM::LSRi:
6713 case ARM::LSLi:
6714 case ARM::RORi: {
6715 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006716 switch(Inst.getOpcode()) {
6717 default: llvm_unreachable("unexpected opcode!");
6718 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6719 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6720 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6721 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6722 }
6723 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006724 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006725 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6726 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006727 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006728 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006729 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6730 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006731 if (Opc == ARM::MOVsi)
6732 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006733 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6734 TmpInst.addOperand(Inst.getOperand(4));
6735 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6736 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006737 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006738 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006739 case ARM::RRXi: {
6740 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6741 MCInst TmpInst;
6742 TmpInst.setOpcode(ARM::MOVsi);
6743 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6744 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6745 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6746 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6747 TmpInst.addOperand(Inst.getOperand(3));
6748 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6749 Inst = TmpInst;
6750 return true;
6751 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006752 case ARM::t2LDMIA_UPD: {
6753 // If this is a load of a single register, then we should use
6754 // a post-indexed LDR instruction instead, per the ARM ARM.
6755 if (Inst.getNumOperands() != 5)
6756 return false;
6757 MCInst TmpInst;
6758 TmpInst.setOpcode(ARM::t2LDR_POST);
6759 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6760 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6761 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6762 TmpInst.addOperand(MCOperand::CreateImm(4));
6763 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6764 TmpInst.addOperand(Inst.getOperand(3));
6765 Inst = TmpInst;
6766 return true;
6767 }
6768 case ARM::t2STMDB_UPD: {
6769 // If this is a store of a single register, then we should use
6770 // a pre-indexed STR instruction instead, per the ARM ARM.
6771 if (Inst.getNumOperands() != 5)
6772 return false;
6773 MCInst TmpInst;
6774 TmpInst.setOpcode(ARM::t2STR_PRE);
6775 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6776 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6777 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6778 TmpInst.addOperand(MCOperand::CreateImm(-4));
6779 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6780 TmpInst.addOperand(Inst.getOperand(3));
6781 Inst = TmpInst;
6782 return true;
6783 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006784 case ARM::LDMIA_UPD:
6785 // If this is a load of a single register via a 'pop', then we should use
6786 // a post-indexed LDR instruction instead, per the ARM ARM.
6787 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6788 Inst.getNumOperands() == 5) {
6789 MCInst TmpInst;
6790 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6791 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6792 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6793 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6794 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6795 TmpInst.addOperand(MCOperand::CreateImm(4));
6796 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6797 TmpInst.addOperand(Inst.getOperand(3));
6798 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006799 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006800 }
6801 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006802 case ARM::STMDB_UPD:
6803 // If this is a store of a single register via a 'push', then we should use
6804 // a pre-indexed STR instruction instead, per the ARM ARM.
6805 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6806 Inst.getNumOperands() == 5) {
6807 MCInst TmpInst;
6808 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6809 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6810 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6811 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6812 TmpInst.addOperand(MCOperand::CreateImm(-4));
6813 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6814 TmpInst.addOperand(Inst.getOperand(3));
6815 Inst = TmpInst;
6816 }
6817 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006818 case ARM::t2ADDri12:
6819 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6820 // mnemonic was used (not "addw"), encoding T3 is preferred.
6821 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6822 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6823 break;
6824 Inst.setOpcode(ARM::t2ADDri);
6825 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6826 break;
6827 case ARM::t2SUBri12:
6828 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6829 // mnemonic was used (not "subw"), encoding T3 is preferred.
6830 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6831 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6832 break;
6833 Inst.setOpcode(ARM::t2SUBri);
6834 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6835 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006836 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006837 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6838 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6839 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6840 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006841 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006842 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006843 return true;
6844 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006845 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006846 case ARM::tSUBi8:
6847 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6848 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6849 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6850 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006851 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006852 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006853 return true;
6854 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006855 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006856 case ARM::t2ADDri:
6857 case ARM::t2SUBri: {
6858 // If the destination and first source operand are the same, and
6859 // the flags are compatible with the current IT status, use encoding T2
6860 // instead of T3. For compatibility with the system 'as'. Make sure the
6861 // wide encoding wasn't explicit.
6862 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach8f1148b2012-03-30 18:39:43 +00006863 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbach2d30d942012-03-30 17:20:40 +00006864 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6865 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6866 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6867 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6868 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
6869 break;
6870 MCInst TmpInst;
6871 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
6872 ARM::tADDi8 : ARM::tSUBi8);
6873 TmpInst.addOperand(Inst.getOperand(0));
6874 TmpInst.addOperand(Inst.getOperand(5));
6875 TmpInst.addOperand(Inst.getOperand(0));
6876 TmpInst.addOperand(Inst.getOperand(2));
6877 TmpInst.addOperand(Inst.getOperand(3));
6878 TmpInst.addOperand(Inst.getOperand(4));
6879 Inst = TmpInst;
6880 return true;
6881 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00006882 case ARM::t2ADDrr: {
6883 // If the destination and first source operand are the same, and
6884 // there's no setting of the flags, use encoding T2 instead of T3.
6885 // Note that this is only for ADD, not SUB. This mirrors the system
6886 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6887 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6888 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006889 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6890 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006891 break;
6892 MCInst TmpInst;
6893 TmpInst.setOpcode(ARM::tADDhirr);
6894 TmpInst.addOperand(Inst.getOperand(0));
6895 TmpInst.addOperand(Inst.getOperand(0));
6896 TmpInst.addOperand(Inst.getOperand(2));
6897 TmpInst.addOperand(Inst.getOperand(3));
6898 TmpInst.addOperand(Inst.getOperand(4));
6899 Inst = TmpInst;
6900 return true;
6901 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006902 case ARM::tB:
6903 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006904 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006905 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006906 return true;
6907 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006908 break;
6909 case ARM::t2B:
6910 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006911 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006912 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006913 return true;
6914 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006915 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006916 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006917 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006918 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006919 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006920 return true;
6921 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006922 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006923 case ARM::tBcc:
6924 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006925 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006926 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006927 return true;
6928 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006929 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006930 case ARM::tLDMIA: {
6931 // If the register list contains any high registers, or if the writeback
6932 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6933 // instead if we're in Thumb2. Otherwise, this should have generated
6934 // an error in validateInstruction().
6935 unsigned Rn = Inst.getOperand(0).getReg();
6936 bool hasWritebackToken =
6937 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6938 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6939 bool listContainsBase;
6940 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6941 (!listContainsBase && !hasWritebackToken) ||
6942 (listContainsBase && hasWritebackToken)) {
6943 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6944 assert (isThumbTwo());
6945 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6946 // If we're switching to the updating version, we need to insert
6947 // the writeback tied operand.
6948 if (hasWritebackToken)
6949 Inst.insert(Inst.begin(),
6950 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006951 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006952 }
6953 break;
6954 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006955 case ARM::tSTMIA_UPD: {
6956 // If the register list contains any high registers, we need to use
6957 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6958 // should have generated an error in validateInstruction().
6959 unsigned Rn = Inst.getOperand(0).getReg();
6960 bool listContainsBase;
6961 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6962 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6963 assert (isThumbTwo());
6964 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006965 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006966 }
6967 break;
6968 }
Jim Grosbach54026372011-11-10 23:17:11 +00006969 case ARM::tPOP: {
6970 bool listContainsBase;
6971 // If the register list contains any high registers, we need to use
6972 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6973 // should have generated an error in validateInstruction().
6974 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006975 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006976 assert (isThumbTwo());
6977 Inst.setOpcode(ARM::t2LDMIA_UPD);
6978 // Add the base register and writeback operands.
6979 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6980 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006981 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006982 }
6983 case ARM::tPUSH: {
6984 bool listContainsBase;
6985 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006986 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006987 assert (isThumbTwo());
6988 Inst.setOpcode(ARM::t2STMDB_UPD);
6989 // Add the base register and writeback operands.
6990 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6991 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006992 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006993 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006994 case ARM::t2MOVi: {
6995 // If we can use the 16-bit encoding and the user didn't explicitly
6996 // request the 32-bit variant, transform it here.
6997 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00006998 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006999 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7000 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7001 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007002 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7003 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7004 // The operands aren't in the same order for tMOVi8...
7005 MCInst TmpInst;
7006 TmpInst.setOpcode(ARM::tMOVi8);
7007 TmpInst.addOperand(Inst.getOperand(0));
7008 TmpInst.addOperand(Inst.getOperand(4));
7009 TmpInst.addOperand(Inst.getOperand(1));
7010 TmpInst.addOperand(Inst.getOperand(2));
7011 TmpInst.addOperand(Inst.getOperand(3));
7012 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007013 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007014 }
7015 break;
7016 }
7017 case ARM::t2MOVr: {
7018 // If we can use the 16-bit encoding and the user didn't explicitly
7019 // request the 32-bit variant, transform it here.
7020 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7021 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7022 Inst.getOperand(2).getImm() == ARMCC::AL &&
7023 Inst.getOperand(4).getReg() == ARM::CPSR &&
7024 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7025 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7026 // The operands aren't the same for tMOV[S]r... (no cc_out)
7027 MCInst TmpInst;
7028 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7029 TmpInst.addOperand(Inst.getOperand(0));
7030 TmpInst.addOperand(Inst.getOperand(1));
7031 TmpInst.addOperand(Inst.getOperand(2));
7032 TmpInst.addOperand(Inst.getOperand(3));
7033 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007034 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007035 }
7036 break;
7037 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007038 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007039 case ARM::t2SXTB:
7040 case ARM::t2UXTH:
7041 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007042 // If we can use the 16-bit encoding and the user didn't explicitly
7043 // request the 32-bit variant, transform it here.
7044 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7045 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7046 Inst.getOperand(2).getImm() == 0 &&
7047 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7048 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007049 unsigned NewOpc;
7050 switch (Inst.getOpcode()) {
7051 default: llvm_unreachable("Illegal opcode!");
7052 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7053 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7054 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7055 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7056 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007057 // The operands aren't the same for thumb1 (no rotate operand).
7058 MCInst TmpInst;
7059 TmpInst.setOpcode(NewOpc);
7060 TmpInst.addOperand(Inst.getOperand(0));
7061 TmpInst.addOperand(Inst.getOperand(1));
7062 TmpInst.addOperand(Inst.getOperand(3));
7063 TmpInst.addOperand(Inst.getOperand(4));
7064 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007065 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007066 }
7067 break;
7068 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007069 case ARM::MOVsi: {
7070 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7071 if (SOpc == ARM_AM::rrx) return false;
7072 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7073 // Shifting by zero is accepted as a vanilla 'MOVr'
7074 MCInst TmpInst;
7075 TmpInst.setOpcode(ARM::MOVr);
7076 TmpInst.addOperand(Inst.getOperand(0));
7077 TmpInst.addOperand(Inst.getOperand(1));
7078 TmpInst.addOperand(Inst.getOperand(3));
7079 TmpInst.addOperand(Inst.getOperand(4));
7080 TmpInst.addOperand(Inst.getOperand(5));
7081 Inst = TmpInst;
7082 return true;
7083 }
7084 return false;
7085 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007086 case ARM::ANDrsi:
7087 case ARM::ORRrsi:
7088 case ARM::EORrsi:
7089 case ARM::BICrsi:
7090 case ARM::SUBrsi:
7091 case ARM::ADDrsi: {
7092 unsigned newOpc;
7093 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7094 if (SOpc == ARM_AM::rrx) return false;
7095 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007096 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007097 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7098 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7099 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7100 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7101 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7102 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7103 }
7104 // If the shift is by zero, use the non-shifted instruction definition.
7105 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7106 MCInst TmpInst;
7107 TmpInst.setOpcode(newOpc);
7108 TmpInst.addOperand(Inst.getOperand(0));
7109 TmpInst.addOperand(Inst.getOperand(1));
7110 TmpInst.addOperand(Inst.getOperand(2));
7111 TmpInst.addOperand(Inst.getOperand(4));
7112 TmpInst.addOperand(Inst.getOperand(5));
7113 TmpInst.addOperand(Inst.getOperand(6));
7114 Inst = TmpInst;
7115 return true;
7116 }
7117 return false;
7118 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007119 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007120 case ARM::t2IT: {
7121 // The mask bits for all but the first condition are represented as
7122 // the low bit of the condition code value implies 't'. We currently
7123 // always have 1 implies 't', so XOR toggle the bits if the low bit
7124 // of the condition code is zero. The encoding also expects the low
7125 // bit of the condition to be encoded as bit 4 of the mask operand,
7126 // so mask that in if needed
7127 MCOperand &MO = Inst.getOperand(1);
7128 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007129 unsigned OrigMask = Mask;
7130 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007131 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007132 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7133 for (unsigned i = 3; i != TZ; --i)
7134 Mask ^= 1 << i;
7135 } else
7136 Mask |= 0x10;
7137 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007138
7139 // Set up the IT block state according to the IT instruction we just
7140 // matched.
7141 assert(!inITBlock() && "nested IT blocks?!");
7142 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7143 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7144 ITState.CurPosition = 0;
7145 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007146 break;
7147 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007148 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007149 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007150}
7151
Jim Grosbach47a0d522011-08-16 20:45:50 +00007152unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7153 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7154 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007155 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007156 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007157 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7158 assert(MCID.hasOptionalDef() &&
7159 "optionally flag setting instruction missing optional def operand");
7160 assert(MCID.NumOperands == Inst.getNumOperands() &&
7161 "operand count mismatch!");
7162 // Find the optional-def operand (cc_out).
7163 unsigned OpNo;
7164 for (OpNo = 0;
7165 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7166 ++OpNo)
7167 ;
7168 // If we're parsing Thumb1, reject it completely.
7169 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7170 return Match_MnemonicFail;
7171 // If we're parsing Thumb2, which form is legal depends on whether we're
7172 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007173 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7174 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007175 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007176 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7177 inITBlock())
7178 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007179 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007180 // Some high-register supporting Thumb1 encodings only allow both registers
7181 // to be from r0-r7 when in Thumb2.
7182 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7183 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7184 isARMLowRegister(Inst.getOperand(2).getReg()))
7185 return Match_RequiresThumb2;
7186 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007187 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007188 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7189 isARMLowRegister(Inst.getOperand(1).getReg()))
7190 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007191 return Match_Success;
7192}
7193
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007194bool ARMAsmParser::
7195MatchAndEmitInstruction(SMLoc IDLoc,
7196 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7197 MCStreamer &Out) {
7198 MCInst Inst;
7199 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007200 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007201 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007202 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007203 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007204 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007205 // Context sensitive operand constraints aren't handled by the matcher,
7206 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007207 if (validateInstruction(Inst, Operands)) {
7208 // Still progress the IT block, otherwise one wrong condition causes
7209 // nasty cascading errors.
7210 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007211 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007212 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007213
Jim Grosbachf8fce712011-08-11 17:35:48 +00007214 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007215 // encoding is selected. Loop on it while changes happen so the
7216 // individual transformations can chain off each other. E.g.,
7217 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7218 while (processInstruction(Inst, Operands))
7219 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007220
Jim Grosbacha1109882011-09-02 23:22:08 +00007221 // Only move forward at the very end so that everything in validate
7222 // and process gets a consistent answer about whether we're in an IT
7223 // block.
7224 forwardITPosition();
7225
Jim Grosbach74423e32012-01-25 19:52:01 +00007226 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7227 // doesn't actually encode.
7228 if (Inst.getOpcode() == ARM::ITasm)
7229 return false;
7230
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007231 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007232 Out.EmitInstruction(Inst);
7233 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007234 case Match_MissingFeature:
7235 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7236 return true;
7237 case Match_InvalidOperand: {
7238 SMLoc ErrorLoc = IDLoc;
7239 if (ErrorInfo != ~0U) {
7240 if (ErrorInfo >= Operands.size())
7241 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007242
Chris Lattnere73d4f82010-10-28 21:41:58 +00007243 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7244 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7245 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007246
Chris Lattnere73d4f82010-10-28 21:41:58 +00007247 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007248 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007249 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007250 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007251 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007252 // The converter function will have already emited a diagnostic.
7253 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007254 case Match_RequiresNotITBlock:
7255 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007256 case Match_RequiresITBlock:
7257 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007258 case Match_RequiresV6:
7259 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7260 case Match_RequiresThumb2:
7261 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007262 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007263
Eric Christopherc223e2b2010-10-29 09:26:59 +00007264 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007265}
7266
Jim Grosbach1355cf12011-07-26 17:10:22 +00007267/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007268bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7269 StringRef IDVal = DirectiveID.getIdentifier();
7270 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007271 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007272 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007273 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007274 else if (IDVal == ".arm")
7275 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007276 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007277 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007278 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007279 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007280 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007281 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007282 else if (IDVal == ".unreq")
7283 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007284 else if (IDVal == ".arch")
7285 return parseDirectiveArch(DirectiveID.getLoc());
7286 else if (IDVal == ".eabi_attribute")
7287 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007288 return true;
7289}
7290
Jim Grosbach1355cf12011-07-26 17:10:22 +00007291/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007292/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007293bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7295 for (;;) {
7296 const MCExpr *Value;
7297 if (getParser().ParseExpression(Value))
7298 return true;
7299
Chris Lattneraaec2052010-01-19 19:46:13 +00007300 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007301
7302 if (getLexer().is(AsmToken::EndOfStatement))
7303 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007304
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007305 // FIXME: Improve diagnostic.
7306 if (getLexer().isNot(AsmToken::Comma))
7307 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007308 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007309 }
7310 }
7311
Sean Callananb9a25b72010-01-19 20:27:46 +00007312 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007313 return false;
7314}
7315
Jim Grosbach1355cf12011-07-26 17:10:22 +00007316/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007317/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007318bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007319 if (getLexer().isNot(AsmToken::EndOfStatement))
7320 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007321 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007322
Jim Grosbach9a70df92011-12-07 18:04:19 +00007323 if (!isThumb())
7324 SwitchMode();
7325 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7326 return false;
7327}
7328
7329/// parseDirectiveARM
7330/// ::= .arm
7331bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7332 if (getLexer().isNot(AsmToken::EndOfStatement))
7333 return Error(L, "unexpected token in directive");
7334 Parser.Lex();
7335
7336 if (isThumb())
7337 SwitchMode();
7338 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007339 return false;
7340}
7341
Jim Grosbach1355cf12011-07-26 17:10:22 +00007342/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007343/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007344bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007345 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7346 bool isMachO = MAI.hasSubsectionsViaSymbols();
7347 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007348 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007349
Jim Grosbachde4d8392011-12-21 22:30:16 +00007350 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007351 // ELF doesn't
7352 if (isMachO) {
7353 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007354 if (Tok.isNot(AsmToken::EndOfStatement)) {
7355 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7356 return Error(L, "unexpected token in .thumb_func directive");
7357 Name = Tok.getIdentifier();
7358 Parser.Lex(); // Consume the identifier token.
7359 needFuncName = false;
7360 }
Rafael Espindola64695402011-05-16 16:17:21 +00007361 }
7362
Jim Grosbachde4d8392011-12-21 22:30:16 +00007363 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007364 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007365
7366 // Eat the end of statement and any blank lines that follow.
7367 while (getLexer().is(AsmToken::EndOfStatement))
7368 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007369
Rafael Espindola64695402011-05-16 16:17:21 +00007370 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007371 // We really should be checking the next symbol definition even if there's
7372 // stuff in between.
7373 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007374 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007375 }
7376
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007377 // Mark symbol as a thumb symbol.
7378 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7379 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007380 return false;
7381}
7382
Jim Grosbach1355cf12011-07-26 17:10:22 +00007383/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007384/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007385bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007386 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007387 if (Tok.isNot(AsmToken::Identifier))
7388 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007389 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007390 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007391 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007392 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007393 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007394 else
7395 return Error(L, "unrecognized syntax mode in .syntax directive");
7396
7397 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007398 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007399 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007400
7401 // TODO tell the MC streamer the mode
7402 // getParser().getStreamer().Emit???();
7403 return false;
7404}
7405
Jim Grosbach1355cf12011-07-26 17:10:22 +00007406/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007407/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007408bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007409 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007410 if (Tok.isNot(AsmToken::Integer))
7411 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007412 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007413 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007414 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007415 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007416 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007417 else
7418 return Error(L, "invalid operand to .code directive");
7419
7420 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007421 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007422 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007423
Evan Cheng32869202011-07-08 22:36:29 +00007424 if (Val == 16) {
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_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007428 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007429 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007430 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007431 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007432 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007433
Kevin Enderby515d5092009-10-15 20:48:48 +00007434 return false;
7435}
7436
Jim Grosbacha39cda72011-12-14 02:16:11 +00007437/// parseDirectiveReq
7438/// ::= name .req registername
7439bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7440 Parser.Lex(); // Eat the '.req' token.
7441 unsigned Reg;
7442 SMLoc SRegLoc, ERegLoc;
7443 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7444 Parser.EatToEndOfStatement();
7445 return Error(SRegLoc, "register name expected");
7446 }
7447
7448 // Shouldn't be anything else.
7449 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7450 Parser.EatToEndOfStatement();
7451 return Error(Parser.getTok().getLoc(),
7452 "unexpected input in .req directive.");
7453 }
7454
7455 Parser.Lex(); // Consume the EndOfStatement
7456
7457 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7458 return Error(SRegLoc, "redefinition of '" + Name +
7459 "' does not match original.");
7460
7461 return false;
7462}
7463
7464/// parseDirectiveUneq
7465/// ::= .unreq registername
7466bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7467 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7468 Parser.EatToEndOfStatement();
7469 return Error(L, "unexpected input in .unreq directive.");
7470 }
7471 RegisterReqs.erase(Parser.getTok().getIdentifier());
7472 Parser.Lex(); // Eat the identifier.
7473 return false;
7474}
7475
Jason W Kimd7c9e082011-12-20 17:38:12 +00007476/// parseDirectiveArch
7477/// ::= .arch token
7478bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7479 return true;
7480}
7481
7482/// parseDirectiveEabiAttr
7483/// ::= .eabi_attribute int, int
7484bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7485 return true;
7486}
7487
Sean Callanan90b70972010-04-07 20:29:34 +00007488extern "C" void LLVMInitializeARMAsmLexer();
7489
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007490/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007491extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007492 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7493 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007494 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007495}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007496
Chris Lattner0692ee62010-09-06 19:11:01 +00007497#define GET_REGISTER_MATCHER
7498#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007499#include "ARMGenAsmMatcher.inc"