blob: ccdadd816691913d999db630b2655f55e75dc51d [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();
785 return ARM_AM::getSOImmVal(-Value) != -1;
786 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000787 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000788 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000789 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
790 if (!CE) return false;
791 int64_t Value = CE->getValue();
792 return ARM_AM::getT2SOImmVal(Value) != -1;
793 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000794 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000795 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000796 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
797 if (!CE) return false;
798 int64_t Value = CE->getValue();
799 return ARM_AM::getT2SOImmVal(~Value) != -1;
800 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000801 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000802 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getT2SOImmVal(-Value) != -1;
807 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000808 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000809 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000810 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
811 if (!CE) return false;
812 int64_t Value = CE->getValue();
813 return Value == 1 || Value == 0;
814 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000815 bool isReg() const { return Kind == k_Register; }
816 bool isRegList() const { return Kind == k_RegisterList; }
817 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
818 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
819 bool isToken() const { return Kind == k_Token; }
820 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
821 bool isMemory() const { return Kind == k_Memory; }
822 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
823 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
824 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
825 bool isRotImm() const { return Kind == k_RotateImmediate; }
826 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
827 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000828 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000829 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000830 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000832 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000833 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000834 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000835 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
836 (alignOK || Memory.Alignment == 0);
837 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000838 bool isMemPCRelImm12() const {
839 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
840 return false;
841 // Base register must be PC.
842 if (Memory.BaseRegNum != ARM::PC)
843 return false;
844 // Immediate offset in range [-4095, 4095].
845 if (!Memory.OffsetImm) return true;
846 int64_t Val = Memory.OffsetImm->getValue();
847 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
848 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 bool isAlignedMemory() const {
850 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000851 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000853 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000854 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000856 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000857 if (!Memory.OffsetImm) return true;
858 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000860 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000861 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000862 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000863 // Immediate offset in range [-4095, 4095].
864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
865 if (!CE) return false;
866 int64_t Val = CE->getValue();
867 return Val > -4096 && Val < 4096;
868 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000869 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000870 // If we have an immediate that's not a constant, treat it as a label
871 // reference needing a fixup. If it is a constant, it's something else
872 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000873 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000874 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000875 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000878 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000880 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (!Memory.OffsetImm) return true;
882 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 return Val > -256 && Val < 256;
884 }
885 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000886 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000887 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000888 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000889 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
890 // Immediate offset in range [-255, 255].
891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
892 if (!CE) return false;
893 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000894 // Special case, #-0 is INT32_MIN.
895 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000896 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000897 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000898 // If we have an immediate that's not a constant, treat it as a label
899 // reference needing a fixup. If it is a constant, it's something else
900 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000901 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000902 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000903 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000904 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000905 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000906 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000907 if (!Memory.OffsetImm) return true;
908 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000909 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000910 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000911 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000912 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000913 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000914 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000915 return false;
916 return true;
917 }
918 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000919 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000920 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
921 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000922 return false;
923 return true;
924 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000925 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000926 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000927 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000928 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000929 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000930 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000931 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
932 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000933 return false;
934 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000935 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000936 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000937 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000938 return false;
939 return true;
940 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000941 bool isMemThumbRR() const {
942 // Thumb reg+reg addressing is simple. Just two registers, a base and
943 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000945 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000946 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 return isARMLowRegister(Memory.BaseRegNum) &&
948 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000949 }
950 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000952 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000953 return false;
954 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000955 if (!Memory.OffsetImm) return true;
956 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000957 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
958 }
Jim Grosbach38466302011-08-19 18:55:51 +0000959 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000961 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000962 return false;
963 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000964 if (!Memory.OffsetImm) return true;
965 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000966 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
967 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000968 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000970 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 return false;
972 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000973 if (!Memory.OffsetImm) return true;
974 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000975 return Val >= 0 && Val <= 31;
976 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000977 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000978 if (!isMemory() || Memory.OffsetRegNum != 0 ||
979 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 return false;
981 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000982 if (!Memory.OffsetImm) return true;
983 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000984 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000985 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000986 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000987 // If we have an immediate that's not a constant, treat it as a label
988 // reference needing a fixup. If it is a constant, it's something else
989 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000990 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000991 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000992 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 return false;
994 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000995 if (!Memory.OffsetImm) return true;
996 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000997 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
998 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000999 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001000 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 return false;
1002 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!Memory.OffsetImm) return true;
1004 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001005 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1006 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001007 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001008 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001009 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001010 // Base reg of PC isn't allowed for these encodings.
1011 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001013 if (!Memory.OffsetImm) return true;
1014 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001015 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001016 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001017 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001018 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return false;
1020 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001023 return Val >= 0 && Val < 256;
1024 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001025 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001027 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001028 // Base reg of PC isn't allowed for these encodings.
1029 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001031 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001032 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001033 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001034 }
1035 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001036 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 return false;
1038 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001039 if (!Memory.OffsetImm) return true;
1040 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001041 return (Val >= 0 && Val < 4096);
1042 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001043 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001044 // If we have an immediate that's not a constant, treat it as a label
1045 // reference needing a fixup. If it is a constant, it's something else
1046 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001047 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001048 return true;
1049
Jim Grosbach57dcb852011-10-11 17:29:55 +00001050 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001051 return false;
1052 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001053 if (!Memory.OffsetImm) return true;
1054 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001055 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001056 }
1057 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001058 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1060 if (!CE) return false;
1061 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001062 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001063 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001064 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001065 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 if (!CE) return false;
1068 int64_t Val = CE->getValue();
1069 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1070 (Val == INT32_MIN);
1071 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001072
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001073 bool isMSRMask() const { return Kind == k_MSRMask; }
1074 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001075
Jim Grosbach0e387b22011-10-17 22:26:03 +00001076 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001077 bool isSingleSpacedVectorList() const {
1078 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1079 }
1080 bool isDoubleSpacedVectorList() const {
1081 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1082 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001083 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001084 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001085 return VectorList.Count == 1;
1086 }
1087
Jim Grosbach28f08c92012-03-05 19:33:30 +00001088 bool isVecListDPair() const {
1089 if (!isSingleSpacedVectorList()) return false;
1090 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1091 .contains(VectorList.RegNum));
1092 }
1093
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001094 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001096 return VectorList.Count == 3;
1097 }
1098
Jim Grosbachb6310312011-10-21 20:35:01 +00001099 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001101 return VectorList.Count == 4;
1102 }
1103
Jim Grosbachc3384c92012-03-05 21:43:40 +00001104 bool isVecListDPairSpaced() const {
1105 if (!isSingleSpacedVectorList()) return false;
1106 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1107 .contains(VectorList.RegNum));
1108 }
1109
Jim Grosbachc387fc62012-01-23 23:20:46 +00001110 bool isVecListThreeQ() const {
1111 if (!isDoubleSpacedVectorList()) return false;
1112 return VectorList.Count == 3;
1113 }
1114
Jim Grosbach7945ead2012-01-24 00:43:12 +00001115 bool isVecListFourQ() const {
1116 if (!isDoubleSpacedVectorList()) return false;
1117 return VectorList.Count == 4;
1118 }
1119
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001120 bool isSingleSpacedVectorAllLanes() const {
1121 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1122 }
1123 bool isDoubleSpacedVectorAllLanes() const {
1124 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1125 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001126 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001127 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001128 return VectorList.Count == 1;
1129 }
1130
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001131 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001132 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001133 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1134 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001135 }
1136
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001137 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001138 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001139 return VectorList.Count == 2;
1140 }
1141
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001142 bool isVecListThreeDAllLanes() const {
1143 if (!isSingleSpacedVectorAllLanes()) return false;
1144 return VectorList.Count == 3;
1145 }
1146
1147 bool isVecListThreeQAllLanes() const {
1148 if (!isDoubleSpacedVectorAllLanes()) return false;
1149 return VectorList.Count == 3;
1150 }
1151
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001152 bool isVecListFourDAllLanes() const {
1153 if (!isSingleSpacedVectorAllLanes()) return false;
1154 return VectorList.Count == 4;
1155 }
1156
1157 bool isVecListFourQAllLanes() const {
1158 if (!isDoubleSpacedVectorAllLanes()) return false;
1159 return VectorList.Count == 4;
1160 }
1161
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001162 bool isSingleSpacedVectorIndexed() const {
1163 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1164 }
1165 bool isDoubleSpacedVectorIndexed() const {
1166 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1167 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001168 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001169 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001170 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1171 }
1172
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001173 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001174 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001175 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1176 }
1177
1178 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001179 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001180 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1181 }
1182
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001183 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001184 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001185 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1186 }
1187
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001188 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001189 if (!isSingleSpacedVectorIndexed()) return false;
1190 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1191 }
1192
1193 bool isVecListTwoQWordIndexed() const {
1194 if (!isDoubleSpacedVectorIndexed()) return false;
1195 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1196 }
1197
1198 bool isVecListTwoQHWordIndexed() const {
1199 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001200 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1201 }
1202
1203 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001204 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001205 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1206 }
1207
Jim Grosbach3a678af2012-01-23 21:53:26 +00001208 bool isVecListThreeDByteIndexed() const {
1209 if (!isSingleSpacedVectorIndexed()) return false;
1210 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1211 }
1212
1213 bool isVecListThreeDHWordIndexed() const {
1214 if (!isSingleSpacedVectorIndexed()) return false;
1215 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1216 }
1217
1218 bool isVecListThreeQWordIndexed() const {
1219 if (!isDoubleSpacedVectorIndexed()) return false;
1220 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1221 }
1222
1223 bool isVecListThreeQHWordIndexed() const {
1224 if (!isDoubleSpacedVectorIndexed()) return false;
1225 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1226 }
1227
1228 bool isVecListThreeDWordIndexed() const {
1229 if (!isSingleSpacedVectorIndexed()) return false;
1230 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1231 }
1232
Jim Grosbache983a132012-01-24 18:37:25 +00001233 bool isVecListFourDByteIndexed() const {
1234 if (!isSingleSpacedVectorIndexed()) return false;
1235 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1236 }
1237
1238 bool isVecListFourDHWordIndexed() const {
1239 if (!isSingleSpacedVectorIndexed()) return false;
1240 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1241 }
1242
1243 bool isVecListFourQWordIndexed() const {
1244 if (!isDoubleSpacedVectorIndexed()) return false;
1245 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1246 }
1247
1248 bool isVecListFourQHWordIndexed() const {
1249 if (!isDoubleSpacedVectorIndexed()) return false;
1250 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1251 }
1252
1253 bool isVecListFourDWordIndexed() const {
1254 if (!isSingleSpacedVectorIndexed()) return false;
1255 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1256 }
1257
Jim Grosbach460a9052011-10-07 23:56:00 +00001258 bool isVectorIndex8() const {
1259 if (Kind != k_VectorIndex) return false;
1260 return VectorIndex.Val < 8;
1261 }
1262 bool isVectorIndex16() const {
1263 if (Kind != k_VectorIndex) return false;
1264 return VectorIndex.Val < 4;
1265 }
1266 bool isVectorIndex32() const {
1267 if (Kind != k_VectorIndex) return false;
1268 return VectorIndex.Val < 2;
1269 }
1270
Jim Grosbach0e387b22011-10-17 22:26:03 +00001271 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001272 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001273 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1274 // Must be a constant.
1275 if (!CE) return false;
1276 int64_t Value = CE->getValue();
1277 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1278 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001279 return Value >= 0 && Value < 256;
1280 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001281
Jim Grosbachea461102011-10-17 23:09:09 +00001282 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001283 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001284 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1285 // Must be a constant.
1286 if (!CE) return false;
1287 int64_t Value = CE->getValue();
1288 // i16 value in the range [0,255] or [0x0100, 0xff00]
1289 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1290 }
1291
Jim Grosbach6248a542011-10-18 00:22:00 +00001292 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001293 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001294 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1295 // Must be a constant.
1296 if (!CE) return false;
1297 int64_t Value = CE->getValue();
1298 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1299 return (Value >= 0 && Value < 256) ||
1300 (Value >= 0x0100 && Value <= 0xff00) ||
1301 (Value >= 0x010000 && Value <= 0xff0000) ||
1302 (Value >= 0x01000000 && Value <= 0xff000000);
1303 }
1304
1305 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001306 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1308 // Must be a constant.
1309 if (!CE) return false;
1310 int64_t Value = CE->getValue();
1311 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1312 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1313 return (Value >= 0 && Value < 256) ||
1314 (Value >= 0x0100 && Value <= 0xff00) ||
1315 (Value >= 0x010000 && Value <= 0xff0000) ||
1316 (Value >= 0x01000000 && Value <= 0xff000000) ||
1317 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1318 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1319 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001320 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001321 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001322 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1323 // Must be a constant.
1324 if (!CE) return false;
1325 int64_t Value = ~CE->getValue();
1326 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1327 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1328 return (Value >= 0 && Value < 256) ||
1329 (Value >= 0x0100 && Value <= 0xff00) ||
1330 (Value >= 0x010000 && Value <= 0xff0000) ||
1331 (Value >= 0x01000000 && Value <= 0xff000000) ||
1332 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1333 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1334 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001335
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001336 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001337 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001338 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1339 // Must be a constant.
1340 if (!CE) return false;
1341 uint64_t Value = CE->getValue();
1342 // i64 value with each byte being either 0 or 0xff.
1343 for (unsigned i = 0; i < 8; ++i)
1344 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1345 return true;
1346 }
1347
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001348 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001349 // Add as immediates when possible. Null MCExpr = 0.
1350 if (Expr == 0)
1351 Inst.addOperand(MCOperand::CreateImm(0));
1352 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001353 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1354 else
1355 Inst.addOperand(MCOperand::CreateExpr(Expr));
1356 }
1357
Daniel Dunbar8462b302010-08-11 06:36:53 +00001358 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001359 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001360 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001361 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1362 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001363 }
1364
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001365 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1366 assert(N == 1 && "Invalid number of operands!");
1367 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1368 }
1369
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001370 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
1372 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1373 }
1374
1375 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
1377 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1378 }
1379
Jim Grosbach89df9962011-08-26 21:43:41 +00001380 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
1382 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1383 }
1384
1385 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1388 }
1389
Jim Grosbachd67641b2010-12-06 18:21:12 +00001390 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392 Inst.addOperand(MCOperand::CreateReg(getReg()));
1393 }
1394
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001395 void addRegOperands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 Inst.addOperand(MCOperand::CreateReg(getReg()));
1398 }
1399
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001400 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001401 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001402 assert(isRegShiftedReg() &&
1403 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001404 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1405 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001406 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001407 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001408 }
1409
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001410 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001411 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001412 assert(isRegShiftedImm() &&
1413 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001414 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001415 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001416 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001417 }
1418
Jim Grosbach580f4a92011-07-25 22:20:28 +00001419 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001420 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001421 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1422 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001423 }
1424
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001425 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001426 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001427 const SmallVectorImpl<unsigned> &RegList = getRegList();
1428 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001429 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1430 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001431 }
1432
Bill Wendling0f630752010-11-17 04:32:08 +00001433 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1434 addRegListOperands(Inst, N);
1435 }
1436
1437 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1438 addRegListOperands(Inst, N);
1439 }
1440
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001441 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1444 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1445 }
1446
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001447 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1448 assert(N == 1 && "Invalid number of operands!");
1449 // Munge the lsb/width into a bitfield mask.
1450 unsigned lsb = Bitfield.LSB;
1451 unsigned width = Bitfield.Width;
1452 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1453 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1454 (32 - (lsb + width)));
1455 Inst.addOperand(MCOperand::CreateImm(Mask));
1456 }
1457
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001458 void addImmOperands(MCInst &Inst, unsigned N) const {
1459 assert(N == 1 && "Invalid number of operands!");
1460 addExpr(Inst, getImm());
1461 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001462
Jim Grosbach4050bc42011-12-22 22:19:05 +00001463 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
1465 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1466 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1467 }
1468
1469 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1470 assert(N == 1 && "Invalid number of operands!");
1471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1472 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1473 }
1474
Jim Grosbach9d390362011-10-03 23:38:36 +00001475 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1478 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1479 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001480 }
1481
Jim Grosbacha77295d2011-09-08 22:07:06 +00001482 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 // FIXME: We really want to scale the value here, but the LDRD/STRD
1485 // instruction don't encode operands that way yet.
1486 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1487 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1488 }
1489
Jim Grosbach72f39f82011-08-24 21:22:15 +00001490 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 // The immediate is scaled by four in the encoding and is stored
1493 // in the MCInst as such. Lop off the low two bits here.
1494 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1495 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1496 }
1497
1498 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1499 assert(N == 1 && "Invalid number of operands!");
1500 // The immediate is scaled by four in the encoding and is stored
1501 // in the MCInst as such. Lop off the low two bits here.
1502 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1503 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1504 }
1505
Jim Grosbachf4943352011-07-25 23:09:14 +00001506 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 // The constant encodes as the immediate-1, and we store in the instruction
1509 // the bits as encoded, so subtract off one here.
1510 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1511 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1512 }
1513
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001514 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 // The constant encodes as the immediate-1, and we store in the instruction
1517 // the bits as encoded, so subtract off one here.
1518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1519 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1520 }
1521
Jim Grosbach70939ee2011-08-17 21:51:27 +00001522 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 1 && "Invalid number of operands!");
1524 // The constant encodes as the immediate, except for 32, which encodes as
1525 // zero.
1526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1527 unsigned Imm = CE->getValue();
1528 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1529 }
1530
Jim Grosbachf6c05252011-07-21 17:23:04 +00001531 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1534 // the instruction as well.
1535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1536 int Val = CE->getValue();
1537 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1538 }
1539
Jim Grosbach89a63372011-10-28 22:36:30 +00001540 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 // The operand is actually a t2_so_imm, but we have its bitwise
1543 // negation in the assembly source, so twiddle it here.
1544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1545 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1546 }
1547
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001548 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1549 assert(N == 1 && "Invalid number of operands!");
1550 // The operand is actually a t2_so_imm, but we have its
1551 // negation in the assembly source, so twiddle it here.
1552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1553 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1554 }
1555
Jim Grosbache70ec842011-10-28 22:50:54 +00001556 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // The operand is actually a so_imm, but we have its bitwise
1559 // negation in the assembly source, so twiddle it here.
1560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1561 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1562 }
1563
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001564 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 // The operand is actually a so_imm, but we have its
1567 // negation in the assembly source, so twiddle it here.
1568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1569 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1570 }
1571
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001572 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 1 && "Invalid number of operands!");
1574 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1575 }
1576
Jim Grosbach7ce05792011-08-03 23:50:40 +00001577 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001579 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001580 }
1581
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001582 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 int32_t Imm = Memory.OffsetImm->getValue();
1585 // FIXME: Handle #-0
1586 if (Imm == INT32_MIN) Imm = 0;
1587 Inst.addOperand(MCOperand::CreateImm(Imm));
1588 }
1589
Jim Grosbach57dcb852011-10-11 17:29:55 +00001590 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 2 && "Invalid number of operands!");
1592 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1593 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1594 }
1595
Jim Grosbach7ce05792011-08-03 23:50:40 +00001596 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1597 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001598 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1599 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001600 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1601 // Special case for #-0
1602 if (Val == INT32_MIN) Val = 0;
1603 if (Val < 0) Val = -Val;
1604 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1605 } else {
1606 // For register offset, we encode the shift type and negation flag
1607 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001608 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1609 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001610 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001611 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1612 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001613 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001614 }
1615
Jim Grosbach039c2e12011-08-04 23:01:30 +00001616 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1617 assert(N == 2 && "Invalid number of operands!");
1618 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1619 assert(CE && "non-constant AM2OffsetImm operand!");
1620 int32_t Val = CE->getValue();
1621 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1622 // Special case for #-0
1623 if (Val == INT32_MIN) Val = 0;
1624 if (Val < 0) Val = -Val;
1625 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1626 Inst.addOperand(MCOperand::CreateReg(0));
1627 Inst.addOperand(MCOperand::CreateImm(Val));
1628 }
1629
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001630 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1631 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001632 // If we have an immediate that's not a constant, treat it as a label
1633 // reference needing a fixup. If it is a constant, it's something else
1634 // and we reject it.
1635 if (isImm()) {
1636 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1637 Inst.addOperand(MCOperand::CreateReg(0));
1638 Inst.addOperand(MCOperand::CreateImm(0));
1639 return;
1640 }
1641
Jim Grosbache53c87b2011-10-11 15:59:20 +00001642 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1643 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001644 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1645 // Special case for #-0
1646 if (Val == INT32_MIN) Val = 0;
1647 if (Val < 0) Val = -Val;
1648 Val = ARM_AM::getAM3Opc(AddSub, Val);
1649 } else {
1650 // For register offset, we encode the shift type and negation flag
1651 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001652 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001653 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001654 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1655 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001656 Inst.addOperand(MCOperand::CreateImm(Val));
1657 }
1658
1659 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1660 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001661 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001662 int32_t Val =
1663 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1664 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1665 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001666 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001667 }
1668
1669 // Constant offset.
1670 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1671 int32_t Val = CE->getValue();
1672 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1673 // Special case for #-0
1674 if (Val == INT32_MIN) Val = 0;
1675 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001676 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001677 Inst.addOperand(MCOperand::CreateReg(0));
1678 Inst.addOperand(MCOperand::CreateImm(Val));
1679 }
1680
Jim Grosbach7ce05792011-08-03 23:50:40 +00001681 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1682 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001683 // If we have an immediate that's not a constant, treat it as a label
1684 // reference needing a fixup. If it is a constant, it's something else
1685 // and we reject it.
1686 if (isImm()) {
1687 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1688 Inst.addOperand(MCOperand::CreateImm(0));
1689 return;
1690 }
1691
Jim Grosbach7ce05792011-08-03 23:50:40 +00001692 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001693 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001694 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1695 // Special case for #-0
1696 if (Val == INT32_MIN) Val = 0;
1697 if (Val < 0) Val = -Val;
1698 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001699 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001700 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001701 }
1702
Jim Grosbacha77295d2011-09-08 22:07:06 +00001703 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1704 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001705 // If we have an immediate that's not a constant, treat it as a label
1706 // reference needing a fixup. If it is a constant, it's something else
1707 // and we reject it.
1708 if (isImm()) {
1709 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1710 Inst.addOperand(MCOperand::CreateImm(0));
1711 return;
1712 }
1713
Jim Grosbache53c87b2011-10-11 15:59:20 +00001714 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1715 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001716 Inst.addOperand(MCOperand::CreateImm(Val));
1717 }
1718
Jim Grosbachb6aed502011-09-09 18:37:27 +00001719 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1720 assert(N == 2 && "Invalid number of operands!");
1721 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001722 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1723 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001724 Inst.addOperand(MCOperand::CreateImm(Val));
1725 }
1726
Jim Grosbach7ce05792011-08-03 23:50:40 +00001727 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1728 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001729 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1730 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001731 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001732 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001733
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001734 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1735 addMemImm8OffsetOperands(Inst, N);
1736 }
1737
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001738 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001739 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001740 }
1741
1742 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1743 assert(N == 2 && "Invalid number of operands!");
1744 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001745 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001746 addExpr(Inst, getImm());
1747 Inst.addOperand(MCOperand::CreateImm(0));
1748 return;
1749 }
1750
1751 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001752 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1753 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001754 Inst.addOperand(MCOperand::CreateImm(Val));
1755 }
1756
Jim Grosbach7ce05792011-08-03 23:50:40 +00001757 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1758 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001759 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001760 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001761 addExpr(Inst, getImm());
1762 Inst.addOperand(MCOperand::CreateImm(0));
1763 return;
1764 }
1765
1766 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001767 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1768 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001769 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001770 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001771
Jim Grosbach7f739be2011-09-19 22:21:13 +00001772 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1773 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001774 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1775 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001776 }
1777
1778 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1779 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001780 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1781 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001782 }
1783
Jim Grosbach7ce05792011-08-03 23:50:40 +00001784 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1785 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001786 unsigned Val =
1787 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1788 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001789 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1790 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001791 Inst.addOperand(MCOperand::CreateImm(Val));
1792 }
1793
Jim Grosbachab899c12011-09-07 23:10:15 +00001794 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001796 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1797 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1798 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001799 }
1800
Jim Grosbach7ce05792011-08-03 23:50:40 +00001801 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1802 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001803 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1804 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001805 }
1806
Jim Grosbach60f91a32011-08-19 17:55:24 +00001807 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1808 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001809 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1810 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001811 Inst.addOperand(MCOperand::CreateImm(Val));
1812 }
1813
Jim Grosbach38466302011-08-19 18:55:51 +00001814 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1815 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001816 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1817 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001818 Inst.addOperand(MCOperand::CreateImm(Val));
1819 }
1820
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001821 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1822 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001823 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1824 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001825 Inst.addOperand(MCOperand::CreateImm(Val));
1826 }
1827
Jim Grosbachecd85892011-08-19 18:13:48 +00001828 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001830 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1831 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001832 Inst.addOperand(MCOperand::CreateImm(Val));
1833 }
1834
Jim Grosbach7ce05792011-08-03 23:50:40 +00001835 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1836 assert(N == 1 && "Invalid number of operands!");
1837 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1838 assert(CE && "non-constant post-idx-imm8 operand!");
1839 int Imm = CE->getValue();
1840 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001841 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001842 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1843 Inst.addOperand(MCOperand::CreateImm(Imm));
1844 }
1845
Jim Grosbach2bd01182011-10-11 21:55:36 +00001846 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1847 assert(N == 1 && "Invalid number of operands!");
1848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1849 assert(CE && "non-constant post-idx-imm8s4 operand!");
1850 int Imm = CE->getValue();
1851 bool isAdd = Imm >= 0;
1852 if (Imm == INT32_MIN) Imm = 0;
1853 // Immediate is scaled by 4.
1854 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1855 Inst.addOperand(MCOperand::CreateImm(Imm));
1856 }
1857
Jim Grosbach7ce05792011-08-03 23:50:40 +00001858 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 2 && "Invalid number of operands!");
1860 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001861 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1862 }
1863
1864 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1865 assert(N == 2 && "Invalid number of operands!");
1866 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1867 // The sign, shift type, and shift amount are encoded in a single operand
1868 // using the AM2 encoding helpers.
1869 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1870 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1871 PostIdxReg.ShiftTy);
1872 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001873 }
1874
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001875 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1876 assert(N == 1 && "Invalid number of operands!");
1877 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1878 }
1879
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001880 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1881 assert(N == 1 && "Invalid number of operands!");
1882 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1883 }
1884
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001885 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001886 assert(N == 1 && "Invalid number of operands!");
1887 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1888 }
1889
Jim Grosbach7636bf62011-12-02 00:35:16 +00001890 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1891 assert(N == 2 && "Invalid number of operands!");
1892 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1893 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1894 }
1895
Jim Grosbach460a9052011-10-07 23:56:00 +00001896 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1897 assert(N == 1 && "Invalid number of operands!");
1898 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1899 }
1900
1901 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1902 assert(N == 1 && "Invalid number of operands!");
1903 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1904 }
1905
1906 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1907 assert(N == 1 && "Invalid number of operands!");
1908 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1909 }
1910
Jim Grosbach0e387b22011-10-17 22:26:03 +00001911 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1912 assert(N == 1 && "Invalid number of operands!");
1913 // The immediate encodes the type of constant as well as the value.
1914 // Mask in that this is an i8 splat.
1915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1916 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1917 }
1918
Jim Grosbachea461102011-10-17 23:09:09 +00001919 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1920 assert(N == 1 && "Invalid number of operands!");
1921 // The immediate encodes the type of constant as well as the value.
1922 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1923 unsigned Value = CE->getValue();
1924 if (Value >= 256)
1925 Value = (Value >> 8) | 0xa00;
1926 else
1927 Value |= 0x800;
1928 Inst.addOperand(MCOperand::CreateImm(Value));
1929 }
1930
Jim Grosbach6248a542011-10-18 00:22:00 +00001931 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1932 assert(N == 1 && "Invalid number of operands!");
1933 // The immediate encodes the type of constant as well as the value.
1934 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1935 unsigned Value = CE->getValue();
1936 if (Value >= 256 && Value <= 0xff00)
1937 Value = (Value >> 8) | 0x200;
1938 else if (Value > 0xffff && Value <= 0xff0000)
1939 Value = (Value >> 16) | 0x400;
1940 else if (Value > 0xffffff)
1941 Value = (Value >> 24) | 0x600;
1942 Inst.addOperand(MCOperand::CreateImm(Value));
1943 }
1944
1945 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1946 assert(N == 1 && "Invalid number of operands!");
1947 // The immediate encodes the type of constant as well as the value.
1948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1949 unsigned Value = CE->getValue();
1950 if (Value >= 256 && Value <= 0xffff)
1951 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1952 else if (Value > 0xffff && Value <= 0xffffff)
1953 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1954 else if (Value > 0xffffff)
1955 Value = (Value >> 24) | 0x600;
1956 Inst.addOperand(MCOperand::CreateImm(Value));
1957 }
1958
Jim Grosbach9b087852011-12-19 23:51:07 +00001959 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1960 assert(N == 1 && "Invalid number of operands!");
1961 // The immediate encodes the type of constant as well as the value.
1962 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1963 unsigned Value = ~CE->getValue();
1964 if (Value >= 256 && Value <= 0xffff)
1965 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1966 else if (Value > 0xffff && Value <= 0xffffff)
1967 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1968 else if (Value > 0xffffff)
1969 Value = (Value >> 24) | 0x600;
1970 Inst.addOperand(MCOperand::CreateImm(Value));
1971 }
1972
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001973 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1974 assert(N == 1 && "Invalid number of operands!");
1975 // The immediate encodes the type of constant as well as the value.
1976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1977 uint64_t Value = CE->getValue();
1978 unsigned Imm = 0;
1979 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1980 Imm |= (Value & 1) << i;
1981 }
1982 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1983 }
1984
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001985 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001986
Jim Grosbach89df9962011-08-26 21:43:41 +00001987 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001989 Op->ITMask.Mask = Mask;
1990 Op->StartLoc = S;
1991 Op->EndLoc = S;
1992 return Op;
1993 }
1994
Chris Lattner3a697562010-10-28 17:20:03 +00001995 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001996 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001997 Op->CC.Val = CC;
1998 Op->StartLoc = S;
1999 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002000 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002001 }
2002
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002003 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002004 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002005 Op->Cop.Val = CopVal;
2006 Op->StartLoc = S;
2007 Op->EndLoc = S;
2008 return Op;
2009 }
2010
2011 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002012 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002013 Op->Cop.Val = CopVal;
2014 Op->StartLoc = S;
2015 Op->EndLoc = S;
2016 return Op;
2017 }
2018
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002019 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2020 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2021 Op->Cop.Val = Val;
2022 Op->StartLoc = S;
2023 Op->EndLoc = E;
2024 return Op;
2025 }
2026
Jim Grosbachd67641b2010-12-06 18:21:12 +00002027 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002028 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002029 Op->Reg.RegNum = RegNum;
2030 Op->StartLoc = S;
2031 Op->EndLoc = S;
2032 return Op;
2033 }
2034
Chris Lattner3a697562010-10-28 17:20:03 +00002035 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002036 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002037 Op->Tok.Data = Str.data();
2038 Op->Tok.Length = Str.size();
2039 Op->StartLoc = S;
2040 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002041 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002042 }
2043
Bill Wendling50d0f582010-11-18 23:43:05 +00002044 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002046 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002047 Op->StartLoc = S;
2048 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002049 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002050 }
2051
Jim Grosbache8606dc2011-07-13 17:50:29 +00002052 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2053 unsigned SrcReg,
2054 unsigned ShiftReg,
2055 unsigned ShiftImm,
2056 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002057 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002058 Op->RegShiftedReg.ShiftTy = ShTy;
2059 Op->RegShiftedReg.SrcReg = SrcReg;
2060 Op->RegShiftedReg.ShiftReg = ShiftReg;
2061 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002062 Op->StartLoc = S;
2063 Op->EndLoc = E;
2064 return Op;
2065 }
2066
Owen Anderson92a20222011-07-21 18:54:16 +00002067 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2068 unsigned SrcReg,
2069 unsigned ShiftImm,
2070 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002071 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002072 Op->RegShiftedImm.ShiftTy = ShTy;
2073 Op->RegShiftedImm.SrcReg = SrcReg;
2074 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002075 Op->StartLoc = S;
2076 Op->EndLoc = E;
2077 return Op;
2078 }
2079
Jim Grosbach580f4a92011-07-25 22:20:28 +00002080 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002081 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002082 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002083 Op->ShifterImm.isASR = isASR;
2084 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002085 Op->StartLoc = S;
2086 Op->EndLoc = E;
2087 return Op;
2088 }
2089
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002090 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002091 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002092 Op->RotImm.Imm = Imm;
2093 Op->StartLoc = S;
2094 Op->EndLoc = E;
2095 return Op;
2096 }
2097
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002098 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2099 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002100 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002101 Op->Bitfield.LSB = LSB;
2102 Op->Bitfield.Width = Width;
2103 Op->StartLoc = S;
2104 Op->EndLoc = E;
2105 return Op;
2106 }
2107
Bill Wendling7729e062010-11-09 22:44:22 +00002108 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002109 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002110 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002111 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002112
Jim Grosbachd300b942011-09-13 22:56:44 +00002113 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002114 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002115 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002116 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002117 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002118
2119 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002120 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002121 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002122 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002123 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002124 Op->StartLoc = StartLoc;
2125 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002126 return Op;
2127 }
2128
Jim Grosbach862019c2011-10-18 23:02:30 +00002129 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002130 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002131 ARMOperand *Op = new ARMOperand(k_VectorList);
2132 Op->VectorList.RegNum = RegNum;
2133 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002134 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002135 Op->StartLoc = S;
2136 Op->EndLoc = E;
2137 return Op;
2138 }
2139
Jim Grosbach98b05a52011-11-30 01:09:44 +00002140 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002141 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002142 SMLoc S, SMLoc E) {
2143 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2144 Op->VectorList.RegNum = RegNum;
2145 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002146 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002147 Op->StartLoc = S;
2148 Op->EndLoc = E;
2149 return Op;
2150 }
2151
Jim Grosbach7636bf62011-12-02 00:35:16 +00002152 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002153 unsigned Index,
2154 bool isDoubleSpaced,
2155 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002156 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2157 Op->VectorList.RegNum = RegNum;
2158 Op->VectorList.Count = Count;
2159 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002160 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002161 Op->StartLoc = S;
2162 Op->EndLoc = E;
2163 return Op;
2164 }
2165
Jim Grosbach460a9052011-10-07 23:56:00 +00002166 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2167 MCContext &Ctx) {
2168 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2169 Op->VectorIndex.Val = Idx;
2170 Op->StartLoc = S;
2171 Op->EndLoc = E;
2172 return Op;
2173 }
2174
Chris Lattner3a697562010-10-28 17:20:03 +00002175 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002176 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002177 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002178 Op->StartLoc = S;
2179 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002180 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002181 }
2182
Jim Grosbach7ce05792011-08-03 23:50:40 +00002183 static ARMOperand *CreateMem(unsigned BaseRegNum,
2184 const MCConstantExpr *OffsetImm,
2185 unsigned OffsetRegNum,
2186 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002187 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002188 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002189 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002190 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002191 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002192 Op->Memory.BaseRegNum = BaseRegNum;
2193 Op->Memory.OffsetImm = OffsetImm;
2194 Op->Memory.OffsetRegNum = OffsetRegNum;
2195 Op->Memory.ShiftType = ShiftType;
2196 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002197 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002198 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002199 Op->StartLoc = S;
2200 Op->EndLoc = E;
2201 return Op;
2202 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002203
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002204 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2205 ARM_AM::ShiftOpc ShiftTy,
2206 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002207 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002208 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002209 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002210 Op->PostIdxReg.isAdd = isAdd;
2211 Op->PostIdxReg.ShiftTy = ShiftTy;
2212 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002213 Op->StartLoc = S;
2214 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002215 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002216 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002217
2218 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002219 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002220 Op->MBOpt.Val = Opt;
2221 Op->StartLoc = S;
2222 Op->EndLoc = S;
2223 return Op;
2224 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002225
2226 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002227 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002228 Op->IFlags.Val = IFlags;
2229 Op->StartLoc = S;
2230 Op->EndLoc = S;
2231 return Op;
2232 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002233
2234 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002235 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002236 Op->MMask.Val = MMask;
2237 Op->StartLoc = S;
2238 Op->EndLoc = S;
2239 return Op;
2240 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002241};
2242
2243} // end anonymous namespace.
2244
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002245void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002246 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002247 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002248 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002249 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002250 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002251 OS << "<ccout " << getReg() << ">";
2252 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002253 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002254 static const char *MaskStr[] = {
2255 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2256 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2257 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002258 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2259 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2260 break;
2261 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002262 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002263 OS << "<coprocessor number: " << getCoproc() << ">";
2264 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002265 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002266 OS << "<coprocessor register: " << getCoproc() << ">";
2267 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002268 case k_CoprocOption:
2269 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2270 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002271 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002272 OS << "<mask: " << getMSRMask() << ">";
2273 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002274 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002275 getImm()->print(OS);
2276 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002277 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002278 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2279 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002280 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002281 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002282 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002283 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002284 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002285 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002286 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2287 << PostIdxReg.RegNum;
2288 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2289 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2290 << PostIdxReg.ShiftImm;
2291 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002292 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002293 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002294 OS << "<ARM_PROC::";
2295 unsigned IFlags = getProcIFlags();
2296 for (int i=2; i >= 0; --i)
2297 if (IFlags & (1 << i))
2298 OS << ARM_PROC::IFlagsToString(1 << i);
2299 OS << ">";
2300 break;
2301 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002302 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002303 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002304 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002305 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002306 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2307 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002308 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002309 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002310 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002311 << RegShiftedReg.SrcReg << " "
2312 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2313 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002314 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002315 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002316 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002317 << RegShiftedImm.SrcReg << " "
2318 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2319 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002320 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002321 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002322 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2323 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002324 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002325 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2326 << ", width: " << Bitfield.Width << ">";
2327 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002328 case k_RegisterList:
2329 case k_DPRRegisterList:
2330 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002331 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002332
Bill Wendling5fa22a12010-11-09 23:28:44 +00002333 const SmallVectorImpl<unsigned> &RegList = getRegList();
2334 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002335 I = RegList.begin(), E = RegList.end(); I != E; ) {
2336 OS << *I;
2337 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002338 }
2339
2340 OS << ">";
2341 break;
2342 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002343 case k_VectorList:
2344 OS << "<vector_list " << VectorList.Count << " * "
2345 << VectorList.RegNum << ">";
2346 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002347 case k_VectorListAllLanes:
2348 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2349 << VectorList.RegNum << ">";
2350 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002351 case k_VectorListIndexed:
2352 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2353 << VectorList.Count << " * " << VectorList.RegNum << ">";
2354 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002355 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002356 OS << "'" << getToken() << "'";
2357 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002358 case k_VectorIndex:
2359 OS << "<vectorindex " << getVectorIndex() << ">";
2360 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002361 }
2362}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002363
2364/// @name Auto-generated Match Functions
2365/// {
2366
2367static unsigned MatchRegisterName(StringRef Name);
2368
2369/// }
2370
Bob Wilson69df7232011-02-03 21:46:10 +00002371bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2372 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002373 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002374 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002375 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002376
2377 return (RegNo == (unsigned)-1);
2378}
2379
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002380/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002381/// and if it is a register name the token is eaten and the register number is
2382/// returned. Otherwise return -1.
2383///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002384int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002385 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002386 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002387
Benjamin Kramer59085362011-11-06 20:37:06 +00002388 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002389 unsigned RegNum = MatchRegisterName(lowerCase);
2390 if (!RegNum) {
2391 RegNum = StringSwitch<unsigned>(lowerCase)
2392 .Case("r13", ARM::SP)
2393 .Case("r14", ARM::LR)
2394 .Case("r15", ARM::PC)
2395 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002396 // Additional register name aliases for 'gas' compatibility.
2397 .Case("a1", ARM::R0)
2398 .Case("a2", ARM::R1)
2399 .Case("a3", ARM::R2)
2400 .Case("a4", ARM::R3)
2401 .Case("v1", ARM::R4)
2402 .Case("v2", ARM::R5)
2403 .Case("v3", ARM::R6)
2404 .Case("v4", ARM::R7)
2405 .Case("v5", ARM::R8)
2406 .Case("v6", ARM::R9)
2407 .Case("v7", ARM::R10)
2408 .Case("v8", ARM::R11)
2409 .Case("sb", ARM::R9)
2410 .Case("sl", ARM::R10)
2411 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002412 .Default(0);
2413 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002414 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002415 // Check for aliases registered via .req. Canonicalize to lower case.
2416 // That's more consistent since register names are case insensitive, and
2417 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2418 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002419 // If no match, return failure.
2420 if (Entry == RegisterReqs.end())
2421 return -1;
2422 Parser.Lex(); // Eat identifier token.
2423 return Entry->getValue();
2424 }
Bob Wilson69df7232011-02-03 21:46:10 +00002425
Chris Lattnere5658fa2010-10-30 04:09:10 +00002426 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002427
Chris Lattnere5658fa2010-10-30 04:09:10 +00002428 return RegNum;
2429}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002430
Jim Grosbach19906722011-07-13 18:49:30 +00002431// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2432// If a recoverable error occurs, return 1. If an irrecoverable error
2433// occurs, return -1. An irrecoverable error is one where tokens have been
2434// consumed in the process of trying to parse the shifter (i.e., when it is
2435// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002436int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002437 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2438 SMLoc S = Parser.getTok().getLoc();
2439 const AsmToken &Tok = Parser.getTok();
2440 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2441
Benjamin Kramer59085362011-11-06 20:37:06 +00002442 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002443 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002444 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002445 .Case("lsl", ARM_AM::lsl)
2446 .Case("lsr", ARM_AM::lsr)
2447 .Case("asr", ARM_AM::asr)
2448 .Case("ror", ARM_AM::ror)
2449 .Case("rrx", ARM_AM::rrx)
2450 .Default(ARM_AM::no_shift);
2451
2452 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002453 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002454
Jim Grosbache8606dc2011-07-13 17:50:29 +00002455 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002456
Jim Grosbache8606dc2011-07-13 17:50:29 +00002457 // The source register for the shift has already been added to the
2458 // operand list, so we need to pop it off and combine it into the shifted
2459 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002460 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002461 if (!PrevOp->isReg())
2462 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2463 int SrcReg = PrevOp->getReg();
2464 int64_t Imm = 0;
2465 int ShiftReg = 0;
2466 if (ShiftTy == ARM_AM::rrx) {
2467 // RRX Doesn't have an explicit shift amount. The encoder expects
2468 // the shift register to be the same as the source register. Seems odd,
2469 // but OK.
2470 ShiftReg = SrcReg;
2471 } else {
2472 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002473 if (Parser.getTok().is(AsmToken::Hash) ||
2474 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002475 Parser.Lex(); // Eat hash.
2476 SMLoc ImmLoc = Parser.getTok().getLoc();
2477 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002478 if (getParser().ParseExpression(ShiftExpr)) {
2479 Error(ImmLoc, "invalid immediate shift value");
2480 return -1;
2481 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002482 // The expression must be evaluatable as an immediate.
2483 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002484 if (!CE) {
2485 Error(ImmLoc, "invalid immediate shift value");
2486 return -1;
2487 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002488 // Range check the immediate.
2489 // lsl, ror: 0 <= imm <= 31
2490 // lsr, asr: 0 <= imm <= 32
2491 Imm = CE->getValue();
2492 if (Imm < 0 ||
2493 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2494 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002495 Error(ImmLoc, "immediate shift value out of range");
2496 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002497 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002498 // shift by zero is a nop. Always send it through as lsl.
2499 // ('as' compatibility)
2500 if (Imm == 0)
2501 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002502 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002503 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002504 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002505 if (ShiftReg == -1) {
2506 Error (L, "expected immediate or register in shift operand");
2507 return -1;
2508 }
2509 } else {
2510 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002511 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002512 return -1;
2513 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002514 }
2515
Owen Anderson92a20222011-07-21 18:54:16 +00002516 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2517 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002518 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002519 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002520 else
2521 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2522 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002523
Jim Grosbach19906722011-07-13 18:49:30 +00002524 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002525}
2526
2527
Bill Wendling50d0f582010-11-18 23:43:05 +00002528/// Try to parse a register name. The token must be an Identifier when called.
2529/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2530/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002531///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002532/// TODO this is likely to change to allow different register types and or to
2533/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002534bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002535tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002536 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002537 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002538 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002539 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002540
Bill Wendling50d0f582010-11-18 23:43:05 +00002541 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002542
Chris Lattnere5658fa2010-10-30 04:09:10 +00002543 const AsmToken &ExclaimTok = Parser.getTok();
2544 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002545 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2546 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002547 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002548 return false;
2549 }
2550
2551 // Also check for an index operand. This is only legal for vector registers,
2552 // but that'll get caught OK in operand matching, so we don't need to
2553 // explicitly filter everything else out here.
2554 if (Parser.getTok().is(AsmToken::LBrac)) {
2555 SMLoc SIdx = Parser.getTok().getLoc();
2556 Parser.Lex(); // Eat left bracket token.
2557
2558 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002559 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002560 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002561 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002562 if (!MCE)
2563 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002564
2565 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002566 if (Parser.getTok().isNot(AsmToken::RBrac))
2567 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002568
2569 Parser.Lex(); // Eat right bracket token.
2570
2571 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2572 SIdx, E,
2573 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002574 }
2575
Bill Wendling50d0f582010-11-18 23:43:05 +00002576 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002577}
2578
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002579/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2580/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2581/// "c5", ...
2582static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002583 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2584 // but efficient.
2585 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002586 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002587 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002588 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002589 return -1;
2590 switch (Name[1]) {
2591 default: return -1;
2592 case '0': return 0;
2593 case '1': return 1;
2594 case '2': return 2;
2595 case '3': return 3;
2596 case '4': return 4;
2597 case '5': return 5;
2598 case '6': return 6;
2599 case '7': return 7;
2600 case '8': return 8;
2601 case '9': return 9;
2602 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002603 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002604 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002605 return -1;
2606 switch (Name[2]) {
2607 default: return -1;
2608 case '0': return 10;
2609 case '1': return 11;
2610 case '2': return 12;
2611 case '3': return 13;
2612 case '4': return 14;
2613 case '5': return 15;
2614 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002615 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002616}
2617
Jim Grosbach89df9962011-08-26 21:43:41 +00002618/// parseITCondCode - Try to parse a condition code for an IT instruction.
2619ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2620parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2621 SMLoc S = Parser.getTok().getLoc();
2622 const AsmToken &Tok = Parser.getTok();
2623 if (!Tok.is(AsmToken::Identifier))
2624 return MatchOperand_NoMatch;
2625 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2626 .Case("eq", ARMCC::EQ)
2627 .Case("ne", ARMCC::NE)
2628 .Case("hs", ARMCC::HS)
2629 .Case("cs", ARMCC::HS)
2630 .Case("lo", ARMCC::LO)
2631 .Case("cc", ARMCC::LO)
2632 .Case("mi", ARMCC::MI)
2633 .Case("pl", ARMCC::PL)
2634 .Case("vs", ARMCC::VS)
2635 .Case("vc", ARMCC::VC)
2636 .Case("hi", ARMCC::HI)
2637 .Case("ls", ARMCC::LS)
2638 .Case("ge", ARMCC::GE)
2639 .Case("lt", ARMCC::LT)
2640 .Case("gt", ARMCC::GT)
2641 .Case("le", ARMCC::LE)
2642 .Case("al", ARMCC::AL)
2643 .Default(~0U);
2644 if (CC == ~0U)
2645 return MatchOperand_NoMatch;
2646 Parser.Lex(); // Eat the token.
2647
2648 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2649
2650 return MatchOperand_Success;
2651}
2652
Jim Grosbach43904292011-07-25 20:14:50 +00002653/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002654/// token must be an Identifier when called, and if it is a coprocessor
2655/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002656ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002657parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002658 SMLoc S = Parser.getTok().getLoc();
2659 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002660 if (Tok.isNot(AsmToken::Identifier))
2661 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002662
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002663 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002664 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002665 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002666
2667 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002668 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002669 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002670}
2671
Jim Grosbach43904292011-07-25 20:14:50 +00002672/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002673/// token must be an Identifier when called, and if it is a coprocessor
2674/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002675ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002676parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002677 SMLoc S = Parser.getTok().getLoc();
2678 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002679 if (Tok.isNot(AsmToken::Identifier))
2680 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002681
2682 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2683 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002684 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002685
2686 Parser.Lex(); // Eat identifier token.
2687 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002688 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002689}
2690
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002691/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2692/// coproc_option : '{' imm0_255 '}'
2693ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2694parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2695 SMLoc S = Parser.getTok().getLoc();
2696
2697 // If this isn't a '{', this isn't a coprocessor immediate operand.
2698 if (Parser.getTok().isNot(AsmToken::LCurly))
2699 return MatchOperand_NoMatch;
2700 Parser.Lex(); // Eat the '{'
2701
2702 const MCExpr *Expr;
2703 SMLoc Loc = Parser.getTok().getLoc();
2704 if (getParser().ParseExpression(Expr)) {
2705 Error(Loc, "illegal expression");
2706 return MatchOperand_ParseFail;
2707 }
2708 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2709 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2710 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2711 return MatchOperand_ParseFail;
2712 }
2713 int Val = CE->getValue();
2714
2715 // Check for and consume the closing '}'
2716 if (Parser.getTok().isNot(AsmToken::RCurly))
2717 return MatchOperand_ParseFail;
2718 SMLoc E = Parser.getTok().getLoc();
2719 Parser.Lex(); // Eat the '}'
2720
2721 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2722 return MatchOperand_Success;
2723}
2724
Jim Grosbachd0588e22011-09-14 18:08:35 +00002725// For register list parsing, we need to map from raw GPR register numbering
2726// to the enumeration values. The enumeration values aren't sorted by
2727// register number due to our using "sp", "lr" and "pc" as canonical names.
2728static unsigned getNextRegister(unsigned Reg) {
2729 // If this is a GPR, we need to do it manually, otherwise we can rely
2730 // on the sort ordering of the enumeration since the other reg-classes
2731 // are sane.
2732 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2733 return Reg + 1;
2734 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002735 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002736 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2737 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2738 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2739 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2740 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2741 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2742 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2743 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2744 }
2745}
2746
Jim Grosbachce485e72011-11-11 21:27:40 +00002747// Return the low-subreg of a given Q register.
2748static unsigned getDRegFromQReg(unsigned QReg) {
2749 switch (QReg) {
2750 default: llvm_unreachable("expected a Q register!");
2751 case ARM::Q0: return ARM::D0;
2752 case ARM::Q1: return ARM::D2;
2753 case ARM::Q2: return ARM::D4;
2754 case ARM::Q3: return ARM::D6;
2755 case ARM::Q4: return ARM::D8;
2756 case ARM::Q5: return ARM::D10;
2757 case ARM::Q6: return ARM::D12;
2758 case ARM::Q7: return ARM::D14;
2759 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002760 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002761 case ARM::Q10: return ARM::D20;
2762 case ARM::Q11: return ARM::D22;
2763 case ARM::Q12: return ARM::D24;
2764 case ARM::Q13: return ARM::D26;
2765 case ARM::Q14: return ARM::D28;
2766 case ARM::Q15: return ARM::D30;
2767 }
2768}
2769
Jim Grosbachd0588e22011-09-14 18:08:35 +00002770/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002771bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002772parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002773 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002774 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002775 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002776 Parser.Lex(); // Eat '{' token.
2777 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002778
Jim Grosbachd0588e22011-09-14 18:08:35 +00002779 // Check the first register in the list to see what register class
2780 // this is a list of.
2781 int Reg = tryParseRegister();
2782 if (Reg == -1)
2783 return Error(RegLoc, "register expected");
2784
Jim Grosbachce485e72011-11-11 21:27:40 +00002785 // The reglist instructions have at most 16 registers, so reserve
2786 // space for that many.
2787 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2788
2789 // Allow Q regs and just interpret them as the two D sub-registers.
2790 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2791 Reg = getDRegFromQReg(Reg);
2792 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2793 ++Reg;
2794 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002795 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002796 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2797 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2798 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2799 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2800 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2801 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2802 else
2803 return Error(RegLoc, "invalid register in register list");
2804
Jim Grosbachce485e72011-11-11 21:27:40 +00002805 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002806 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002807
Jim Grosbachd0588e22011-09-14 18:08:35 +00002808 // This starts immediately after the first register token in the list,
2809 // so we can see either a comma or a minus (range separator) as a legal
2810 // next token.
2811 while (Parser.getTok().is(AsmToken::Comma) ||
2812 Parser.getTok().is(AsmToken::Minus)) {
2813 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002814 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002815 SMLoc EndLoc = Parser.getTok().getLoc();
2816 int EndReg = tryParseRegister();
2817 if (EndReg == -1)
2818 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002819 // Allow Q regs and just interpret them as the two D sub-registers.
2820 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2821 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002822 // If the register is the same as the start reg, there's nothing
2823 // more to do.
2824 if (Reg == EndReg)
2825 continue;
2826 // The register must be in the same register class as the first.
2827 if (!RC->contains(EndReg))
2828 return Error(EndLoc, "invalid register in register list");
2829 // Ranges must go from low to high.
2830 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2831 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002832
Jim Grosbachd0588e22011-09-14 18:08:35 +00002833 // Add all the registers in the range to the register list.
2834 while (Reg != EndReg) {
2835 Reg = getNextRegister(Reg);
2836 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2837 }
2838 continue;
2839 }
2840 Parser.Lex(); // Eat the comma.
2841 RegLoc = Parser.getTok().getLoc();
2842 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002843 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002844 Reg = tryParseRegister();
2845 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002846 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002847 // Allow Q regs and just interpret them as the two D sub-registers.
2848 bool isQReg = false;
2849 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2850 Reg = getDRegFromQReg(Reg);
2851 isQReg = true;
2852 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002853 // The register must be in the same register class as the first.
2854 if (!RC->contains(Reg))
2855 return Error(RegLoc, "invalid register in register list");
2856 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002857 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2858 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2859 Warning(RegLoc, "register list not in ascending order");
2860 else
2861 return Error(RegLoc, "register list not in ascending order");
2862 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002863 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2864 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2865 ") in register list");
2866 continue;
2867 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002868 // VFP register lists must also be contiguous.
2869 // It's OK to use the enumeration values directly here rather, as the
2870 // VFP register classes have the enum sorted properly.
2871 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2872 Reg != OldReg + 1)
2873 return Error(RegLoc, "non-contiguous register range");
2874 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002875 if (isQReg)
2876 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002877 }
2878
Jim Grosbachd0588e22011-09-14 18:08:35 +00002879 SMLoc E = Parser.getTok().getLoc();
2880 if (Parser.getTok().isNot(AsmToken::RCurly))
2881 return Error(E, "'}' expected");
2882 Parser.Lex(); // Eat '}' token.
2883
Jim Grosbach27debd62011-12-13 21:48:29 +00002884 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002885 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002886
2887 // The ARM system instruction variants for LDM/STM have a '^' token here.
2888 if (Parser.getTok().is(AsmToken::Caret)) {
2889 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2890 Parser.Lex(); // Eat '^' token.
2891 }
2892
Bill Wendling50d0f582010-11-18 23:43:05 +00002893 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002894}
2895
Jim Grosbach98b05a52011-11-30 01:09:44 +00002896// Helper function to parse the lane index for vector lists.
2897ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002898parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2899 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002900 if (Parser.getTok().is(AsmToken::LBrac)) {
2901 Parser.Lex(); // Eat the '['.
2902 if (Parser.getTok().is(AsmToken::RBrac)) {
2903 // "Dn[]" is the 'all lanes' syntax.
2904 LaneKind = AllLanes;
2905 Parser.Lex(); // Eat the ']'.
2906 return MatchOperand_Success;
2907 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002908
2909 // There's an optional '#' token here. Normally there wouldn't be, but
2910 // inline assemble puts one in, and it's friendly to accept that.
2911 if (Parser.getTok().is(AsmToken::Hash))
2912 Parser.Lex(); // Eat the '#'
2913
Jim Grosbachc9313252011-12-21 01:19:23 +00002914 const MCExpr *LaneIndex;
2915 SMLoc Loc = Parser.getTok().getLoc();
2916 if (getParser().ParseExpression(LaneIndex)) {
2917 Error(Loc, "illegal expression");
2918 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002919 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002920 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2921 if (!CE) {
2922 Error(Loc, "lane index must be empty or an integer");
2923 return MatchOperand_ParseFail;
2924 }
2925 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2926 Error(Parser.getTok().getLoc(), "']' expected");
2927 return MatchOperand_ParseFail;
2928 }
2929 Parser.Lex(); // Eat the ']'.
2930 int64_t Val = CE->getValue();
2931
2932 // FIXME: Make this range check context sensitive for .8, .16, .32.
2933 if (Val < 0 || Val > 7) {
2934 Error(Parser.getTok().getLoc(), "lane index out of range");
2935 return MatchOperand_ParseFail;
2936 }
2937 Index = Val;
2938 LaneKind = IndexedLane;
2939 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002940 }
2941 LaneKind = NoLanes;
2942 return MatchOperand_Success;
2943}
2944
Jim Grosbach862019c2011-10-18 23:02:30 +00002945// parse a vector register list
2946ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2947parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002948 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002949 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002950 SMLoc S = Parser.getTok().getLoc();
2951 // As an extension (to match gas), support a plain D register or Q register
2952 // (without encosing curly braces) as a single or double entry list,
2953 // respectively.
2954 if (Parser.getTok().is(AsmToken::Identifier)) {
2955 int Reg = tryParseRegister();
2956 if (Reg == -1)
2957 return MatchOperand_NoMatch;
2958 SMLoc E = Parser.getTok().getLoc();
2959 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002960 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002961 if (Res != MatchOperand_Success)
2962 return Res;
2963 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002964 case NoLanes:
2965 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002966 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002967 break;
2968 case AllLanes:
2969 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002970 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2971 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002972 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002973 case IndexedLane:
2974 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002975 LaneIndex,
2976 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002977 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002978 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002979 return MatchOperand_Success;
2980 }
2981 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2982 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002983 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002984 if (Res != MatchOperand_Success)
2985 return Res;
2986 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002987 case NoLanes:
2988 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00002989 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00002990 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002991 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002992 break;
2993 case AllLanes:
2994 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00002995 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
2996 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002997 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2998 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002999 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003000 case IndexedLane:
3001 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003002 LaneIndex,
3003 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003004 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003005 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003006 return MatchOperand_Success;
3007 }
3008 Error(S, "vector register expected");
3009 return MatchOperand_ParseFail;
3010 }
3011
3012 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003013 return MatchOperand_NoMatch;
3014
Jim Grosbach862019c2011-10-18 23:02:30 +00003015 Parser.Lex(); // Eat '{' token.
3016 SMLoc RegLoc = Parser.getTok().getLoc();
3017
3018 int Reg = tryParseRegister();
3019 if (Reg == -1) {
3020 Error(RegLoc, "register expected");
3021 return MatchOperand_ParseFail;
3022 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003023 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003024 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003025 unsigned FirstReg = Reg;
3026 // The list is of D registers, but we also allow Q regs and just interpret
3027 // them as the two D sub-registers.
3028 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3029 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003030 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3031 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003032 ++Reg;
3033 ++Count;
3034 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003035 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003036 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003037
Jim Grosbache43862b2011-11-15 23:19:15 +00003038 while (Parser.getTok().is(AsmToken::Comma) ||
3039 Parser.getTok().is(AsmToken::Minus)) {
3040 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003041 if (!Spacing)
3042 Spacing = 1; // Register range implies a single spaced list.
3043 else if (Spacing == 2) {
3044 Error(Parser.getTok().getLoc(),
3045 "sequential registers in double spaced list");
3046 return MatchOperand_ParseFail;
3047 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003048 Parser.Lex(); // Eat the minus.
3049 SMLoc EndLoc = Parser.getTok().getLoc();
3050 int EndReg = tryParseRegister();
3051 if (EndReg == -1) {
3052 Error(EndLoc, "register expected");
3053 return MatchOperand_ParseFail;
3054 }
3055 // Allow Q regs and just interpret them as the two D sub-registers.
3056 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3057 EndReg = getDRegFromQReg(EndReg) + 1;
3058 // If the register is the same as the start reg, there's nothing
3059 // more to do.
3060 if (Reg == EndReg)
3061 continue;
3062 // The register must be in the same register class as the first.
3063 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3064 Error(EndLoc, "invalid register in register list");
3065 return MatchOperand_ParseFail;
3066 }
3067 // Ranges must go from low to high.
3068 if (Reg > EndReg) {
3069 Error(EndLoc, "bad range in register list");
3070 return MatchOperand_ParseFail;
3071 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003072 // Parse the lane specifier if present.
3073 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003074 unsigned NextLaneIndex;
3075 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003076 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003077 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003078 Error(EndLoc, "mismatched lane index in register list");
3079 return MatchOperand_ParseFail;
3080 }
3081 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003082
3083 // Add all the registers in the range to the register list.
3084 Count += EndReg - Reg;
3085 Reg = EndReg;
3086 continue;
3087 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003088 Parser.Lex(); // Eat the comma.
3089 RegLoc = Parser.getTok().getLoc();
3090 int OldReg = Reg;
3091 Reg = tryParseRegister();
3092 if (Reg == -1) {
3093 Error(RegLoc, "register expected");
3094 return MatchOperand_ParseFail;
3095 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003096 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003097 // It's OK to use the enumeration values directly here rather, as the
3098 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003099 //
3100 // The list is of D registers, but we also allow Q regs and just interpret
3101 // them as the two D sub-registers.
3102 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003103 if (!Spacing)
3104 Spacing = 1; // Register range implies a single spaced list.
3105 else if (Spacing == 2) {
3106 Error(RegLoc,
3107 "invalid register in double-spaced list (must be 'D' register')");
3108 return MatchOperand_ParseFail;
3109 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003110 Reg = getDRegFromQReg(Reg);
3111 if (Reg != OldReg + 1) {
3112 Error(RegLoc, "non-contiguous register range");
3113 return MatchOperand_ParseFail;
3114 }
3115 ++Reg;
3116 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003117 // Parse the lane specifier if present.
3118 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003119 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003120 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003121 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003122 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003123 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003124 Error(EndLoc, "mismatched lane index in register list");
3125 return MatchOperand_ParseFail;
3126 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003127 continue;
3128 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003129 // Normal D register.
3130 // Figure out the register spacing (single or double) of the list if
3131 // we don't know it already.
3132 if (!Spacing)
3133 Spacing = 1 + (Reg == OldReg + 2);
3134
3135 // Just check that it's contiguous and keep going.
3136 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003137 Error(RegLoc, "non-contiguous register range");
3138 return MatchOperand_ParseFail;
3139 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003140 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003141 // Parse the lane specifier if present.
3142 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003143 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003144 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003145 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003146 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003147 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003148 Error(EndLoc, "mismatched lane index in register list");
3149 return MatchOperand_ParseFail;
3150 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003151 }
3152
3153 SMLoc E = Parser.getTok().getLoc();
3154 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3155 Error(E, "'}' expected");
3156 return MatchOperand_ParseFail;
3157 }
3158 Parser.Lex(); // Eat '}' token.
3159
Jim Grosbach98b05a52011-11-30 01:09:44 +00003160 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003161 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003162 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003163 // composite register classes.
3164 if (Count == 2) {
3165 const MCRegisterClass *RC = (Spacing == 1) ?
3166 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3167 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3168 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3169 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003170
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003171 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3172 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003173 break;
3174 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003175 // Two-register operands have been converted to the
3176 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003177 if (Count == 2) {
3178 const MCRegisterClass *RC = (Spacing == 1) ?
3179 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3180 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003181 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3182 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003183 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003184 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003185 S, E));
3186 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003187 case IndexedLane:
3188 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003189 LaneIndex,
3190 (Spacing == 2),
3191 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003192 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003193 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003194 return MatchOperand_Success;
3195}
3196
Jim Grosbach43904292011-07-25 20:14:50 +00003197/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003198ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003199parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003200 SMLoc S = Parser.getTok().getLoc();
3201 const AsmToken &Tok = Parser.getTok();
3202 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3203 StringRef OptStr = Tok.getString();
3204
3205 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3206 .Case("sy", ARM_MB::SY)
3207 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003208 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003209 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003210 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003211 .Case("ishst", ARM_MB::ISHST)
3212 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003213 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003214 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003215 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003216 .Case("osh", ARM_MB::OSH)
3217 .Case("oshst", ARM_MB::OSHST)
3218 .Default(~0U);
3219
3220 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003221 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003222
3223 Parser.Lex(); // Eat identifier token.
3224 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003225 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003226}
3227
Jim Grosbach43904292011-07-25 20:14:50 +00003228/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003229ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003230parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003231 SMLoc S = Parser.getTok().getLoc();
3232 const AsmToken &Tok = Parser.getTok();
3233 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3234 StringRef IFlagsStr = Tok.getString();
3235
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003236 // An iflags string of "none" is interpreted to mean that none of the AIF
3237 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003238 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003239 if (IFlagsStr != "none") {
3240 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3241 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3242 .Case("a", ARM_PROC::A)
3243 .Case("i", ARM_PROC::I)
3244 .Case("f", ARM_PROC::F)
3245 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003246
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003247 // If some specific iflag is already set, it means that some letter is
3248 // present more than once, this is not acceptable.
3249 if (Flag == ~0U || (IFlags & Flag))
3250 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003251
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003252 IFlags |= Flag;
3253 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003254 }
3255
3256 Parser.Lex(); // Eat identifier token.
3257 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3258 return MatchOperand_Success;
3259}
3260
Jim Grosbach43904292011-07-25 20:14:50 +00003261/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003262ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003263parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003264 SMLoc S = Parser.getTok().getLoc();
3265 const AsmToken &Tok = Parser.getTok();
3266 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3267 StringRef Mask = Tok.getString();
3268
James Molloyacad68d2011-09-28 14:21:38 +00003269 if (isMClass()) {
3270 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003271 std::string Name = Mask.lower();
3272 unsigned FlagsVal = StringSwitch<unsigned>(Name)
James Molloyacad68d2011-09-28 14:21:38 +00003273 .Case("apsr", 0)
3274 .Case("iapsr", 1)
3275 .Case("eapsr", 2)
3276 .Case("xpsr", 3)
3277 .Case("ipsr", 5)
3278 .Case("epsr", 6)
3279 .Case("iepsr", 7)
3280 .Case("msp", 8)
3281 .Case("psp", 9)
3282 .Case("primask", 16)
3283 .Case("basepri", 17)
3284 .Case("basepri_max", 18)
3285 .Case("faultmask", 19)
3286 .Case("control", 20)
3287 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003288
James Molloyacad68d2011-09-28 14:21:38 +00003289 if (FlagsVal == ~0U)
3290 return MatchOperand_NoMatch;
3291
3292 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3293 // basepri, basepri_max and faultmask only valid for V7m.
3294 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003295
James Molloyacad68d2011-09-28 14:21:38 +00003296 Parser.Lex(); // Eat identifier token.
3297 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3298 return MatchOperand_Success;
3299 }
3300
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003301 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3302 size_t Start = 0, Next = Mask.find('_');
3303 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003304 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003305 if (Next != StringRef::npos)
3306 Flags = Mask.slice(Next+1, Mask.size());
3307
3308 // FlagsVal contains the complete mask:
3309 // 3-0: Mask
3310 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3311 unsigned FlagsVal = 0;
3312
3313 if (SpecReg == "apsr") {
3314 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003315 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003316 .Case("g", 0x4) // same as CPSR_s
3317 .Case("nzcvqg", 0xc) // same as CPSR_fs
3318 .Default(~0U);
3319
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003320 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003321 if (!Flags.empty())
3322 return MatchOperand_NoMatch;
3323 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003324 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003325 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003326 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003327 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3328 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003329 for (int i = 0, e = Flags.size(); i != e; ++i) {
3330 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3331 .Case("c", 1)
3332 .Case("x", 2)
3333 .Case("s", 4)
3334 .Case("f", 8)
3335 .Default(~0U);
3336
3337 // If some specific flag is already set, it means that some letter is
3338 // present more than once, this is not acceptable.
3339 if (FlagsVal == ~0U || (FlagsVal & Flag))
3340 return MatchOperand_NoMatch;
3341 FlagsVal |= Flag;
3342 }
3343 } else // No match for special register.
3344 return MatchOperand_NoMatch;
3345
Owen Anderson7784f1d2011-10-21 18:43:28 +00003346 // Special register without flags is NOT equivalent to "fc" flags.
3347 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3348 // two lines would enable gas compatibility at the expense of breaking
3349 // round-tripping.
3350 //
3351 // if (!FlagsVal)
3352 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003353
3354 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3355 if (SpecReg == "spsr")
3356 FlagsVal |= 16;
3357
3358 Parser.Lex(); // Eat identifier token.
3359 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3360 return MatchOperand_Success;
3361}
3362
Jim Grosbachf6c05252011-07-21 17:23:04 +00003363ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3364parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3365 int Low, int High) {
3366 const AsmToken &Tok = Parser.getTok();
3367 if (Tok.isNot(AsmToken::Identifier)) {
3368 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3369 return MatchOperand_ParseFail;
3370 }
3371 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003372 std::string LowerOp = Op.lower();
3373 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003374 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3375 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3376 return MatchOperand_ParseFail;
3377 }
3378 Parser.Lex(); // Eat shift type token.
3379
3380 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003381 if (Parser.getTok().isNot(AsmToken::Hash) &&
3382 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003383 Error(Parser.getTok().getLoc(), "'#' expected");
3384 return MatchOperand_ParseFail;
3385 }
3386 Parser.Lex(); // Eat hash token.
3387
3388 const MCExpr *ShiftAmount;
3389 SMLoc Loc = Parser.getTok().getLoc();
3390 if (getParser().ParseExpression(ShiftAmount)) {
3391 Error(Loc, "illegal expression");
3392 return MatchOperand_ParseFail;
3393 }
3394 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3395 if (!CE) {
3396 Error(Loc, "constant expression expected");
3397 return MatchOperand_ParseFail;
3398 }
3399 int Val = CE->getValue();
3400 if (Val < Low || Val > High) {
3401 Error(Loc, "immediate value out of range");
3402 return MatchOperand_ParseFail;
3403 }
3404
3405 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3406
3407 return MatchOperand_Success;
3408}
3409
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003410ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3411parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3412 const AsmToken &Tok = Parser.getTok();
3413 SMLoc S = Tok.getLoc();
3414 if (Tok.isNot(AsmToken::Identifier)) {
3415 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3416 return MatchOperand_ParseFail;
3417 }
3418 int Val = StringSwitch<int>(Tok.getString())
3419 .Case("be", 1)
3420 .Case("le", 0)
3421 .Default(-1);
3422 Parser.Lex(); // Eat the token.
3423
3424 if (Val == -1) {
3425 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3426 return MatchOperand_ParseFail;
3427 }
3428 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3429 getContext()),
3430 S, Parser.getTok().getLoc()));
3431 return MatchOperand_Success;
3432}
3433
Jim Grosbach580f4a92011-07-25 22:20:28 +00003434/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3435/// instructions. Legal values are:
3436/// lsl #n 'n' in [0,31]
3437/// asr #n 'n' in [1,32]
3438/// n == 32 encoded as n == 0.
3439ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3440parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3441 const AsmToken &Tok = Parser.getTok();
3442 SMLoc S = Tok.getLoc();
3443 if (Tok.isNot(AsmToken::Identifier)) {
3444 Error(S, "shift operator 'asr' or 'lsl' expected");
3445 return MatchOperand_ParseFail;
3446 }
3447 StringRef ShiftName = Tok.getString();
3448 bool isASR;
3449 if (ShiftName == "lsl" || ShiftName == "LSL")
3450 isASR = false;
3451 else if (ShiftName == "asr" || ShiftName == "ASR")
3452 isASR = true;
3453 else {
3454 Error(S, "shift operator 'asr' or 'lsl' expected");
3455 return MatchOperand_ParseFail;
3456 }
3457 Parser.Lex(); // Eat the operator.
3458
3459 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003460 if (Parser.getTok().isNot(AsmToken::Hash) &&
3461 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003462 Error(Parser.getTok().getLoc(), "'#' expected");
3463 return MatchOperand_ParseFail;
3464 }
3465 Parser.Lex(); // Eat hash token.
3466
3467 const MCExpr *ShiftAmount;
3468 SMLoc E = Parser.getTok().getLoc();
3469 if (getParser().ParseExpression(ShiftAmount)) {
3470 Error(E, "malformed shift expression");
3471 return MatchOperand_ParseFail;
3472 }
3473 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3474 if (!CE) {
3475 Error(E, "shift amount must be an immediate");
3476 return MatchOperand_ParseFail;
3477 }
3478
3479 int64_t Val = CE->getValue();
3480 if (isASR) {
3481 // Shift amount must be in [1,32]
3482 if (Val < 1 || Val > 32) {
3483 Error(E, "'asr' shift amount must be in range [1,32]");
3484 return MatchOperand_ParseFail;
3485 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003486 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3487 if (isThumb() && Val == 32) {
3488 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3489 return MatchOperand_ParseFail;
3490 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003491 if (Val == 32) Val = 0;
3492 } else {
3493 // Shift amount must be in [1,32]
3494 if (Val < 0 || Val > 31) {
3495 Error(E, "'lsr' shift amount must be in range [0,31]");
3496 return MatchOperand_ParseFail;
3497 }
3498 }
3499
3500 E = Parser.getTok().getLoc();
3501 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3502
3503 return MatchOperand_Success;
3504}
3505
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003506/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3507/// of instructions. Legal values are:
3508/// ror #n 'n' in {0, 8, 16, 24}
3509ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3510parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3511 const AsmToken &Tok = Parser.getTok();
3512 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003513 if (Tok.isNot(AsmToken::Identifier))
3514 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003515 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003516 if (ShiftName != "ror" && ShiftName != "ROR")
3517 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003518 Parser.Lex(); // Eat the operator.
3519
3520 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003521 if (Parser.getTok().isNot(AsmToken::Hash) &&
3522 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003523 Error(Parser.getTok().getLoc(), "'#' expected");
3524 return MatchOperand_ParseFail;
3525 }
3526 Parser.Lex(); // Eat hash token.
3527
3528 const MCExpr *ShiftAmount;
3529 SMLoc E = Parser.getTok().getLoc();
3530 if (getParser().ParseExpression(ShiftAmount)) {
3531 Error(E, "malformed rotate expression");
3532 return MatchOperand_ParseFail;
3533 }
3534 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3535 if (!CE) {
3536 Error(E, "rotate amount must be an immediate");
3537 return MatchOperand_ParseFail;
3538 }
3539
3540 int64_t Val = CE->getValue();
3541 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3542 // normally, zero is represented in asm by omitting the rotate operand
3543 // entirely.
3544 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3545 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3546 return MatchOperand_ParseFail;
3547 }
3548
3549 E = Parser.getTok().getLoc();
3550 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3551
3552 return MatchOperand_Success;
3553}
3554
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003555ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3556parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3557 SMLoc S = Parser.getTok().getLoc();
3558 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003559 if (Parser.getTok().isNot(AsmToken::Hash) &&
3560 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003561 Error(Parser.getTok().getLoc(), "'#' expected");
3562 return MatchOperand_ParseFail;
3563 }
3564 Parser.Lex(); // Eat hash token.
3565
3566 const MCExpr *LSBExpr;
3567 SMLoc E = Parser.getTok().getLoc();
3568 if (getParser().ParseExpression(LSBExpr)) {
3569 Error(E, "malformed immediate expression");
3570 return MatchOperand_ParseFail;
3571 }
3572 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3573 if (!CE) {
3574 Error(E, "'lsb' operand must be an immediate");
3575 return MatchOperand_ParseFail;
3576 }
3577
3578 int64_t LSB = CE->getValue();
3579 // The LSB must be in the range [0,31]
3580 if (LSB < 0 || LSB > 31) {
3581 Error(E, "'lsb' operand must be in the range [0,31]");
3582 return MatchOperand_ParseFail;
3583 }
3584 E = Parser.getTok().getLoc();
3585
3586 // Expect another immediate operand.
3587 if (Parser.getTok().isNot(AsmToken::Comma)) {
3588 Error(Parser.getTok().getLoc(), "too few operands");
3589 return MatchOperand_ParseFail;
3590 }
3591 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003592 if (Parser.getTok().isNot(AsmToken::Hash) &&
3593 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003594 Error(Parser.getTok().getLoc(), "'#' expected");
3595 return MatchOperand_ParseFail;
3596 }
3597 Parser.Lex(); // Eat hash token.
3598
3599 const MCExpr *WidthExpr;
3600 if (getParser().ParseExpression(WidthExpr)) {
3601 Error(E, "malformed immediate expression");
3602 return MatchOperand_ParseFail;
3603 }
3604 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3605 if (!CE) {
3606 Error(E, "'width' operand must be an immediate");
3607 return MatchOperand_ParseFail;
3608 }
3609
3610 int64_t Width = CE->getValue();
3611 // The LSB must be in the range [1,32-lsb]
3612 if (Width < 1 || Width > 32 - LSB) {
3613 Error(E, "'width' operand must be in the range [1,32-lsb]");
3614 return MatchOperand_ParseFail;
3615 }
3616 E = Parser.getTok().getLoc();
3617
3618 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3619
3620 return MatchOperand_Success;
3621}
3622
Jim Grosbach7ce05792011-08-03 23:50:40 +00003623ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3624parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3625 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003626 // postidx_reg := '+' register {, shift}
3627 // | '-' register {, shift}
3628 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003629
3630 // This method must return MatchOperand_NoMatch without consuming any tokens
3631 // in the case where there is no match, as other alternatives take other
3632 // parse methods.
3633 AsmToken Tok = Parser.getTok();
3634 SMLoc S = Tok.getLoc();
3635 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003636 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003637 int Reg = -1;
3638 if (Tok.is(AsmToken::Plus)) {
3639 Parser.Lex(); // Eat the '+' token.
3640 haveEaten = true;
3641 } else if (Tok.is(AsmToken::Minus)) {
3642 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003643 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003644 haveEaten = true;
3645 }
3646 if (Parser.getTok().is(AsmToken::Identifier))
3647 Reg = tryParseRegister();
3648 if (Reg == -1) {
3649 if (!haveEaten)
3650 return MatchOperand_NoMatch;
3651 Error(Parser.getTok().getLoc(), "register expected");
3652 return MatchOperand_ParseFail;
3653 }
3654 SMLoc E = Parser.getTok().getLoc();
3655
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003656 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3657 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003658 if (Parser.getTok().is(AsmToken::Comma)) {
3659 Parser.Lex(); // Eat the ','.
3660 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3661 return MatchOperand_ParseFail;
3662 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003663
3664 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3665 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003666
3667 return MatchOperand_Success;
3668}
3669
Jim Grosbach251bf252011-08-10 21:56:18 +00003670ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3671parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3672 // Check for a post-index addressing register operand. Specifically:
3673 // am3offset := '+' register
3674 // | '-' register
3675 // | register
3676 // | # imm
3677 // | # + imm
3678 // | # - imm
3679
3680 // This method must return MatchOperand_NoMatch without consuming any tokens
3681 // in the case where there is no match, as other alternatives take other
3682 // parse methods.
3683 AsmToken Tok = Parser.getTok();
3684 SMLoc S = Tok.getLoc();
3685
3686 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003687 if (Parser.getTok().is(AsmToken::Hash) ||
3688 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003689 Parser.Lex(); // Eat the '#'.
3690 // Explicitly look for a '-', as we need to encode negative zero
3691 // differently.
3692 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3693 const MCExpr *Offset;
3694 if (getParser().ParseExpression(Offset))
3695 return MatchOperand_ParseFail;
3696 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3697 if (!CE) {
3698 Error(S, "constant expression expected");
3699 return MatchOperand_ParseFail;
3700 }
3701 SMLoc E = Tok.getLoc();
3702 // Negative zero is encoded as the flag value INT32_MIN.
3703 int32_t Val = CE->getValue();
3704 if (isNegative && Val == 0)
3705 Val = INT32_MIN;
3706
3707 Operands.push_back(
3708 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3709
3710 return MatchOperand_Success;
3711 }
3712
3713
3714 bool haveEaten = false;
3715 bool isAdd = true;
3716 int Reg = -1;
3717 if (Tok.is(AsmToken::Plus)) {
3718 Parser.Lex(); // Eat the '+' token.
3719 haveEaten = true;
3720 } else if (Tok.is(AsmToken::Minus)) {
3721 Parser.Lex(); // Eat the '-' token.
3722 isAdd = false;
3723 haveEaten = true;
3724 }
3725 if (Parser.getTok().is(AsmToken::Identifier))
3726 Reg = tryParseRegister();
3727 if (Reg == -1) {
3728 if (!haveEaten)
3729 return MatchOperand_NoMatch;
3730 Error(Parser.getTok().getLoc(), "register expected");
3731 return MatchOperand_ParseFail;
3732 }
3733 SMLoc E = Parser.getTok().getLoc();
3734
3735 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3736 0, S, E));
3737
3738 return MatchOperand_Success;
3739}
3740
Jim Grosbacha77295d2011-09-08 22:07:06 +00003741/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3742/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3743/// when they refer multiple MIOperands inside a single one.
3744bool ARMAsmParser::
3745cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3746 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3747 // Rt, Rt2
3748 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3749 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3750 // Create a writeback register dummy placeholder.
3751 Inst.addOperand(MCOperand::CreateReg(0));
3752 // addr
3753 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3754 // pred
3755 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3756 return true;
3757}
3758
3759/// cvtT2StrdPre - Convert parsed operands to MCInst.
3760/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3761/// when they refer multiple MIOperands inside a single one.
3762bool ARMAsmParser::
3763cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3764 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3765 // Create a writeback register dummy placeholder.
3766 Inst.addOperand(MCOperand::CreateReg(0));
3767 // Rt, Rt2
3768 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3769 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3770 // addr
3771 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3772 // pred
3773 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3774 return true;
3775}
3776
Jim Grosbacheeec0252011-09-08 00:39:19 +00003777/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3778/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3779/// when they refer multiple MIOperands inside a single one.
3780bool ARMAsmParser::
3781cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3782 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3783 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3784
3785 // Create a writeback register dummy placeholder.
3786 Inst.addOperand(MCOperand::CreateImm(0));
3787
3788 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3789 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3790 return true;
3791}
3792
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003793/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3794/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3795/// when they refer multiple MIOperands inside a single one.
3796bool ARMAsmParser::
3797cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3798 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3799 // Create a writeback register dummy placeholder.
3800 Inst.addOperand(MCOperand::CreateImm(0));
3801 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3802 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3803 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3804 return true;
3805}
3806
Jim Grosbach1355cf12011-07-26 17:10:22 +00003807/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003808/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3809/// when they refer multiple MIOperands inside a single one.
3810bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003811cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003812 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3813 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3814
3815 // Create a writeback register dummy placeholder.
3816 Inst.addOperand(MCOperand::CreateImm(0));
3817
Jim Grosbach7ce05792011-08-03 23:50:40 +00003818 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003819 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3820 return true;
3821}
3822
Owen Anderson9ab0f252011-08-26 20:43:14 +00003823/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3824/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3825/// when they refer multiple MIOperands inside a single one.
3826bool ARMAsmParser::
3827cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3828 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3829 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3830
3831 // Create a writeback register dummy placeholder.
3832 Inst.addOperand(MCOperand::CreateImm(0));
3833
3834 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3835 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3836 return true;
3837}
3838
3839
Jim Grosbach548340c2011-08-11 19:22:40 +00003840/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3841/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3842/// when they refer multiple MIOperands inside a single one.
3843bool ARMAsmParser::
3844cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3845 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3846 // Create a writeback register dummy placeholder.
3847 Inst.addOperand(MCOperand::CreateImm(0));
3848 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3849 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3850 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3851 return true;
3852}
3853
Jim Grosbach1355cf12011-07-26 17:10:22 +00003854/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003855/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3856/// when they refer multiple MIOperands inside a single one.
3857bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003858cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003859 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3860 // Create a writeback register dummy placeholder.
3861 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003862 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3863 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3864 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003865 return true;
3866}
3867
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003868/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3869/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3870/// when they refer multiple MIOperands inside a single one.
3871bool ARMAsmParser::
3872cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3873 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3874 // Create a writeback register dummy placeholder.
3875 Inst.addOperand(MCOperand::CreateImm(0));
3876 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3877 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3878 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3879 return true;
3880}
3881
Jim Grosbach7ce05792011-08-03 23:50:40 +00003882/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3883/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3884/// when they refer multiple MIOperands inside a single one.
3885bool ARMAsmParser::
3886cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3887 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3888 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003889 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003890 // Create a writeback register dummy placeholder.
3891 Inst.addOperand(MCOperand::CreateImm(0));
3892 // addr
3893 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3894 // offset
3895 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3896 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003897 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3898 return true;
3899}
3900
Jim Grosbach7ce05792011-08-03 23:50:40 +00003901/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003902/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3903/// when they refer multiple MIOperands inside a single one.
3904bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003905cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3906 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3907 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003908 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003909 // Create a writeback register dummy placeholder.
3910 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003911 // addr
3912 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3913 // offset
3914 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3915 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003916 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3917 return true;
3918}
3919
Jim Grosbach7ce05792011-08-03 23:50:40 +00003920/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003921/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3922/// when they refer multiple MIOperands inside a single one.
3923bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003924cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3925 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003926 // Create a writeback register dummy placeholder.
3927 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003928 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003929 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003930 // addr
3931 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3932 // offset
3933 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3934 // pred
3935 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3936 return true;
3937}
3938
3939/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3940/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3941/// when they refer multiple MIOperands inside a single one.
3942bool ARMAsmParser::
3943cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3944 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3945 // Create a writeback register dummy placeholder.
3946 Inst.addOperand(MCOperand::CreateImm(0));
3947 // Rt
3948 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3949 // addr
3950 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3951 // offset
3952 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3953 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003954 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3955 return true;
3956}
3957
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003958/// cvtLdrdPre - Convert parsed operands to MCInst.
3959/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3960/// when they refer multiple MIOperands inside a single one.
3961bool ARMAsmParser::
3962cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3963 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3964 // Rt, Rt2
3965 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3966 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3967 // Create a writeback register dummy placeholder.
3968 Inst.addOperand(MCOperand::CreateImm(0));
3969 // addr
3970 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3971 // pred
3972 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3973 return true;
3974}
3975
Jim Grosbach14605d12011-08-11 20:28:23 +00003976/// cvtStrdPre - Convert parsed operands to MCInst.
3977/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3978/// when they refer multiple MIOperands inside a single one.
3979bool ARMAsmParser::
3980cvtStrdPre(MCInst &Inst, unsigned Opcode,
3981 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3982 // Create a writeback register dummy placeholder.
3983 Inst.addOperand(MCOperand::CreateImm(0));
3984 // Rt, Rt2
3985 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3986 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3987 // addr
3988 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3989 // pred
3990 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3991 return true;
3992}
3993
Jim Grosbach623a4542011-08-10 22:42:16 +00003994/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3995/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3996/// when they refer multiple MIOperands inside a single one.
3997bool ARMAsmParser::
3998cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3999 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4000 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4001 // Create a writeback register dummy placeholder.
4002 Inst.addOperand(MCOperand::CreateImm(0));
4003 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4004 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4005 return true;
4006}
4007
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004008/// cvtThumbMultiple- Convert parsed operands to MCInst.
4009/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4010/// when they refer multiple MIOperands inside a single one.
4011bool ARMAsmParser::
4012cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4013 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4014 // The second source operand must be the same register as the destination
4015 // operand.
4016 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004017 (((ARMOperand*)Operands[3])->getReg() !=
4018 ((ARMOperand*)Operands[5])->getReg()) &&
4019 (((ARMOperand*)Operands[3])->getReg() !=
4020 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004021 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004022 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004023 return false;
4024 }
4025 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4026 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004027 // If we have a three-operand form, make sure to set Rn to be the operand
4028 // that isn't the same as Rd.
4029 unsigned RegOp = 4;
4030 if (Operands.size() == 6 &&
4031 ((ARMOperand*)Operands[4])->getReg() ==
4032 ((ARMOperand*)Operands[3])->getReg())
4033 RegOp = 5;
4034 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4035 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004036 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4037
4038 return true;
4039}
Jim Grosbach623a4542011-08-10 22:42:16 +00004040
Jim Grosbach12431322011-10-24 22:16:58 +00004041bool ARMAsmParser::
4042cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4043 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4044 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004045 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004046 // Create a writeback register dummy placeholder.
4047 Inst.addOperand(MCOperand::CreateImm(0));
4048 // Vn
4049 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4050 // pred
4051 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4052 return true;
4053}
4054
4055bool ARMAsmParser::
4056cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4057 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4058 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004059 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004060 // Create a writeback register dummy placeholder.
4061 Inst.addOperand(MCOperand::CreateImm(0));
4062 // Vn
4063 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4064 // Vm
4065 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4066 // pred
4067 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4068 return true;
4069}
4070
Jim Grosbach4334e032011-10-31 21:50:31 +00004071bool ARMAsmParser::
4072cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4073 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4074 // Create a writeback register dummy placeholder.
4075 Inst.addOperand(MCOperand::CreateImm(0));
4076 // Vn
4077 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4078 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004079 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004080 // pred
4081 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4082 return true;
4083}
4084
4085bool ARMAsmParser::
4086cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4087 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4088 // Create a writeback register dummy placeholder.
4089 Inst.addOperand(MCOperand::CreateImm(0));
4090 // Vn
4091 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4092 // Vm
4093 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4094 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004095 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004096 // pred
4097 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4098 return true;
4099}
4100
Bill Wendlinge7176102010-11-06 22:36:58 +00004101/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004102/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004103bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004104parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004105 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004106 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004107 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004108 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004109 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004110
Sean Callanan18b83232010-01-19 21:44:56 +00004111 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004112 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004113 if (BaseRegNum == -1)
4114 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004115
Daniel Dunbar05710932011-01-18 05:34:17 +00004116 // The next token must either be a comma or a closing bracket.
4117 const AsmToken &Tok = Parser.getTok();
4118 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004119 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004120
Jim Grosbach7ce05792011-08-03 23:50:40 +00004121 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004122 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004123 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004124
Jim Grosbach7ce05792011-08-03 23:50:40 +00004125 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004126 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004127
Jim Grosbachfb12f352011-09-19 18:42:21 +00004128 // If there's a pre-indexing writeback marker, '!', just add it as a token
4129 // operand. It's rather odd, but syntactically valid.
4130 if (Parser.getTok().is(AsmToken::Exclaim)) {
4131 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4132 Parser.Lex(); // Eat the '!'.
4133 }
4134
Jim Grosbach7ce05792011-08-03 23:50:40 +00004135 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004136 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004137
Jim Grosbach7ce05792011-08-03 23:50:40 +00004138 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4139 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004140
Jim Grosbach57dcb852011-10-11 17:29:55 +00004141 // If we have a ':', it's an alignment specifier.
4142 if (Parser.getTok().is(AsmToken::Colon)) {
4143 Parser.Lex(); // Eat the ':'.
4144 E = Parser.getTok().getLoc();
4145
4146 const MCExpr *Expr;
4147 if (getParser().ParseExpression(Expr))
4148 return true;
4149
4150 // The expression has to be a constant. Memory references with relocations
4151 // don't come through here, as they use the <label> forms of the relevant
4152 // instructions.
4153 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4154 if (!CE)
4155 return Error (E, "constant expression expected");
4156
4157 unsigned Align = 0;
4158 switch (CE->getValue()) {
4159 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004160 return Error(E,
4161 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4162 case 16: Align = 2; break;
4163 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004164 case 64: Align = 8; break;
4165 case 128: Align = 16; break;
4166 case 256: Align = 32; break;
4167 }
4168
4169 // Now we should have the closing ']'
4170 E = Parser.getTok().getLoc();
4171 if (Parser.getTok().isNot(AsmToken::RBrac))
4172 return Error(E, "']' expected");
4173 Parser.Lex(); // Eat right bracket token.
4174
4175 // Don't worry about range checking the value here. That's handled by
4176 // the is*() predicates.
4177 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4178 ARM_AM::no_shift, 0, Align,
4179 false, S, E));
4180
4181 // If there's a pre-indexing writeback marker, '!', just add it as a token
4182 // operand.
4183 if (Parser.getTok().is(AsmToken::Exclaim)) {
4184 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4185 Parser.Lex(); // Eat the '!'.
4186 }
4187
4188 return false;
4189 }
4190
4191 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004192 // offset. Be friendly and also accept a plain integer (without a leading
4193 // hash) for gas compatibility.
4194 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004195 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004196 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004197 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004198 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004199 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004200
Owen Anderson0da10cf2011-08-29 19:36:44 +00004201 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004202 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004203 if (getParser().ParseExpression(Offset))
4204 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004205
4206 // The expression has to be a constant. Memory references with relocations
4207 // don't come through here, as they use the <label> forms of the relevant
4208 // instructions.
4209 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4210 if (!CE)
4211 return Error (E, "constant expression expected");
4212
Owen Anderson0da10cf2011-08-29 19:36:44 +00004213 // If the constant was #-0, represent it as INT32_MIN.
4214 int32_t Val = CE->getValue();
4215 if (isNegative && Val == 0)
4216 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4217
Jim Grosbach7ce05792011-08-03 23:50:40 +00004218 // Now we should have the closing ']'
4219 E = Parser.getTok().getLoc();
4220 if (Parser.getTok().isNot(AsmToken::RBrac))
4221 return Error(E, "']' expected");
4222 Parser.Lex(); // Eat right bracket token.
4223
4224 // Don't worry about range checking the value here. That's handled by
4225 // the is*() predicates.
4226 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004227 ARM_AM::no_shift, 0, 0,
4228 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004229
4230 // If there's a pre-indexing writeback marker, '!', just add it as a token
4231 // operand.
4232 if (Parser.getTok().is(AsmToken::Exclaim)) {
4233 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4234 Parser.Lex(); // Eat the '!'.
4235 }
4236
4237 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004238 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004239
4240 // The register offset is optionally preceded by a '+' or '-'
4241 bool isNegative = false;
4242 if (Parser.getTok().is(AsmToken::Minus)) {
4243 isNegative = true;
4244 Parser.Lex(); // Eat the '-'.
4245 } else if (Parser.getTok().is(AsmToken::Plus)) {
4246 // Nothing to do.
4247 Parser.Lex(); // Eat the '+'.
4248 }
4249
4250 E = Parser.getTok().getLoc();
4251 int OffsetRegNum = tryParseRegister();
4252 if (OffsetRegNum == -1)
4253 return Error(E, "register expected");
4254
4255 // If there's a shift operator, handle it.
4256 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004257 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004258 if (Parser.getTok().is(AsmToken::Comma)) {
4259 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004260 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004261 return true;
4262 }
4263
4264 // Now we should have the closing ']'
4265 E = Parser.getTok().getLoc();
4266 if (Parser.getTok().isNot(AsmToken::RBrac))
4267 return Error(E, "']' expected");
4268 Parser.Lex(); // Eat right bracket token.
4269
4270 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004271 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004272 S, E));
4273
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004274 // If there's a pre-indexing writeback marker, '!', just add it as a token
4275 // operand.
4276 if (Parser.getTok().is(AsmToken::Exclaim)) {
4277 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4278 Parser.Lex(); // Eat the '!'.
4279 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004280
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004281 return false;
4282}
4283
Jim Grosbach7ce05792011-08-03 23:50:40 +00004284/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004285/// ( lsl | lsr | asr | ror ) , # shift_amount
4286/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004287/// return true if it parses a shift otherwise it returns false.
4288bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4289 unsigned &Amount) {
4290 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004291 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004292 if (Tok.isNot(AsmToken::Identifier))
4293 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004294 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004295 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4296 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004297 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004298 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004299 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004300 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004301 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004302 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004303 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004304 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004305 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004306 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004307 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004308 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004309
Jim Grosbach7ce05792011-08-03 23:50:40 +00004310 // rrx stands alone.
4311 Amount = 0;
4312 if (St != ARM_AM::rrx) {
4313 Loc = Parser.getTok().getLoc();
4314 // A '#' and a shift amount.
4315 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004316 if (HashTok.isNot(AsmToken::Hash) &&
4317 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004318 return Error(HashTok.getLoc(), "'#' expected");
4319 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004320
Jim Grosbach7ce05792011-08-03 23:50:40 +00004321 const MCExpr *Expr;
4322 if (getParser().ParseExpression(Expr))
4323 return true;
4324 // Range check the immediate.
4325 // lsl, ror: 0 <= imm <= 31
4326 // lsr, asr: 0 <= imm <= 32
4327 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4328 if (!CE)
4329 return Error(Loc, "shift amount must be an immediate");
4330 int64_t Imm = CE->getValue();
4331 if (Imm < 0 ||
4332 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4333 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4334 return Error(Loc, "immediate shift value out of range");
4335 Amount = Imm;
4336 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004337
4338 return false;
4339}
4340
Jim Grosbach9d390362011-10-03 23:38:36 +00004341/// parseFPImm - A floating point immediate expression operand.
4342ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4343parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004344 // Anything that can accept a floating point constant as an operand
4345 // needs to go through here, as the regular ParseExpression is
4346 // integer only.
4347 //
4348 // This routine still creates a generic Immediate operand, containing
4349 // a bitcast of the 64-bit floating point value. The various operands
4350 // that accept floats can check whether the value is valid for them
4351 // via the standard is*() predicates.
4352
Jim Grosbach9d390362011-10-03 23:38:36 +00004353 SMLoc S = Parser.getTok().getLoc();
4354
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004355 if (Parser.getTok().isNot(AsmToken::Hash) &&
4356 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004357 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004358
4359 // Disambiguate the VMOV forms that can accept an FP immediate.
4360 // vmov.f32 <sreg>, #imm
4361 // vmov.f64 <dreg>, #imm
4362 // vmov.f32 <dreg>, #imm @ vector f32x2
4363 // vmov.f32 <qreg>, #imm @ vector f32x4
4364 //
4365 // There are also the NEON VMOV instructions which expect an
4366 // integer constant. Make sure we don't try to parse an FPImm
4367 // for these:
4368 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4369 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4370 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4371 TyOp->getToken() != ".f64"))
4372 return MatchOperand_NoMatch;
4373
Jim Grosbach9d390362011-10-03 23:38:36 +00004374 Parser.Lex(); // Eat the '#'.
4375
4376 // Handle negation, as that still comes through as a separate token.
4377 bool isNegative = false;
4378 if (Parser.getTok().is(AsmToken::Minus)) {
4379 isNegative = true;
4380 Parser.Lex();
4381 }
4382 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004383 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004384 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004385 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004386 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4387 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004388 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004389 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004390 Operands.push_back(ARMOperand::CreateImm(
4391 MCConstantExpr::Create(IntVal, getContext()),
4392 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004393 return MatchOperand_Success;
4394 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004395 // Also handle plain integers. Instructions which allow floating point
4396 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004397 if (Tok.is(AsmToken::Integer)) {
4398 int64_t Val = Tok.getIntVal();
4399 Parser.Lex(); // Eat the token.
4400 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004401 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004402 return MatchOperand_ParseFail;
4403 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004404 double RealVal = ARM_AM::getFPImmFloat(Val);
4405 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4406 Operands.push_back(ARMOperand::CreateImm(
4407 MCConstantExpr::Create(Val, getContext()), S,
4408 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004409 return MatchOperand_Success;
4410 }
4411
Jim Grosbachae69f702012-01-19 02:47:30 +00004412 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004413 return MatchOperand_ParseFail;
4414}
Jim Grosbach51222d12012-01-20 18:09:51 +00004415
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004416/// Parse a arm instruction operand. For now this parses the operand regardless
4417/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004418bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004419 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004420 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004421
4422 // Check if the current operand has a custom associated parser, if so, try to
4423 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004424 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4425 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004426 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004427 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4428 // there was a match, but an error occurred, in which case, just return that
4429 // the operand parsing failed.
4430 if (ResTy == MatchOperand_ParseFail)
4431 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004432
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004433 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004434 default:
4435 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004436 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004437 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004438 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004439 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004440 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004441 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004442 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004443 else if (Res == -1) // irrecoverable error
4444 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004445 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004446 if (Mnemonic == "vmrs" &&
4447 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004448 S = Parser.getTok().getLoc();
4449 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004450 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004451 return false;
4452 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004453
4454 // Fall though for the Identifier case that is not a register or a
4455 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004456 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004457 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004458 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004459 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004460 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004461 // This was not a register so parse other operands that start with an
4462 // identifier (like labels) as expressions and create them as immediates.
4463 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004464 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004465 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004466 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004467 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004468 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4469 return false;
4470 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004471 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004472 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004473 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004474 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004475 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004476 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004477 // #42 -> immediate.
4478 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004479 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004480 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004481 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004482 const MCExpr *ImmVal;
4483 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004484 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004485 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004486 if (CE) {
4487 int32_t Val = CE->getValue();
4488 if (isNegative && Val == 0)
4489 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004490 }
Sean Callanan76264762010-04-02 22:27:05 +00004491 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004492 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4493 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004494 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004495 case AsmToken::Colon: {
4496 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004497 // FIXME: Check it's an expression prefix,
4498 // e.g. (FOO - :lower16:BAR) isn't legal.
4499 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004500 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004501 return true;
4502
Evan Cheng75972122011-01-13 07:58:56 +00004503 const MCExpr *SubExprVal;
4504 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004505 return true;
4506
Evan Cheng75972122011-01-13 07:58:56 +00004507 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4508 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004509 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004510 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004511 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004512 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004513 }
4514}
4515
Jim Grosbach1355cf12011-07-26 17:10:22 +00004516// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004517// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004518bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004519 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004520
4521 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004522 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004523 Parser.Lex(); // Eat ':'
4524
4525 if (getLexer().isNot(AsmToken::Identifier)) {
4526 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4527 return true;
4528 }
4529
4530 StringRef IDVal = Parser.getTok().getIdentifier();
4531 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004532 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004533 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004534 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004535 } else {
4536 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4537 return true;
4538 }
4539 Parser.Lex();
4540
4541 if (getLexer().isNot(AsmToken::Colon)) {
4542 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4543 return true;
4544 }
4545 Parser.Lex(); // Eat the last ':'
4546 return false;
4547}
4548
Daniel Dunbar352e1482011-01-11 15:59:50 +00004549/// \brief Given a mnemonic, split out possible predication code and carry
4550/// setting letters to form a canonical mnemonic and flags.
4551//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004552// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004553// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004554StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004555 unsigned &PredicationCode,
4556 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004557 unsigned &ProcessorIMod,
4558 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004559 PredicationCode = ARMCC::AL;
4560 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004561 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004562
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004563 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004564 //
4565 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004566 if ((Mnemonic == "movs" && isThumb()) ||
4567 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4568 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4569 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4570 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4571 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4572 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004573 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4574 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004575 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004576
Jim Grosbach3f00e312011-07-11 17:09:57 +00004577 // First, split out any predication code. Ignore mnemonics we know aren't
4578 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004579 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004580 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004581 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004582 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004583 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4584 .Case("eq", ARMCC::EQ)
4585 .Case("ne", ARMCC::NE)
4586 .Case("hs", ARMCC::HS)
4587 .Case("cs", ARMCC::HS)
4588 .Case("lo", ARMCC::LO)
4589 .Case("cc", ARMCC::LO)
4590 .Case("mi", ARMCC::MI)
4591 .Case("pl", ARMCC::PL)
4592 .Case("vs", ARMCC::VS)
4593 .Case("vc", ARMCC::VC)
4594 .Case("hi", ARMCC::HI)
4595 .Case("ls", ARMCC::LS)
4596 .Case("ge", ARMCC::GE)
4597 .Case("lt", ARMCC::LT)
4598 .Case("gt", ARMCC::GT)
4599 .Case("le", ARMCC::LE)
4600 .Case("al", ARMCC::AL)
4601 .Default(~0U);
4602 if (CC != ~0U) {
4603 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4604 PredicationCode = CC;
4605 }
Bill Wendling52925b62010-10-29 23:50:21 +00004606 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004607
Daniel Dunbar352e1482011-01-11 15:59:50 +00004608 // Next, determine if we have a carry setting bit. We explicitly ignore all
4609 // the instructions we know end in 's'.
4610 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004611 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004612 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4613 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4614 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004615 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004616 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004617 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004618 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004619 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004620 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4621 CarrySetting = true;
4622 }
4623
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004624 // The "cps" instruction can have a interrupt mode operand which is glued into
4625 // the mnemonic. Check if this is the case, split it and parse the imod op
4626 if (Mnemonic.startswith("cps")) {
4627 // Split out any imod code.
4628 unsigned IMod =
4629 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4630 .Case("ie", ARM_PROC::IE)
4631 .Case("id", ARM_PROC::ID)
4632 .Default(~0U);
4633 if (IMod != ~0U) {
4634 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4635 ProcessorIMod = IMod;
4636 }
4637 }
4638
Jim Grosbach89df9962011-08-26 21:43:41 +00004639 // The "it" instruction has the condition mask on the end of the mnemonic.
4640 if (Mnemonic.startswith("it")) {
4641 ITMask = Mnemonic.slice(2, Mnemonic.size());
4642 Mnemonic = Mnemonic.slice(0, 2);
4643 }
4644
Daniel Dunbar352e1482011-01-11 15:59:50 +00004645 return Mnemonic;
4646}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004647
4648/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4649/// inclusion of carry set or predication code operands.
4650//
4651// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004652void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004653getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004654 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004655 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4656 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004657 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004658 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004659 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004660 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004661 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004662 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004663 Mnemonic == "mla" || Mnemonic == "smlal" ||
4664 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004665 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004666 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004667 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004668
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004669 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4670 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4671 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4672 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004673 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4674 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004675 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004676 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4677 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4678 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004679 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4680 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004681 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004682 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004683 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004684 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004685
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004686 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004687 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004688 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004689 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004690 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004691}
4692
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004693bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4694 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004695 // FIXME: This is all horribly hacky. We really need a better way to deal
4696 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004697
4698 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4699 // another does not. Specifically, the MOVW instruction does not. So we
4700 // special case it here and remove the defaulted (non-setting) cc_out
4701 // operand if that's the instruction we're trying to match.
4702 //
4703 // We do this as post-processing of the explicit operands rather than just
4704 // conditionally adding the cc_out in the first place because we need
4705 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004706 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004707 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4708 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4709 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4710 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004711
4712 // Register-register 'add' for thumb does not have a cc_out operand
4713 // when there are only two register operands.
4714 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4715 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4716 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4717 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4718 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004719 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004720 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4721 // have to check the immediate range here since Thumb2 has a variant
4722 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004723 if (((isThumb() && Mnemonic == "add") ||
4724 (isThumbTwo() && Mnemonic == "sub")) &&
4725 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004726 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4727 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4728 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004729 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4730 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4731 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004732 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004733 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4734 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004735 // selecting via the generic "add" mnemonic, so to know that we
4736 // should remove the cc_out operand, we have to explicitly check that
4737 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004738 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4739 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004740 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4741 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4742 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4743 // Nest conditions rather than one big 'if' statement for readability.
4744 //
4745 // If either register is a high reg, it's either one of the SP
4746 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004747 // check against T3. If the second register is the PC, this is an
4748 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004749 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4750 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004751 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004752 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4753 return false;
4754 // If both registers are low, we're in an IT block, and the immediate is
4755 // in range, we should use encoding T1 instead, which has a cc_out.
4756 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004757 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004758 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4759 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4760 return false;
4761
4762 // Otherwise, we use encoding T4, which does not have a cc_out
4763 // operand.
4764 return true;
4765 }
4766
Jim Grosbach64944f42011-09-14 21:00:40 +00004767 // The thumb2 multiply instruction doesn't have a CCOut register, so
4768 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4769 // use the 16-bit encoding or not.
4770 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4771 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4772 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4773 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4774 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4775 // If the registers aren't low regs, the destination reg isn't the
4776 // same as one of the source regs, or the cc_out operand is zero
4777 // outside of an IT block, we have to use the 32-bit encoding, so
4778 // remove the cc_out operand.
4779 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4780 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004781 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004782 !inITBlock() ||
4783 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4784 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4785 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4786 static_cast<ARMOperand*>(Operands[4])->getReg())))
4787 return true;
4788
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004789 // Also check the 'mul' syntax variant that doesn't specify an explicit
4790 // destination register.
4791 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4792 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4793 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4794 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4795 // If the registers aren't low regs or the cc_out operand is zero
4796 // outside of an IT block, we have to use the 32-bit encoding, so
4797 // remove the cc_out operand.
4798 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4799 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4800 !inITBlock()))
4801 return true;
4802
Jim Grosbach64944f42011-09-14 21:00:40 +00004803
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004804
Jim Grosbachf69c8042011-08-24 21:42:27 +00004805 // Register-register 'add/sub' for thumb does not have a cc_out operand
4806 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4807 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4808 // right, this will result in better diagnostics (which operand is off)
4809 // anyway.
4810 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4811 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004812 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4813 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4814 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4815 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004816
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004817 return false;
4818}
4819
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004820static bool isDataTypeToken(StringRef Tok) {
4821 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4822 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4823 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4824 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4825 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4826 Tok == ".f" || Tok == ".d";
4827}
4828
4829// FIXME: This bit should probably be handled via an explicit match class
4830// in the .td files that matches the suffix instead of having it be
4831// a literal string token the way it is now.
4832static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4833 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4834}
4835
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004836static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004837/// Parse an arm instruction mnemonic followed by its operands.
4838bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4839 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004840 // Apply mnemonic aliases before doing anything else, as the destination
4841 // mnemnonic may include suffices and we want to handle them normally.
4842 // The generic tblgen'erated code does this later, at the start of
4843 // MatchInstructionImpl(), but that's too late for aliases that include
4844 // any sort of suffix.
4845 unsigned AvailableFeatures = getAvailableFeatures();
4846 applyMnemonicAliases(Name, AvailableFeatures);
4847
Jim Grosbacha39cda72011-12-14 02:16:11 +00004848 // First check for the ARM-specific .req directive.
4849 if (Parser.getTok().is(AsmToken::Identifier) &&
4850 Parser.getTok().getIdentifier() == ".req") {
4851 parseDirectiveReq(Name, NameLoc);
4852 // We always return 'error' for this, as we're done with this
4853 // statement and don't need to match the 'instruction."
4854 return true;
4855 }
4856
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004857 // Create the leading tokens for the mnemonic, split by '.' characters.
4858 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004859 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004860
Daniel Dunbar352e1482011-01-11 15:59:50 +00004861 // Split out the predication code and carry setting flag from the mnemonic.
4862 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004863 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004864 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004865 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004866 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004867 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004868
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004869 // In Thumb1, only the branch (B) instruction can be predicated.
4870 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4871 Parser.EatToEndOfStatement();
4872 return Error(NameLoc, "conditional execution not supported in Thumb1");
4873 }
4874
Jim Grosbachffa32252011-07-19 19:13:28 +00004875 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4876
Jim Grosbach89df9962011-08-26 21:43:41 +00004877 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4878 // is the mask as it will be for the IT encoding if the conditional
4879 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4880 // where the conditional bit0 is zero, the instruction post-processing
4881 // will adjust the mask accordingly.
4882 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004883 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4884 if (ITMask.size() > 3) {
4885 Parser.EatToEndOfStatement();
4886 return Error(Loc, "too many conditions on IT instruction");
4887 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004888 unsigned Mask = 8;
4889 for (unsigned i = ITMask.size(); i != 0; --i) {
4890 char pos = ITMask[i - 1];
4891 if (pos != 't' && pos != 'e') {
4892 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004893 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004894 }
4895 Mask >>= 1;
4896 if (ITMask[i - 1] == 't')
4897 Mask |= 8;
4898 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004899 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004900 }
4901
Jim Grosbachffa32252011-07-19 19:13:28 +00004902 // FIXME: This is all a pretty gross hack. We should automatically handle
4903 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004904
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004905 // Next, add the CCOut and ConditionCode operands, if needed.
4906 //
4907 // For mnemonics which can ever incorporate a carry setting bit or predication
4908 // code, our matching model involves us always generating CCOut and
4909 // ConditionCode operands to match the mnemonic "as written" and then we let
4910 // the matcher deal with finding the right instruction or generating an
4911 // appropriate error.
4912 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004913 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004914
Jim Grosbach33c16a22011-07-14 22:04:21 +00004915 // If we had a carry-set on an instruction that can't do that, issue an
4916 // error.
4917 if (!CanAcceptCarrySet && CarrySetting) {
4918 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004919 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004920 "' can not set flags, but 's' suffix specified");
4921 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004922 // If we had a predication code on an instruction that can't do that, issue an
4923 // error.
4924 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4925 Parser.EatToEndOfStatement();
4926 return Error(NameLoc, "instruction '" + Mnemonic +
4927 "' is not predicable, but condition code specified");
4928 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004929
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004930 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004931 if (CanAcceptCarrySet) {
4932 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004933 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004934 Loc));
4935 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004936
4937 // Add the predication code operand, if necessary.
4938 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004939 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4940 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004941 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004942 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004943 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004944
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004945 // Add the processor imod operand, if necessary.
4946 if (ProcessorIMod) {
4947 Operands.push_back(ARMOperand::CreateImm(
4948 MCConstantExpr::Create(ProcessorIMod, getContext()),
4949 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004950 }
4951
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004952 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004953 while (Next != StringRef::npos) {
4954 Start = Next;
4955 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004956 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004957
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004958 // Some NEON instructions have an optional datatype suffix that is
4959 // completely ignored. Check for that.
4960 if (isDataTypeToken(ExtraToken) &&
4961 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4962 continue;
4963
Jim Grosbach81d2e392011-09-07 16:06:04 +00004964 if (ExtraToken != ".n") {
4965 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4966 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4967 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004968 }
4969
4970 // Read the remaining operands.
4971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004972 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004973 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004974 Parser.EatToEndOfStatement();
4975 return true;
4976 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004977
4978 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004979 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004980
4981 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004982 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004983 Parser.EatToEndOfStatement();
4984 return true;
4985 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004986 }
4987 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004988
Chris Lattnercbf8a982010-09-11 16:18:25 +00004989 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004990 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004991 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004992 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004993 }
Bill Wendling146018f2010-11-06 21:42:12 +00004994
Chris Lattner34e53142010-09-08 05:10:46 +00004995 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004996
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004997 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4998 // do and don't have a cc_out optional-def operand. With some spot-checks
4999 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005000 // parse and adjust accordingly before actually matching. We shouldn't ever
5001 // try to remove a cc_out operand that was explicitly set on the the
5002 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5003 // table driven matcher doesn't fit well with the ARM instruction set.
5004 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005005 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5006 Operands.erase(Operands.begin() + 1);
5007 delete Op;
5008 }
5009
Jim Grosbachcf121c32011-07-28 21:57:55 +00005010 // ARM mode 'blx' need special handling, as the register operand version
5011 // is predicable, but the label operand version is not. So, we can't rely
5012 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005013 // a k_CondCode operand in the list. If we're trying to match the label
5014 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005015 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5016 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5017 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5018 Operands.erase(Operands.begin() + 1);
5019 delete Op;
5020 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005021
5022 // The vector-compare-to-zero instructions have a literal token "#0" at
5023 // the end that comes to here as an immediate operand. Convert it to a
5024 // token to play nicely with the matcher.
5025 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5026 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5027 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5028 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5029 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5030 if (CE && CE->getValue() == 0) {
5031 Operands.erase(Operands.begin() + 5);
5032 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5033 delete Op;
5034 }
5035 }
Jim Grosbach68259142011-10-03 22:30:24 +00005036 // VCMP{E} does the same thing, but with a different operand count.
5037 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5038 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5039 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5041 if (CE && CE->getValue() == 0) {
5042 Operands.erase(Operands.begin() + 4);
5043 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5044 delete Op;
5045 }
5046 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005047 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005048 // end. Convert it to a token here. Take care not to convert those
5049 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005050 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005051 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5052 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005053 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5054 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005056 if (CE && CE->getValue() == 0 &&
5057 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005058 // The cc_out operand matches the IT block.
5059 ((inITBlock() != CarrySetting) &&
5060 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005061 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005062 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005063 Operands.erase(Operands.begin() + 5);
5064 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5065 delete Op;
5066 }
5067 }
5068
Chris Lattner98986712010-01-14 22:21:20 +00005069 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005070}
5071
Jim Grosbach189610f2011-07-26 18:25:39 +00005072// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005073
5074// return 'true' if register list contains non-low GPR registers,
5075// 'false' otherwise. If Reg is in the register list or is HiReg, set
5076// 'containsReg' to true.
5077static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5078 unsigned HiReg, bool &containsReg) {
5079 containsReg = false;
5080 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5081 unsigned OpReg = Inst.getOperand(i).getReg();
5082 if (OpReg == Reg)
5083 containsReg = true;
5084 // Anything other than a low register isn't legal here.
5085 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5086 return true;
5087 }
5088 return false;
5089}
5090
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005091// Check if the specified regisgter is in the register list of the inst,
5092// starting at the indicated operand number.
5093static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5094 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5095 unsigned OpReg = Inst.getOperand(i).getReg();
5096 if (OpReg == Reg)
5097 return true;
5098 }
5099 return false;
5100}
5101
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005102// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5103// the ARMInsts array) instead. Getting that here requires awkward
5104// API changes, though. Better way?
5105namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005106extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005107}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005108static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005109 return ARMInsts[Opcode];
5110}
5111
Jim Grosbach189610f2011-07-26 18:25:39 +00005112// FIXME: We would really like to be able to tablegen'erate this.
5113bool ARMAsmParser::
5114validateInstruction(MCInst &Inst,
5115 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005116 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005117 SMLoc Loc = Operands[0]->getStartLoc();
5118 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005119 // NOTE: BKPT instruction has the interesting property of being
5120 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005121 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005122 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5123 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005124 unsigned bit = 1;
5125 if (ITState.FirstCond)
5126 ITState.FirstCond = false;
5127 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005128 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005129 // The instruction must be predicable.
5130 if (!MCID.isPredicable())
5131 return Error(Loc, "instructions in IT block must be predicable");
5132 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5133 unsigned ITCond = bit ? ITState.Cond :
5134 ARMCC::getOppositeCondition(ITState.Cond);
5135 if (Cond != ITCond) {
5136 // Find the condition code Operand to get its SMLoc information.
5137 SMLoc CondLoc;
5138 for (unsigned i = 1; i < Operands.size(); ++i)
5139 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5140 CondLoc = Operands[i]->getStartLoc();
5141 return Error(CondLoc, "incorrect condition in IT block; got '" +
5142 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5143 "', but expected '" +
5144 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5145 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005146 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005147 } else if (isThumbTwo() && MCID.isPredicable() &&
5148 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005149 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5150 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005151 return Error(Loc, "predicated instructions must be in IT block");
5152
Jim Grosbach189610f2011-07-26 18:25:39 +00005153 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005154 case ARM::LDRD:
5155 case ARM::LDRD_PRE:
5156 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005157 case ARM::LDREXD: {
5158 // Rt2 must be Rt + 1.
5159 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5160 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5161 if (Rt2 != Rt + 1)
5162 return Error(Operands[3]->getStartLoc(),
5163 "destination operands must be sequential");
5164 return false;
5165 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005166 case ARM::STRD: {
5167 // Rt2 must be Rt + 1.
5168 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5169 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5170 if (Rt2 != Rt + 1)
5171 return Error(Operands[3]->getStartLoc(),
5172 "source operands must be sequential");
5173 return false;
5174 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005175 case ARM::STRD_PRE:
5176 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005177 case ARM::STREXD: {
5178 // Rt2 must be Rt + 1.
5179 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5180 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5181 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005182 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005183 "source operands must be sequential");
5184 return false;
5185 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005186 case ARM::SBFX:
5187 case ARM::UBFX: {
5188 // width must be in range [1, 32-lsb]
5189 unsigned lsb = Inst.getOperand(2).getImm();
5190 unsigned widthm1 = Inst.getOperand(3).getImm();
5191 if (widthm1 >= 32 - lsb)
5192 return Error(Operands[5]->getStartLoc(),
5193 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005194 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005195 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005196 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005197 // If we're parsing Thumb2, the .w variant is available and handles
5198 // most cases that are normally illegal for a Thumb1 LDM
5199 // instruction. We'll make the transformation in processInstruction()
5200 // if necessary.
5201 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005202 // Thumb LDM instructions are writeback iff the base register is not
5203 // in the register list.
5204 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005205 bool hasWritebackToken =
5206 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5207 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005208 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005209 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005210 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5211 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005212 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005213 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005214 return Error(Operands[2]->getStartLoc(),
5215 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005216 // If we should not have writeback, there must not be a '!'. This is
5217 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005218 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005219 return Error(Operands[3]->getStartLoc(),
5220 "writeback operator '!' not allowed when base register "
5221 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005222
5223 break;
5224 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005225 case ARM::t2LDMIA_UPD: {
5226 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5227 return Error(Operands[4]->getStartLoc(),
5228 "writeback operator '!' not allowed when base register "
5229 "in register list");
5230 break;
5231 }
Jim Grosbach54026372011-11-10 23:17:11 +00005232 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5233 // so only issue a diagnostic for thumb1. The instructions will be
5234 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005235 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005236 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005237 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5238 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005239 return Error(Operands[2]->getStartLoc(),
5240 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005241 break;
5242 }
5243 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005244 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005245 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5246 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005247 return Error(Operands[2]->getStartLoc(),
5248 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005249 break;
5250 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005251 case ARM::tSTMIA_UPD: {
5252 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005253 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005254 return Error(Operands[4]->getStartLoc(),
5255 "registers must be in range r0-r7");
5256 break;
5257 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005258 }
5259
5260 return false;
5261}
5262
Jim Grosbachd7433e22012-01-23 23:45:44 +00005263static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005264 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005265 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005266 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005267 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5268 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5269 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5270 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5271 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5272 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5273 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5274 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5275 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005276
5277 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005278 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5279 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5280 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5281 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5282 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005283
Jim Grosbach7945ead2012-01-24 00:43:12 +00005284 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5285 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5286 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5287 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5288 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005289
Jim Grosbach7945ead2012-01-24 00:43:12 +00005290 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5291 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5292 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5293 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5294 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005295
Jim Grosbach4adb1822012-01-24 00:07:41 +00005296 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005297 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5298 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5299 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5300 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5301 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5302 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5303 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5304 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5305 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5306 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5307 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5308 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5309 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5310 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5311 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005312
Jim Grosbachd7433e22012-01-23 23:45:44 +00005313 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005314 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5315 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5316 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5317 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5318 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5319 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5320 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5321 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5322 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5323 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5324 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5325 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5326 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5327 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5328 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5329 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5330 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5331 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005332
Jim Grosbach88a54de2012-01-24 18:53:13 +00005333 // VST4LN
5334 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5335 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5336 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5337 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5338 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5339 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5340 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5341 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5342 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5343 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5344 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5345 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5346 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5347 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5348 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5349
Jim Grosbach539aab72012-01-24 00:58:13 +00005350 // VST4
5351 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5352 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5353 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5354 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5355 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5356 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5357 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5358 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5359 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5360 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5361 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5362 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5363 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5364 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5365 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5366 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5367 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5368 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005369 }
5370}
5371
Jim Grosbachd7433e22012-01-23 23:45:44 +00005372static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005373 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005374 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005375 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005376 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5377 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5378 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5379 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5380 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5381 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5382 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5383 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5384 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005385
5386 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005387 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5388 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5389 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5390 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5391 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5392 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5393 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5394 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5395 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5396 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5397 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5398 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5399 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5400 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5401 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005402
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005403 // VLD3DUP
5404 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5405 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5406 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5407 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5408 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5409 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5410 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5411 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5412 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5413 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5414 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5415 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5416 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5417 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5418 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5419 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5420 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5421 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5422
Jim Grosbach3a678af2012-01-23 21:53:26 +00005423 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005424 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5425 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5426 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5427 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5428 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5429 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5430 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5431 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5432 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5433 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5434 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5435 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5436 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5437 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5438 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005439
5440 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005441 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5442 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5443 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5444 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5445 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5446 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5447 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5448 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5449 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5450 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5451 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5452 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5453 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5454 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5455 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5456 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5457 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5458 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005459
Jim Grosbache983a132012-01-24 18:37:25 +00005460 // VLD4LN
5461 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5462 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5463 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5464 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5465 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5466 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5467 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5468 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5469 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5470 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5471 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5472 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5473 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5474 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5475 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5476
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005477 // VLD4DUP
5478 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5479 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5480 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5481 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5482 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5483 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5484 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5485 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5486 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5487 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5488 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5489 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5490 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5491 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5492 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5493 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5494 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5495 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5496
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005497 // VLD4
5498 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5499 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5500 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5501 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5502 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5503 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5504 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5505 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5506 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5507 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5508 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5509 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5510 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5511 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5512 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5513 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5514 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5515 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005516 }
5517}
5518
Jim Grosbach83ec8772011-11-10 23:42:14 +00005519bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005520processInstruction(MCInst &Inst,
5521 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5522 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005523 // Aliases for alternate PC+imm syntax of LDR instructions.
5524 case ARM::t2LDRpcrel:
5525 Inst.setOpcode(ARM::t2LDRpci);
5526 return true;
5527 case ARM::t2LDRBpcrel:
5528 Inst.setOpcode(ARM::t2LDRBpci);
5529 return true;
5530 case ARM::t2LDRHpcrel:
5531 Inst.setOpcode(ARM::t2LDRHpci);
5532 return true;
5533 case ARM::t2LDRSBpcrel:
5534 Inst.setOpcode(ARM::t2LDRSBpci);
5535 return true;
5536 case ARM::t2LDRSHpcrel:
5537 Inst.setOpcode(ARM::t2LDRSHpci);
5538 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005539 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005540 case ARM::VST1LNdWB_register_Asm_8:
5541 case ARM::VST1LNdWB_register_Asm_16:
5542 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005543 MCInst TmpInst;
5544 // Shuffle the operands around so the lane index operand is in the
5545 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005546 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005547 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005548 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5549 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5550 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5551 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5552 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5553 TmpInst.addOperand(Inst.getOperand(1)); // lane
5554 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5555 TmpInst.addOperand(Inst.getOperand(6));
5556 Inst = TmpInst;
5557 return true;
5558 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005559
Jim Grosbach8b31f952012-01-23 19:39:08 +00005560 case ARM::VST2LNdWB_register_Asm_8:
5561 case ARM::VST2LNdWB_register_Asm_16:
5562 case ARM::VST2LNdWB_register_Asm_32:
5563 case ARM::VST2LNqWB_register_Asm_16:
5564 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005565 MCInst TmpInst;
5566 // Shuffle the operands around so the lane index operand is in the
5567 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005568 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005569 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005570 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5571 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5572 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5573 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5574 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005575 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5576 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005577 TmpInst.addOperand(Inst.getOperand(1)); // lane
5578 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5579 TmpInst.addOperand(Inst.getOperand(6));
5580 Inst = TmpInst;
5581 return true;
5582 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005583
5584 case ARM::VST3LNdWB_register_Asm_8:
5585 case ARM::VST3LNdWB_register_Asm_16:
5586 case ARM::VST3LNdWB_register_Asm_32:
5587 case ARM::VST3LNqWB_register_Asm_16:
5588 case ARM::VST3LNqWB_register_Asm_32: {
5589 MCInst TmpInst;
5590 // Shuffle the operands around so the lane index operand is in the
5591 // right place.
5592 unsigned Spacing;
5593 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5594 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5595 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5596 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5597 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5598 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5599 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5600 Spacing));
5601 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5602 Spacing * 2));
5603 TmpInst.addOperand(Inst.getOperand(1)); // lane
5604 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5605 TmpInst.addOperand(Inst.getOperand(6));
5606 Inst = TmpInst;
5607 return true;
5608 }
5609
Jim Grosbach88a54de2012-01-24 18:53:13 +00005610 case ARM::VST4LNdWB_register_Asm_8:
5611 case ARM::VST4LNdWB_register_Asm_16:
5612 case ARM::VST4LNdWB_register_Asm_32:
5613 case ARM::VST4LNqWB_register_Asm_16:
5614 case ARM::VST4LNqWB_register_Asm_32: {
5615 MCInst TmpInst;
5616 // Shuffle the operands around so the lane index operand is in the
5617 // right place.
5618 unsigned Spacing;
5619 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5620 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5621 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5622 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5623 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5624 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5625 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5626 Spacing));
5627 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5628 Spacing * 2));
5629 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5630 Spacing * 3));
5631 TmpInst.addOperand(Inst.getOperand(1)); // lane
5632 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5633 TmpInst.addOperand(Inst.getOperand(6));
5634 Inst = TmpInst;
5635 return true;
5636 }
5637
Jim Grosbach8b31f952012-01-23 19:39:08 +00005638 case ARM::VST1LNdWB_fixed_Asm_8:
5639 case ARM::VST1LNdWB_fixed_Asm_16:
5640 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005641 MCInst TmpInst;
5642 // Shuffle the operands around so the lane index operand is in the
5643 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005644 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005645 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005646 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5647 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5648 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5649 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5650 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5651 TmpInst.addOperand(Inst.getOperand(1)); // lane
5652 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5653 TmpInst.addOperand(Inst.getOperand(5));
5654 Inst = TmpInst;
5655 return true;
5656 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005657
Jim Grosbach8b31f952012-01-23 19:39:08 +00005658 case ARM::VST2LNdWB_fixed_Asm_8:
5659 case ARM::VST2LNdWB_fixed_Asm_16:
5660 case ARM::VST2LNdWB_fixed_Asm_32:
5661 case ARM::VST2LNqWB_fixed_Asm_16:
5662 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005663 MCInst TmpInst;
5664 // Shuffle the operands around so the lane index operand is in the
5665 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005666 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005667 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005668 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5669 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5670 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5671 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5672 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005673 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5674 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005675 TmpInst.addOperand(Inst.getOperand(1)); // lane
5676 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5677 TmpInst.addOperand(Inst.getOperand(5));
5678 Inst = TmpInst;
5679 return true;
5680 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005681
5682 case ARM::VST3LNdWB_fixed_Asm_8:
5683 case ARM::VST3LNdWB_fixed_Asm_16:
5684 case ARM::VST3LNdWB_fixed_Asm_32:
5685 case ARM::VST3LNqWB_fixed_Asm_16:
5686 case ARM::VST3LNqWB_fixed_Asm_32: {
5687 MCInst TmpInst;
5688 // Shuffle the operands around so the lane index operand is in the
5689 // right place.
5690 unsigned Spacing;
5691 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5692 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5693 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5694 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5695 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5696 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5697 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5698 Spacing));
5699 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5700 Spacing * 2));
5701 TmpInst.addOperand(Inst.getOperand(1)); // lane
5702 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5703 TmpInst.addOperand(Inst.getOperand(5));
5704 Inst = TmpInst;
5705 return true;
5706 }
5707
Jim Grosbach88a54de2012-01-24 18:53:13 +00005708 case ARM::VST4LNdWB_fixed_Asm_8:
5709 case ARM::VST4LNdWB_fixed_Asm_16:
5710 case ARM::VST4LNdWB_fixed_Asm_32:
5711 case ARM::VST4LNqWB_fixed_Asm_16:
5712 case ARM::VST4LNqWB_fixed_Asm_32: {
5713 MCInst TmpInst;
5714 // Shuffle the operands around so the lane index operand is in the
5715 // right place.
5716 unsigned Spacing;
5717 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5718 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5719 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5720 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5721 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5722 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5723 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5724 Spacing));
5725 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5726 Spacing * 2));
5727 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5728 Spacing * 3));
5729 TmpInst.addOperand(Inst.getOperand(1)); // lane
5730 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5731 TmpInst.addOperand(Inst.getOperand(5));
5732 Inst = TmpInst;
5733 return true;
5734 }
5735
Jim Grosbach8b31f952012-01-23 19:39:08 +00005736 case ARM::VST1LNdAsm_8:
5737 case ARM::VST1LNdAsm_16:
5738 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005739 MCInst TmpInst;
5740 // Shuffle the operands around so the lane index operand is in the
5741 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005742 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005743 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005744 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5745 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5746 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5747 TmpInst.addOperand(Inst.getOperand(1)); // lane
5748 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5749 TmpInst.addOperand(Inst.getOperand(5));
5750 Inst = TmpInst;
5751 return true;
5752 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005753
Jim Grosbach8b31f952012-01-23 19:39:08 +00005754 case ARM::VST2LNdAsm_8:
5755 case ARM::VST2LNdAsm_16:
5756 case ARM::VST2LNdAsm_32:
5757 case ARM::VST2LNqAsm_16:
5758 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005759 MCInst TmpInst;
5760 // Shuffle the operands around so the lane index operand is in the
5761 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005762 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005763 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005764 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5765 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5766 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005767 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5768 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005769 TmpInst.addOperand(Inst.getOperand(1)); // lane
5770 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5771 TmpInst.addOperand(Inst.getOperand(5));
5772 Inst = TmpInst;
5773 return true;
5774 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005775
5776 case ARM::VST3LNdAsm_8:
5777 case ARM::VST3LNdAsm_16:
5778 case ARM::VST3LNdAsm_32:
5779 case ARM::VST3LNqAsm_16:
5780 case ARM::VST3LNqAsm_32: {
5781 MCInst TmpInst;
5782 // Shuffle the operands around so the lane index operand is in the
5783 // right place.
5784 unsigned Spacing;
5785 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5786 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5787 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5788 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5789 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5790 Spacing));
5791 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5792 Spacing * 2));
5793 TmpInst.addOperand(Inst.getOperand(1)); // lane
5794 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5795 TmpInst.addOperand(Inst.getOperand(5));
5796 Inst = TmpInst;
5797 return true;
5798 }
5799
Jim Grosbach88a54de2012-01-24 18:53:13 +00005800 case ARM::VST4LNdAsm_8:
5801 case ARM::VST4LNdAsm_16:
5802 case ARM::VST4LNdAsm_32:
5803 case ARM::VST4LNqAsm_16:
5804 case ARM::VST4LNqAsm_32: {
5805 MCInst TmpInst;
5806 // Shuffle the operands around so the lane index operand is in the
5807 // right place.
5808 unsigned Spacing;
5809 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5810 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5811 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5812 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5813 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5814 Spacing));
5815 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5816 Spacing * 2));
5817 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5818 Spacing * 3));
5819 TmpInst.addOperand(Inst.getOperand(1)); // lane
5820 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5821 TmpInst.addOperand(Inst.getOperand(5));
5822 Inst = TmpInst;
5823 return true;
5824 }
5825
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005826 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005827 case ARM::VLD1LNdWB_register_Asm_8:
5828 case ARM::VLD1LNdWB_register_Asm_16:
5829 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005830 MCInst TmpInst;
5831 // Shuffle the operands around so the lane index operand is in the
5832 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005833 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005834 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005835 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5836 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5837 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5838 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5839 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5840 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5841 TmpInst.addOperand(Inst.getOperand(1)); // lane
5842 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5843 TmpInst.addOperand(Inst.getOperand(6));
5844 Inst = TmpInst;
5845 return true;
5846 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005847
Jim Grosbach8b31f952012-01-23 19:39:08 +00005848 case ARM::VLD2LNdWB_register_Asm_8:
5849 case ARM::VLD2LNdWB_register_Asm_16:
5850 case ARM::VLD2LNdWB_register_Asm_32:
5851 case ARM::VLD2LNqWB_register_Asm_16:
5852 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005853 MCInst TmpInst;
5854 // Shuffle the operands around so the lane index operand is in the
5855 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005856 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005857 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005858 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005859 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5860 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005861 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5862 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5863 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5864 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5865 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005866 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5867 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005868 TmpInst.addOperand(Inst.getOperand(1)); // lane
5869 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5870 TmpInst.addOperand(Inst.getOperand(6));
5871 Inst = TmpInst;
5872 return true;
5873 }
5874
Jim Grosbach3a678af2012-01-23 21:53:26 +00005875 case ARM::VLD3LNdWB_register_Asm_8:
5876 case ARM::VLD3LNdWB_register_Asm_16:
5877 case ARM::VLD3LNdWB_register_Asm_32:
5878 case ARM::VLD3LNqWB_register_Asm_16:
5879 case ARM::VLD3LNqWB_register_Asm_32: {
5880 MCInst TmpInst;
5881 // Shuffle the operands around so the lane index operand is in the
5882 // right place.
5883 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005884 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005885 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5886 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5887 Spacing));
5888 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005889 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005890 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5891 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5892 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5893 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5894 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5895 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5896 Spacing));
5897 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005898 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005899 TmpInst.addOperand(Inst.getOperand(1)); // lane
5900 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5901 TmpInst.addOperand(Inst.getOperand(6));
5902 Inst = TmpInst;
5903 return true;
5904 }
5905
Jim Grosbache983a132012-01-24 18:37:25 +00005906 case ARM::VLD4LNdWB_register_Asm_8:
5907 case ARM::VLD4LNdWB_register_Asm_16:
5908 case ARM::VLD4LNdWB_register_Asm_32:
5909 case ARM::VLD4LNqWB_register_Asm_16:
5910 case ARM::VLD4LNqWB_register_Asm_32: {
5911 MCInst TmpInst;
5912 // Shuffle the operands around so the lane index operand is in the
5913 // right place.
5914 unsigned Spacing;
5915 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5916 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5917 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5918 Spacing));
5919 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5920 Spacing * 2));
5921 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5922 Spacing * 3));
5923 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5924 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5925 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5926 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5927 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5928 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5929 Spacing));
5930 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5931 Spacing * 2));
5932 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5933 Spacing * 3));
5934 TmpInst.addOperand(Inst.getOperand(1)); // lane
5935 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5936 TmpInst.addOperand(Inst.getOperand(6));
5937 Inst = TmpInst;
5938 return true;
5939 }
5940
Jim Grosbach8b31f952012-01-23 19:39:08 +00005941 case ARM::VLD1LNdWB_fixed_Asm_8:
5942 case ARM::VLD1LNdWB_fixed_Asm_16:
5943 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005944 MCInst TmpInst;
5945 // Shuffle the operands around so the lane index operand is in the
5946 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005947 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005948 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005949 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5950 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5951 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5952 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5953 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5954 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5955 TmpInst.addOperand(Inst.getOperand(1)); // lane
5956 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5957 TmpInst.addOperand(Inst.getOperand(5));
5958 Inst = TmpInst;
5959 return true;
5960 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005961
Jim Grosbach8b31f952012-01-23 19:39:08 +00005962 case ARM::VLD2LNdWB_fixed_Asm_8:
5963 case ARM::VLD2LNdWB_fixed_Asm_16:
5964 case ARM::VLD2LNdWB_fixed_Asm_32:
5965 case ARM::VLD2LNqWB_fixed_Asm_16:
5966 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005967 MCInst TmpInst;
5968 // Shuffle the operands around so the lane index operand is in the
5969 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005970 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005971 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005972 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005973 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5974 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005975 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5976 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5977 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5978 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5979 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005980 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5981 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005982 TmpInst.addOperand(Inst.getOperand(1)); // lane
5983 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5984 TmpInst.addOperand(Inst.getOperand(5));
5985 Inst = TmpInst;
5986 return true;
5987 }
5988
Jim Grosbach3a678af2012-01-23 21:53:26 +00005989 case ARM::VLD3LNdWB_fixed_Asm_8:
5990 case ARM::VLD3LNdWB_fixed_Asm_16:
5991 case ARM::VLD3LNdWB_fixed_Asm_32:
5992 case ARM::VLD3LNqWB_fixed_Asm_16:
5993 case ARM::VLD3LNqWB_fixed_Asm_32: {
5994 MCInst TmpInst;
5995 // Shuffle the operands around so the lane index operand is in the
5996 // right place.
5997 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005998 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005999 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6000 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6001 Spacing));
6002 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006003 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006004 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6005 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6006 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6007 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6008 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6009 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6010 Spacing));
6011 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006012 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006013 TmpInst.addOperand(Inst.getOperand(1)); // lane
6014 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6015 TmpInst.addOperand(Inst.getOperand(5));
6016 Inst = TmpInst;
6017 return true;
6018 }
6019
Jim Grosbache983a132012-01-24 18:37:25 +00006020 case ARM::VLD4LNdWB_fixed_Asm_8:
6021 case ARM::VLD4LNdWB_fixed_Asm_16:
6022 case ARM::VLD4LNdWB_fixed_Asm_32:
6023 case ARM::VLD4LNqWB_fixed_Asm_16:
6024 case ARM::VLD4LNqWB_fixed_Asm_32: {
6025 MCInst TmpInst;
6026 // Shuffle the operands around so the lane index operand is in the
6027 // right place.
6028 unsigned Spacing;
6029 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6030 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6031 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6032 Spacing));
6033 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6034 Spacing * 2));
6035 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6036 Spacing * 3));
6037 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6038 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6039 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6040 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6041 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6042 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6043 Spacing));
6044 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6045 Spacing * 2));
6046 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6047 Spacing * 3));
6048 TmpInst.addOperand(Inst.getOperand(1)); // lane
6049 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6050 TmpInst.addOperand(Inst.getOperand(5));
6051 Inst = TmpInst;
6052 return true;
6053 }
6054
Jim Grosbach8b31f952012-01-23 19:39:08 +00006055 case ARM::VLD1LNdAsm_8:
6056 case ARM::VLD1LNdAsm_16:
6057 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006058 MCInst TmpInst;
6059 // Shuffle the operands around so the lane index operand is in the
6060 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006061 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006062 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006063 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6064 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6065 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6066 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6067 TmpInst.addOperand(Inst.getOperand(1)); // lane
6068 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6069 TmpInst.addOperand(Inst.getOperand(5));
6070 Inst = TmpInst;
6071 return true;
6072 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006073
Jim Grosbach8b31f952012-01-23 19:39:08 +00006074 case ARM::VLD2LNdAsm_8:
6075 case ARM::VLD2LNdAsm_16:
6076 case ARM::VLD2LNdAsm_32:
6077 case ARM::VLD2LNqAsm_16:
6078 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006079 MCInst TmpInst;
6080 // Shuffle the operands around so the lane index operand is in the
6081 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006082 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006083 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006084 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006085 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6086 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006087 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6088 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6089 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== 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(1)); // lane
6093 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6094 TmpInst.addOperand(Inst.getOperand(5));
6095 Inst = TmpInst;
6096 return true;
6097 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006098
6099 case ARM::VLD3LNdAsm_8:
6100 case ARM::VLD3LNdAsm_16:
6101 case ARM::VLD3LNdAsm_32:
6102 case ARM::VLD3LNqAsm_16:
6103 case ARM::VLD3LNqAsm_32: {
6104 MCInst TmpInst;
6105 // Shuffle the operands around so the lane index operand is in the
6106 // right place.
6107 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006108 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006109 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6110 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6111 Spacing));
6112 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006113 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006114 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6115 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6116 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6117 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6118 Spacing));
6119 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006120 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006121 TmpInst.addOperand(Inst.getOperand(1)); // lane
6122 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6123 TmpInst.addOperand(Inst.getOperand(5));
6124 Inst = TmpInst;
6125 return true;
6126 }
6127
Jim Grosbache983a132012-01-24 18:37:25 +00006128 case ARM::VLD4LNdAsm_8:
6129 case ARM::VLD4LNdAsm_16:
6130 case ARM::VLD4LNdAsm_32:
6131 case ARM::VLD4LNqAsm_16:
6132 case ARM::VLD4LNqAsm_32: {
6133 MCInst TmpInst;
6134 // Shuffle the operands around so the lane index operand is in the
6135 // right place.
6136 unsigned Spacing;
6137 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6138 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6139 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6140 Spacing));
6141 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6142 Spacing * 2));
6143 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6144 Spacing * 3));
6145 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6146 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6147 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6148 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6149 Spacing));
6150 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6151 Spacing * 2));
6152 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6153 Spacing * 3));
6154 TmpInst.addOperand(Inst.getOperand(1)); // lane
6155 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6156 TmpInst.addOperand(Inst.getOperand(5));
6157 Inst = TmpInst;
6158 return true;
6159 }
6160
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006161 // VLD3DUP single 3-element structure to all lanes instructions.
6162 case ARM::VLD3DUPdAsm_8:
6163 case ARM::VLD3DUPdAsm_16:
6164 case ARM::VLD3DUPdAsm_32:
6165 case ARM::VLD3DUPqAsm_8:
6166 case ARM::VLD3DUPqAsm_16:
6167 case ARM::VLD3DUPqAsm_32: {
6168 MCInst TmpInst;
6169 unsigned Spacing;
6170 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6171 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6172 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6173 Spacing));
6174 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6175 Spacing * 2));
6176 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6177 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6178 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6179 TmpInst.addOperand(Inst.getOperand(4));
6180 Inst = TmpInst;
6181 return true;
6182 }
6183
6184 case ARM::VLD3DUPdWB_fixed_Asm_8:
6185 case ARM::VLD3DUPdWB_fixed_Asm_16:
6186 case ARM::VLD3DUPdWB_fixed_Asm_32:
6187 case ARM::VLD3DUPqWB_fixed_Asm_8:
6188 case ARM::VLD3DUPqWB_fixed_Asm_16:
6189 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6190 MCInst TmpInst;
6191 unsigned Spacing;
6192 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6193 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6194 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6195 Spacing));
6196 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6197 Spacing * 2));
6198 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6199 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6200 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6201 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6202 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6203 TmpInst.addOperand(Inst.getOperand(4));
6204 Inst = TmpInst;
6205 return true;
6206 }
6207
6208 case ARM::VLD3DUPdWB_register_Asm_8:
6209 case ARM::VLD3DUPdWB_register_Asm_16:
6210 case ARM::VLD3DUPdWB_register_Asm_32:
6211 case ARM::VLD3DUPqWB_register_Asm_8:
6212 case ARM::VLD3DUPqWB_register_Asm_16:
6213 case ARM::VLD3DUPqWB_register_Asm_32: {
6214 MCInst TmpInst;
6215 unsigned Spacing;
6216 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6217 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6218 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6219 Spacing));
6220 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6221 Spacing * 2));
6222 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6223 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6224 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6225 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6226 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6227 TmpInst.addOperand(Inst.getOperand(5));
6228 Inst = TmpInst;
6229 return true;
6230 }
6231
Jim Grosbachc387fc62012-01-23 23:20:46 +00006232 // VLD3 multiple 3-element structure instructions.
6233 case ARM::VLD3dAsm_8:
6234 case ARM::VLD3dAsm_16:
6235 case ARM::VLD3dAsm_32:
6236 case ARM::VLD3qAsm_8:
6237 case ARM::VLD3qAsm_16:
6238 case ARM::VLD3qAsm_32: {
6239 MCInst TmpInst;
6240 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006241 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006242 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6243 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6244 Spacing));
6245 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6246 Spacing * 2));
6247 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6248 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6249 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6250 TmpInst.addOperand(Inst.getOperand(4));
6251 Inst = TmpInst;
6252 return true;
6253 }
6254
6255 case ARM::VLD3dWB_fixed_Asm_8:
6256 case ARM::VLD3dWB_fixed_Asm_16:
6257 case ARM::VLD3dWB_fixed_Asm_32:
6258 case ARM::VLD3qWB_fixed_Asm_8:
6259 case ARM::VLD3qWB_fixed_Asm_16:
6260 case ARM::VLD3qWB_fixed_Asm_32: {
6261 MCInst TmpInst;
6262 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006263 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006264 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6265 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6266 Spacing));
6267 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6268 Spacing * 2));
6269 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6270 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6271 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6272 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6273 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6274 TmpInst.addOperand(Inst.getOperand(4));
6275 Inst = TmpInst;
6276 return true;
6277 }
6278
6279 case ARM::VLD3dWB_register_Asm_8:
6280 case ARM::VLD3dWB_register_Asm_16:
6281 case ARM::VLD3dWB_register_Asm_32:
6282 case ARM::VLD3qWB_register_Asm_8:
6283 case ARM::VLD3qWB_register_Asm_16:
6284 case ARM::VLD3qWB_register_Asm_32: {
6285 MCInst TmpInst;
6286 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006287 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006288 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6289 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6290 Spacing));
6291 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6292 Spacing * 2));
6293 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6294 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6295 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6296 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6297 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6298 TmpInst.addOperand(Inst.getOperand(5));
6299 Inst = TmpInst;
6300 return true;
6301 }
6302
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006303 // VLD4DUP single 3-element structure to all lanes instructions.
6304 case ARM::VLD4DUPdAsm_8:
6305 case ARM::VLD4DUPdAsm_16:
6306 case ARM::VLD4DUPdAsm_32:
6307 case ARM::VLD4DUPqAsm_8:
6308 case ARM::VLD4DUPqAsm_16:
6309 case ARM::VLD4DUPqAsm_32: {
6310 MCInst TmpInst;
6311 unsigned Spacing;
6312 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6313 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6314 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6315 Spacing));
6316 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6317 Spacing * 2));
6318 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6319 Spacing * 3));
6320 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6321 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6322 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6323 TmpInst.addOperand(Inst.getOperand(4));
6324 Inst = TmpInst;
6325 return true;
6326 }
6327
6328 case ARM::VLD4DUPdWB_fixed_Asm_8:
6329 case ARM::VLD4DUPdWB_fixed_Asm_16:
6330 case ARM::VLD4DUPdWB_fixed_Asm_32:
6331 case ARM::VLD4DUPqWB_fixed_Asm_8:
6332 case ARM::VLD4DUPqWB_fixed_Asm_16:
6333 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6334 MCInst TmpInst;
6335 unsigned Spacing;
6336 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6337 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6338 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6339 Spacing));
6340 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6341 Spacing * 2));
6342 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6343 Spacing * 3));
6344 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6345 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6346 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6347 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6348 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6349 TmpInst.addOperand(Inst.getOperand(4));
6350 Inst = TmpInst;
6351 return true;
6352 }
6353
6354 case ARM::VLD4DUPdWB_register_Asm_8:
6355 case ARM::VLD4DUPdWB_register_Asm_16:
6356 case ARM::VLD4DUPdWB_register_Asm_32:
6357 case ARM::VLD4DUPqWB_register_Asm_8:
6358 case ARM::VLD4DUPqWB_register_Asm_16:
6359 case ARM::VLD4DUPqWB_register_Asm_32: {
6360 MCInst TmpInst;
6361 unsigned Spacing;
6362 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6363 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6364 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6365 Spacing));
6366 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6367 Spacing * 2));
6368 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6369 Spacing * 3));
6370 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6371 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6372 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6373 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6374 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6375 TmpInst.addOperand(Inst.getOperand(5));
6376 Inst = TmpInst;
6377 return true;
6378 }
6379
6380 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006381 case ARM::VLD4dAsm_8:
6382 case ARM::VLD4dAsm_16:
6383 case ARM::VLD4dAsm_32:
6384 case ARM::VLD4qAsm_8:
6385 case ARM::VLD4qAsm_16:
6386 case ARM::VLD4qAsm_32: {
6387 MCInst TmpInst;
6388 unsigned Spacing;
6389 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6390 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6391 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6392 Spacing));
6393 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6394 Spacing * 2));
6395 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6396 Spacing * 3));
6397 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6398 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6399 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6400 TmpInst.addOperand(Inst.getOperand(4));
6401 Inst = TmpInst;
6402 return true;
6403 }
6404
6405 case ARM::VLD4dWB_fixed_Asm_8:
6406 case ARM::VLD4dWB_fixed_Asm_16:
6407 case ARM::VLD4dWB_fixed_Asm_32:
6408 case ARM::VLD4qWB_fixed_Asm_8:
6409 case ARM::VLD4qWB_fixed_Asm_16:
6410 case ARM::VLD4qWB_fixed_Asm_32: {
6411 MCInst TmpInst;
6412 unsigned Spacing;
6413 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6414 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6415 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6416 Spacing));
6417 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6418 Spacing * 2));
6419 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6420 Spacing * 3));
6421 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6422 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6423 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6424 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6425 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6426 TmpInst.addOperand(Inst.getOperand(4));
6427 Inst = TmpInst;
6428 return true;
6429 }
6430
6431 case ARM::VLD4dWB_register_Asm_8:
6432 case ARM::VLD4dWB_register_Asm_16:
6433 case ARM::VLD4dWB_register_Asm_32:
6434 case ARM::VLD4qWB_register_Asm_8:
6435 case ARM::VLD4qWB_register_Asm_16:
6436 case ARM::VLD4qWB_register_Asm_32: {
6437 MCInst TmpInst;
6438 unsigned Spacing;
6439 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6440 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6441 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6442 Spacing));
6443 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6444 Spacing * 2));
6445 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6446 Spacing * 3));
6447 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6448 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6449 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6450 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6451 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6452 TmpInst.addOperand(Inst.getOperand(5));
6453 Inst = TmpInst;
6454 return true;
6455 }
6456
Jim Grosbachd7433e22012-01-23 23:45:44 +00006457 // VST3 multiple 3-element structure instructions.
6458 case ARM::VST3dAsm_8:
6459 case ARM::VST3dAsm_16:
6460 case ARM::VST3dAsm_32:
6461 case ARM::VST3qAsm_8:
6462 case ARM::VST3qAsm_16:
6463 case ARM::VST3qAsm_32: {
6464 MCInst TmpInst;
6465 unsigned Spacing;
6466 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6467 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6468 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6469 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6470 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6471 Spacing));
6472 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6473 Spacing * 2));
6474 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6475 TmpInst.addOperand(Inst.getOperand(4));
6476 Inst = TmpInst;
6477 return true;
6478 }
6479
6480 case ARM::VST3dWB_fixed_Asm_8:
6481 case ARM::VST3dWB_fixed_Asm_16:
6482 case ARM::VST3dWB_fixed_Asm_32:
6483 case ARM::VST3qWB_fixed_Asm_8:
6484 case ARM::VST3qWB_fixed_Asm_16:
6485 case ARM::VST3qWB_fixed_Asm_32: {
6486 MCInst TmpInst;
6487 unsigned Spacing;
6488 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6489 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6490 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6491 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6492 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6493 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6494 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6495 Spacing));
6496 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6497 Spacing * 2));
6498 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6499 TmpInst.addOperand(Inst.getOperand(4));
6500 Inst = TmpInst;
6501 return true;
6502 }
6503
6504 case ARM::VST3dWB_register_Asm_8:
6505 case ARM::VST3dWB_register_Asm_16:
6506 case ARM::VST3dWB_register_Asm_32:
6507 case ARM::VST3qWB_register_Asm_8:
6508 case ARM::VST3qWB_register_Asm_16:
6509 case ARM::VST3qWB_register_Asm_32: {
6510 MCInst TmpInst;
6511 unsigned Spacing;
6512 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6513 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6514 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6515 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6516 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6517 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6518 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6519 Spacing));
6520 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6521 Spacing * 2));
6522 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6523 TmpInst.addOperand(Inst.getOperand(5));
6524 Inst = TmpInst;
6525 return true;
6526 }
6527
Jim Grosbach539aab72012-01-24 00:58:13 +00006528 // VST4 multiple 3-element structure instructions.
6529 case ARM::VST4dAsm_8:
6530 case ARM::VST4dAsm_16:
6531 case ARM::VST4dAsm_32:
6532 case ARM::VST4qAsm_8:
6533 case ARM::VST4qAsm_16:
6534 case ARM::VST4qAsm_32: {
6535 MCInst TmpInst;
6536 unsigned Spacing;
6537 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6538 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6539 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6540 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6541 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6542 Spacing));
6543 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6544 Spacing * 2));
6545 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6546 Spacing * 3));
6547 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6548 TmpInst.addOperand(Inst.getOperand(4));
6549 Inst = TmpInst;
6550 return true;
6551 }
6552
6553 case ARM::VST4dWB_fixed_Asm_8:
6554 case ARM::VST4dWB_fixed_Asm_16:
6555 case ARM::VST4dWB_fixed_Asm_32:
6556 case ARM::VST4qWB_fixed_Asm_8:
6557 case ARM::VST4qWB_fixed_Asm_16:
6558 case ARM::VST4qWB_fixed_Asm_32: {
6559 MCInst TmpInst;
6560 unsigned Spacing;
6561 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6562 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6563 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6564 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6565 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6566 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6567 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6568 Spacing));
6569 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6570 Spacing * 2));
6571 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6572 Spacing * 3));
6573 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6574 TmpInst.addOperand(Inst.getOperand(4));
6575 Inst = TmpInst;
6576 return true;
6577 }
6578
6579 case ARM::VST4dWB_register_Asm_8:
6580 case ARM::VST4dWB_register_Asm_16:
6581 case ARM::VST4dWB_register_Asm_32:
6582 case ARM::VST4qWB_register_Asm_8:
6583 case ARM::VST4qWB_register_Asm_16:
6584 case ARM::VST4qWB_register_Asm_32: {
6585 MCInst TmpInst;
6586 unsigned Spacing;
6587 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6588 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6589 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6590 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6591 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6592 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6593 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6594 Spacing));
6595 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6596 Spacing * 2));
6597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6598 Spacing * 3));
6599 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6600 TmpInst.addOperand(Inst.getOperand(5));
6601 Inst = TmpInst;
6602 return true;
6603 }
6604
Jim Grosbach863d2af2011-12-13 22:45:11 +00006605 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006606 case ARM::t2MOVsr:
6607 case ARM::t2MOVSsr: {
6608 // Which instruction to expand to depends on the CCOut operand and
6609 // whether we're in an IT block if the register operands are low
6610 // registers.
6611 bool isNarrow = false;
6612 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6613 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6614 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6615 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6616 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6617 isNarrow = true;
6618 MCInst TmpInst;
6619 unsigned newOpc;
6620 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6621 default: llvm_unreachable("unexpected opcode!");
6622 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6623 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6624 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6625 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6626 }
6627 TmpInst.setOpcode(newOpc);
6628 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6629 if (isNarrow)
6630 TmpInst.addOperand(MCOperand::CreateReg(
6631 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6632 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6633 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6634 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6635 TmpInst.addOperand(Inst.getOperand(5));
6636 if (!isNarrow)
6637 TmpInst.addOperand(MCOperand::CreateReg(
6638 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6639 Inst = TmpInst;
6640 return true;
6641 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006642 case ARM::t2MOVsi:
6643 case ARM::t2MOVSsi: {
6644 // Which instruction to expand to depends on the CCOut operand and
6645 // whether we're in an IT block if the register operands are low
6646 // registers.
6647 bool isNarrow = false;
6648 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6649 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6650 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6651 isNarrow = true;
6652 MCInst TmpInst;
6653 unsigned newOpc;
6654 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6655 default: llvm_unreachable("unexpected opcode!");
6656 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6657 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6658 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6659 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006660 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006661 }
6662 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6663 if (Ammount == 32) Ammount = 0;
6664 TmpInst.setOpcode(newOpc);
6665 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6666 if (isNarrow)
6667 TmpInst.addOperand(MCOperand::CreateReg(
6668 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6669 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006670 if (newOpc != ARM::t2RRX)
6671 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006672 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6673 TmpInst.addOperand(Inst.getOperand(4));
6674 if (!isNarrow)
6675 TmpInst.addOperand(MCOperand::CreateReg(
6676 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6677 Inst = TmpInst;
6678 return true;
6679 }
6680 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006681 case ARM::ASRr:
6682 case ARM::LSRr:
6683 case ARM::LSLr:
6684 case ARM::RORr: {
6685 ARM_AM::ShiftOpc ShiftTy;
6686 switch(Inst.getOpcode()) {
6687 default: llvm_unreachable("unexpected opcode!");
6688 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6689 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6690 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6691 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6692 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006693 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6694 MCInst TmpInst;
6695 TmpInst.setOpcode(ARM::MOVsr);
6696 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6697 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6698 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6699 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6700 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6701 TmpInst.addOperand(Inst.getOperand(4));
6702 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6703 Inst = TmpInst;
6704 return true;
6705 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006706 case ARM::ASRi:
6707 case ARM::LSRi:
6708 case ARM::LSLi:
6709 case ARM::RORi: {
6710 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006711 switch(Inst.getOpcode()) {
6712 default: llvm_unreachable("unexpected opcode!");
6713 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6714 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6715 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6716 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6717 }
6718 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006719 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006720 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6721 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006722 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006723 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006724 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6725 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006726 if (Opc == ARM::MOVsi)
6727 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006728 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6729 TmpInst.addOperand(Inst.getOperand(4));
6730 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6731 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006732 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006733 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006734 case ARM::RRXi: {
6735 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6736 MCInst TmpInst;
6737 TmpInst.setOpcode(ARM::MOVsi);
6738 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6739 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6740 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6741 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6742 TmpInst.addOperand(Inst.getOperand(3));
6743 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6744 Inst = TmpInst;
6745 return true;
6746 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006747 case ARM::t2LDMIA_UPD: {
6748 // If this is a load of a single register, then we should use
6749 // a post-indexed LDR instruction instead, per the ARM ARM.
6750 if (Inst.getNumOperands() != 5)
6751 return false;
6752 MCInst TmpInst;
6753 TmpInst.setOpcode(ARM::t2LDR_POST);
6754 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6755 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6756 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6757 TmpInst.addOperand(MCOperand::CreateImm(4));
6758 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6759 TmpInst.addOperand(Inst.getOperand(3));
6760 Inst = TmpInst;
6761 return true;
6762 }
6763 case ARM::t2STMDB_UPD: {
6764 // If this is a store of a single register, then we should use
6765 // a pre-indexed STR instruction instead, per the ARM ARM.
6766 if (Inst.getNumOperands() != 5)
6767 return false;
6768 MCInst TmpInst;
6769 TmpInst.setOpcode(ARM::t2STR_PRE);
6770 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6771 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6772 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6773 TmpInst.addOperand(MCOperand::CreateImm(-4));
6774 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6775 TmpInst.addOperand(Inst.getOperand(3));
6776 Inst = TmpInst;
6777 return true;
6778 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006779 case ARM::LDMIA_UPD:
6780 // If this is a load of a single register via a 'pop', then we should use
6781 // a post-indexed LDR instruction instead, per the ARM ARM.
6782 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6783 Inst.getNumOperands() == 5) {
6784 MCInst TmpInst;
6785 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6786 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6787 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6788 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6789 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6790 TmpInst.addOperand(MCOperand::CreateImm(4));
6791 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6792 TmpInst.addOperand(Inst.getOperand(3));
6793 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006794 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006795 }
6796 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006797 case ARM::STMDB_UPD:
6798 // If this is a store of a single register via a 'push', then we should use
6799 // a pre-indexed STR instruction instead, per the ARM ARM.
6800 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6801 Inst.getNumOperands() == 5) {
6802 MCInst TmpInst;
6803 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6804 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6805 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6806 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6807 TmpInst.addOperand(MCOperand::CreateImm(-4));
6808 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6809 TmpInst.addOperand(Inst.getOperand(3));
6810 Inst = TmpInst;
6811 }
6812 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006813 case ARM::t2ADDri12:
6814 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6815 // mnemonic was used (not "addw"), encoding T3 is preferred.
6816 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6817 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6818 break;
6819 Inst.setOpcode(ARM::t2ADDri);
6820 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6821 break;
6822 case ARM::t2SUBri12:
6823 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6824 // mnemonic was used (not "subw"), encoding T3 is preferred.
6825 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6826 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6827 break;
6828 Inst.setOpcode(ARM::t2SUBri);
6829 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6830 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006831 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006832 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6833 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6834 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6835 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006836 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006837 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006838 return true;
6839 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006840 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006841 case ARM::tSUBi8:
6842 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6843 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6844 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6845 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006846 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006847 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006848 return true;
6849 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006850 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006851 case ARM::t2ADDrr: {
6852 // If the destination and first source operand are the same, and
6853 // there's no setting of the flags, use encoding T2 instead of T3.
6854 // Note that this is only for ADD, not SUB. This mirrors the system
6855 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6856 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6857 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006858 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6859 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006860 break;
6861 MCInst TmpInst;
6862 TmpInst.setOpcode(ARM::tADDhirr);
6863 TmpInst.addOperand(Inst.getOperand(0));
6864 TmpInst.addOperand(Inst.getOperand(0));
6865 TmpInst.addOperand(Inst.getOperand(2));
6866 TmpInst.addOperand(Inst.getOperand(3));
6867 TmpInst.addOperand(Inst.getOperand(4));
6868 Inst = TmpInst;
6869 return true;
6870 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006871 case ARM::tB:
6872 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006873 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006874 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006875 return true;
6876 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006877 break;
6878 case ARM::t2B:
6879 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006880 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006881 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006882 return true;
6883 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006884 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006885 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006886 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006887 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006888 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006889 return true;
6890 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006891 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006892 case ARM::tBcc:
6893 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006894 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006895 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006896 return true;
6897 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006898 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006899 case ARM::tLDMIA: {
6900 // If the register list contains any high registers, or if the writeback
6901 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6902 // instead if we're in Thumb2. Otherwise, this should have generated
6903 // an error in validateInstruction().
6904 unsigned Rn = Inst.getOperand(0).getReg();
6905 bool hasWritebackToken =
6906 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6907 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6908 bool listContainsBase;
6909 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6910 (!listContainsBase && !hasWritebackToken) ||
6911 (listContainsBase && hasWritebackToken)) {
6912 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6913 assert (isThumbTwo());
6914 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6915 // If we're switching to the updating version, we need to insert
6916 // the writeback tied operand.
6917 if (hasWritebackToken)
6918 Inst.insert(Inst.begin(),
6919 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006920 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006921 }
6922 break;
6923 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006924 case ARM::tSTMIA_UPD: {
6925 // If the register list contains any high registers, we need to use
6926 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6927 // should have generated an error in validateInstruction().
6928 unsigned Rn = Inst.getOperand(0).getReg();
6929 bool listContainsBase;
6930 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6931 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6932 assert (isThumbTwo());
6933 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006934 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006935 }
6936 break;
6937 }
Jim Grosbach54026372011-11-10 23:17:11 +00006938 case ARM::tPOP: {
6939 bool listContainsBase;
6940 // If the register list contains any high registers, we need to use
6941 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6942 // should have generated an error in validateInstruction().
6943 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006944 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006945 assert (isThumbTwo());
6946 Inst.setOpcode(ARM::t2LDMIA_UPD);
6947 // Add the base register and writeback operands.
6948 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6949 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006950 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006951 }
6952 case ARM::tPUSH: {
6953 bool listContainsBase;
6954 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006955 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006956 assert (isThumbTwo());
6957 Inst.setOpcode(ARM::t2STMDB_UPD);
6958 // Add the base register and writeback operands.
6959 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6960 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006961 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006962 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006963 case ARM::t2MOVi: {
6964 // If we can use the 16-bit encoding and the user didn't explicitly
6965 // request the 32-bit variant, transform it here.
6966 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6967 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006968 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6969 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6970 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006971 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6972 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6973 // The operands aren't in the same order for tMOVi8...
6974 MCInst TmpInst;
6975 TmpInst.setOpcode(ARM::tMOVi8);
6976 TmpInst.addOperand(Inst.getOperand(0));
6977 TmpInst.addOperand(Inst.getOperand(4));
6978 TmpInst.addOperand(Inst.getOperand(1));
6979 TmpInst.addOperand(Inst.getOperand(2));
6980 TmpInst.addOperand(Inst.getOperand(3));
6981 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006982 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006983 }
6984 break;
6985 }
6986 case ARM::t2MOVr: {
6987 // If we can use the 16-bit encoding and the user didn't explicitly
6988 // request the 32-bit variant, transform it here.
6989 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6990 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6991 Inst.getOperand(2).getImm() == ARMCC::AL &&
6992 Inst.getOperand(4).getReg() == ARM::CPSR &&
6993 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6994 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6995 // The operands aren't the same for tMOV[S]r... (no cc_out)
6996 MCInst TmpInst;
6997 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6998 TmpInst.addOperand(Inst.getOperand(0));
6999 TmpInst.addOperand(Inst.getOperand(1));
7000 TmpInst.addOperand(Inst.getOperand(2));
7001 TmpInst.addOperand(Inst.getOperand(3));
7002 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007003 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007004 }
7005 break;
7006 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007007 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007008 case ARM::t2SXTB:
7009 case ARM::t2UXTH:
7010 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007011 // If we can use the 16-bit encoding and the user didn't explicitly
7012 // request the 32-bit variant, transform it here.
7013 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7014 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7015 Inst.getOperand(2).getImm() == 0 &&
7016 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7017 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007018 unsigned NewOpc;
7019 switch (Inst.getOpcode()) {
7020 default: llvm_unreachable("Illegal opcode!");
7021 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7022 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7023 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7024 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7025 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007026 // The operands aren't the same for thumb1 (no rotate operand).
7027 MCInst TmpInst;
7028 TmpInst.setOpcode(NewOpc);
7029 TmpInst.addOperand(Inst.getOperand(0));
7030 TmpInst.addOperand(Inst.getOperand(1));
7031 TmpInst.addOperand(Inst.getOperand(3));
7032 TmpInst.addOperand(Inst.getOperand(4));
7033 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007034 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007035 }
7036 break;
7037 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007038 case ARM::MOVsi: {
7039 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7040 if (SOpc == ARM_AM::rrx) return false;
7041 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7042 // Shifting by zero is accepted as a vanilla 'MOVr'
7043 MCInst TmpInst;
7044 TmpInst.setOpcode(ARM::MOVr);
7045 TmpInst.addOperand(Inst.getOperand(0));
7046 TmpInst.addOperand(Inst.getOperand(1));
7047 TmpInst.addOperand(Inst.getOperand(3));
7048 TmpInst.addOperand(Inst.getOperand(4));
7049 TmpInst.addOperand(Inst.getOperand(5));
7050 Inst = TmpInst;
7051 return true;
7052 }
7053 return false;
7054 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007055 case ARM::ANDrsi:
7056 case ARM::ORRrsi:
7057 case ARM::EORrsi:
7058 case ARM::BICrsi:
7059 case ARM::SUBrsi:
7060 case ARM::ADDrsi: {
7061 unsigned newOpc;
7062 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7063 if (SOpc == ARM_AM::rrx) return false;
7064 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007065 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007066 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7067 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7068 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7069 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7070 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7071 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7072 }
7073 // If the shift is by zero, use the non-shifted instruction definition.
7074 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7075 MCInst TmpInst;
7076 TmpInst.setOpcode(newOpc);
7077 TmpInst.addOperand(Inst.getOperand(0));
7078 TmpInst.addOperand(Inst.getOperand(1));
7079 TmpInst.addOperand(Inst.getOperand(2));
7080 TmpInst.addOperand(Inst.getOperand(4));
7081 TmpInst.addOperand(Inst.getOperand(5));
7082 TmpInst.addOperand(Inst.getOperand(6));
7083 Inst = TmpInst;
7084 return true;
7085 }
7086 return false;
7087 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007088 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007089 case ARM::t2IT: {
7090 // The mask bits for all but the first condition are represented as
7091 // the low bit of the condition code value implies 't'. We currently
7092 // always have 1 implies 't', so XOR toggle the bits if the low bit
7093 // of the condition code is zero. The encoding also expects the low
7094 // bit of the condition to be encoded as bit 4 of the mask operand,
7095 // so mask that in if needed
7096 MCOperand &MO = Inst.getOperand(1);
7097 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007098 unsigned OrigMask = Mask;
7099 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007100 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007101 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7102 for (unsigned i = 3; i != TZ; --i)
7103 Mask ^= 1 << i;
7104 } else
7105 Mask |= 0x10;
7106 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007107
7108 // Set up the IT block state according to the IT instruction we just
7109 // matched.
7110 assert(!inITBlock() && "nested IT blocks?!");
7111 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7112 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7113 ITState.CurPosition = 0;
7114 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007115 break;
7116 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007117 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007118 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007119}
7120
Jim Grosbach47a0d522011-08-16 20:45:50 +00007121unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7122 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7123 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007124 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007125 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007126 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7127 assert(MCID.hasOptionalDef() &&
7128 "optionally flag setting instruction missing optional def operand");
7129 assert(MCID.NumOperands == Inst.getNumOperands() &&
7130 "operand count mismatch!");
7131 // Find the optional-def operand (cc_out).
7132 unsigned OpNo;
7133 for (OpNo = 0;
7134 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7135 ++OpNo)
7136 ;
7137 // If we're parsing Thumb1, reject it completely.
7138 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7139 return Match_MnemonicFail;
7140 // If we're parsing Thumb2, which form is legal depends on whether we're
7141 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007142 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7143 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007144 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007145 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7146 inITBlock())
7147 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007148 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007149 // Some high-register supporting Thumb1 encodings only allow both registers
7150 // to be from r0-r7 when in Thumb2.
7151 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7152 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7153 isARMLowRegister(Inst.getOperand(2).getReg()))
7154 return Match_RequiresThumb2;
7155 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007156 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007157 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7158 isARMLowRegister(Inst.getOperand(1).getReg()))
7159 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007160 return Match_Success;
7161}
7162
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007163bool ARMAsmParser::
7164MatchAndEmitInstruction(SMLoc IDLoc,
7165 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7166 MCStreamer &Out) {
7167 MCInst Inst;
7168 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007169 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007170 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007171 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007172 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007173 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007174 // Context sensitive operand constraints aren't handled by the matcher,
7175 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007176 if (validateInstruction(Inst, Operands)) {
7177 // Still progress the IT block, otherwise one wrong condition causes
7178 // nasty cascading errors.
7179 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007180 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007181 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007182
Jim Grosbachf8fce712011-08-11 17:35:48 +00007183 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007184 // encoding is selected. Loop on it while changes happen so the
7185 // individual transformations can chain off each other. E.g.,
7186 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7187 while (processInstruction(Inst, Operands))
7188 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007189
Jim Grosbacha1109882011-09-02 23:22:08 +00007190 // Only move forward at the very end so that everything in validate
7191 // and process gets a consistent answer about whether we're in an IT
7192 // block.
7193 forwardITPosition();
7194
Jim Grosbach74423e32012-01-25 19:52:01 +00007195 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7196 // doesn't actually encode.
7197 if (Inst.getOpcode() == ARM::ITasm)
7198 return false;
7199
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007200 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007201 Out.EmitInstruction(Inst);
7202 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007203 case Match_MissingFeature:
7204 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7205 return true;
7206 case Match_InvalidOperand: {
7207 SMLoc ErrorLoc = IDLoc;
7208 if (ErrorInfo != ~0U) {
7209 if (ErrorInfo >= Operands.size())
7210 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007211
Chris Lattnere73d4f82010-10-28 21:41:58 +00007212 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7213 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7214 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007215
Chris Lattnere73d4f82010-10-28 21:41:58 +00007216 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007217 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007218 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007219 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007220 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007221 // The converter function will have already emited a diagnostic.
7222 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007223 case Match_RequiresNotITBlock:
7224 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007225 case Match_RequiresITBlock:
7226 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007227 case Match_RequiresV6:
7228 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7229 case Match_RequiresThumb2:
7230 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007231 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007232
Eric Christopherc223e2b2010-10-29 09:26:59 +00007233 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007234}
7235
Jim Grosbach1355cf12011-07-26 17:10:22 +00007236/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007237bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7238 StringRef IDVal = DirectiveID.getIdentifier();
7239 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007240 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007241 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007242 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007243 else if (IDVal == ".arm")
7244 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007245 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007246 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007247 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007248 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007249 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007250 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007251 else if (IDVal == ".unreq")
7252 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007253 else if (IDVal == ".arch")
7254 return parseDirectiveArch(DirectiveID.getLoc());
7255 else if (IDVal == ".eabi_attribute")
7256 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007257 return true;
7258}
7259
Jim Grosbach1355cf12011-07-26 17:10:22 +00007260/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007261/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007262bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007263 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7264 for (;;) {
7265 const MCExpr *Value;
7266 if (getParser().ParseExpression(Value))
7267 return true;
7268
Chris Lattneraaec2052010-01-19 19:46:13 +00007269 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007270
7271 if (getLexer().is(AsmToken::EndOfStatement))
7272 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007273
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007274 // FIXME: Improve diagnostic.
7275 if (getLexer().isNot(AsmToken::Comma))
7276 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007277 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007278 }
7279 }
7280
Sean Callananb9a25b72010-01-19 20:27:46 +00007281 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007282 return false;
7283}
7284
Jim Grosbach1355cf12011-07-26 17:10:22 +00007285/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007286/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007287bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007288 if (getLexer().isNot(AsmToken::EndOfStatement))
7289 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007290 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007291
Jim Grosbach9a70df92011-12-07 18:04:19 +00007292 if (!isThumb())
7293 SwitchMode();
7294 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7295 return false;
7296}
7297
7298/// parseDirectiveARM
7299/// ::= .arm
7300bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7301 if (getLexer().isNot(AsmToken::EndOfStatement))
7302 return Error(L, "unexpected token in directive");
7303 Parser.Lex();
7304
7305 if (isThumb())
7306 SwitchMode();
7307 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007308 return false;
7309}
7310
Jim Grosbach1355cf12011-07-26 17:10:22 +00007311/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007312/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007313bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007314 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7315 bool isMachO = MAI.hasSubsectionsViaSymbols();
7316 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007317 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007318
Jim Grosbachde4d8392011-12-21 22:30:16 +00007319 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007320 // ELF doesn't
7321 if (isMachO) {
7322 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007323 if (Tok.isNot(AsmToken::EndOfStatement)) {
7324 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7325 return Error(L, "unexpected token in .thumb_func directive");
7326 Name = Tok.getIdentifier();
7327 Parser.Lex(); // Consume the identifier token.
7328 needFuncName = false;
7329 }
Rafael Espindola64695402011-05-16 16:17:21 +00007330 }
7331
Jim Grosbachde4d8392011-12-21 22:30:16 +00007332 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007333 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007334
7335 // Eat the end of statement and any blank lines that follow.
7336 while (getLexer().is(AsmToken::EndOfStatement))
7337 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007338
Rafael Espindola64695402011-05-16 16:17:21 +00007339 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007340 // We really should be checking the next symbol definition even if there's
7341 // stuff in between.
7342 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007343 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007344 }
7345
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007346 // Mark symbol as a thumb symbol.
7347 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7348 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007349 return false;
7350}
7351
Jim Grosbach1355cf12011-07-26 17:10:22 +00007352/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007353/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007354bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007355 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007356 if (Tok.isNot(AsmToken::Identifier))
7357 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007358 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007359 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007360 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007361 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007362 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007363 else
7364 return Error(L, "unrecognized syntax mode in .syntax directive");
7365
7366 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007367 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007368 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007369
7370 // TODO tell the MC streamer the mode
7371 // getParser().getStreamer().Emit???();
7372 return false;
7373}
7374
Jim Grosbach1355cf12011-07-26 17:10:22 +00007375/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007376/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007377bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007378 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007379 if (Tok.isNot(AsmToken::Integer))
7380 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007381 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007382 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007383 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007384 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007385 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007386 else
7387 return Error(L, "invalid operand to .code directive");
7388
7389 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007390 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007391 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007392
Evan Cheng32869202011-07-08 22:36:29 +00007393 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007394 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007395 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007396 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007397 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007398 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007399 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007400 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007401 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007402
Kevin Enderby515d5092009-10-15 20:48:48 +00007403 return false;
7404}
7405
Jim Grosbacha39cda72011-12-14 02:16:11 +00007406/// parseDirectiveReq
7407/// ::= name .req registername
7408bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7409 Parser.Lex(); // Eat the '.req' token.
7410 unsigned Reg;
7411 SMLoc SRegLoc, ERegLoc;
7412 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7413 Parser.EatToEndOfStatement();
7414 return Error(SRegLoc, "register name expected");
7415 }
7416
7417 // Shouldn't be anything else.
7418 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7419 Parser.EatToEndOfStatement();
7420 return Error(Parser.getTok().getLoc(),
7421 "unexpected input in .req directive.");
7422 }
7423
7424 Parser.Lex(); // Consume the EndOfStatement
7425
7426 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7427 return Error(SRegLoc, "redefinition of '" + Name +
7428 "' does not match original.");
7429
7430 return false;
7431}
7432
7433/// parseDirectiveUneq
7434/// ::= .unreq registername
7435bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7436 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7437 Parser.EatToEndOfStatement();
7438 return Error(L, "unexpected input in .unreq directive.");
7439 }
7440 RegisterReqs.erase(Parser.getTok().getIdentifier());
7441 Parser.Lex(); // Eat the identifier.
7442 return false;
7443}
7444
Jason W Kimd7c9e082011-12-20 17:38:12 +00007445/// parseDirectiveArch
7446/// ::= .arch token
7447bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7448 return true;
7449}
7450
7451/// parseDirectiveEabiAttr
7452/// ::= .eabi_attribute int, int
7453bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7454 return true;
7455}
7456
Sean Callanan90b70972010-04-07 20:29:34 +00007457extern "C" void LLVMInitializeARMAsmLexer();
7458
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007459/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007460extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007461 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7462 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007463 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007464}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007465
Chris Lattner0692ee62010-09-06 19:11:01 +00007466#define GET_REGISTER_MATCHER
7467#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007468#include "ARMGenAsmMatcher.inc"