blob: 845f0a329965fbcf5a98293794a1c1341f9540cf [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 Grosbach280dfad2011-10-21 18:54:25 +00001088 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001089 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001090 return VectorList.Count == 2;
1091 }
1092
Jim Grosbach28f08c92012-03-05 19:33:30 +00001093 bool isVecListDPair() const {
1094 if (!isSingleSpacedVectorList()) return false;
1095 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1096 .contains(VectorList.RegNum));
1097 }
1098
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001099 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001101 return VectorList.Count == 3;
1102 }
1103
Jim Grosbachb6310312011-10-21 20:35:01 +00001104 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001105 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001106 return VectorList.Count == 4;
1107 }
1108
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001109 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001110 if (!isDoubleSpacedVectorList()) return false;
1111 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001112 }
1113
Jim Grosbachc387fc62012-01-23 23:20:46 +00001114 bool isVecListThreeQ() const {
1115 if (!isDoubleSpacedVectorList()) return false;
1116 return VectorList.Count == 3;
1117 }
1118
Jim Grosbach7945ead2012-01-24 00:43:12 +00001119 bool isVecListFourQ() const {
1120 if (!isDoubleSpacedVectorList()) return false;
1121 return VectorList.Count == 4;
1122 }
1123
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001124 bool isSingleSpacedVectorAllLanes() const {
1125 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1126 }
1127 bool isDoubleSpacedVectorAllLanes() const {
1128 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1129 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001130 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001131 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001132 return VectorList.Count == 1;
1133 }
1134
Jim Grosbach13af2222011-11-30 18:21:25 +00001135 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001136 if (!isSingleSpacedVectorAllLanes()) return false;
1137 return VectorList.Count == 2;
1138 }
1139
1140 bool isVecListTwoQAllLanes() const {
1141 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001142 return VectorList.Count == 2;
1143 }
1144
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001145 bool isVecListThreeDAllLanes() const {
1146 if (!isSingleSpacedVectorAllLanes()) return false;
1147 return VectorList.Count == 3;
1148 }
1149
1150 bool isVecListThreeQAllLanes() const {
1151 if (!isDoubleSpacedVectorAllLanes()) return false;
1152 return VectorList.Count == 3;
1153 }
1154
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001155 bool isVecListFourDAllLanes() const {
1156 if (!isSingleSpacedVectorAllLanes()) return false;
1157 return VectorList.Count == 4;
1158 }
1159
1160 bool isVecListFourQAllLanes() const {
1161 if (!isDoubleSpacedVectorAllLanes()) return false;
1162 return VectorList.Count == 4;
1163 }
1164
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001165 bool isSingleSpacedVectorIndexed() const {
1166 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1167 }
1168 bool isDoubleSpacedVectorIndexed() const {
1169 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1170 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001171 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001172 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001173 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1174 }
1175
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001176 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001177 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001178 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1179 }
1180
1181 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001182 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001183 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1184 }
1185
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001186 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001187 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001188 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1189 }
1190
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001191 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001192 if (!isSingleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1194 }
1195
1196 bool isVecListTwoQWordIndexed() const {
1197 if (!isDoubleSpacedVectorIndexed()) return false;
1198 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1199 }
1200
1201 bool isVecListTwoQHWordIndexed() const {
1202 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001203 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1204 }
1205
1206 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001207 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001208 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1209 }
1210
Jim Grosbach3a678af2012-01-23 21:53:26 +00001211 bool isVecListThreeDByteIndexed() const {
1212 if (!isSingleSpacedVectorIndexed()) return false;
1213 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1214 }
1215
1216 bool isVecListThreeDHWordIndexed() const {
1217 if (!isSingleSpacedVectorIndexed()) return false;
1218 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1219 }
1220
1221 bool isVecListThreeQWordIndexed() const {
1222 if (!isDoubleSpacedVectorIndexed()) return false;
1223 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1224 }
1225
1226 bool isVecListThreeQHWordIndexed() const {
1227 if (!isDoubleSpacedVectorIndexed()) return false;
1228 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1229 }
1230
1231 bool isVecListThreeDWordIndexed() const {
1232 if (!isSingleSpacedVectorIndexed()) return false;
1233 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1234 }
1235
Jim Grosbache983a132012-01-24 18:37:25 +00001236 bool isVecListFourDByteIndexed() const {
1237 if (!isSingleSpacedVectorIndexed()) return false;
1238 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1239 }
1240
1241 bool isVecListFourDHWordIndexed() const {
1242 if (!isSingleSpacedVectorIndexed()) return false;
1243 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1244 }
1245
1246 bool isVecListFourQWordIndexed() const {
1247 if (!isDoubleSpacedVectorIndexed()) return false;
1248 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1249 }
1250
1251 bool isVecListFourQHWordIndexed() const {
1252 if (!isDoubleSpacedVectorIndexed()) return false;
1253 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1254 }
1255
1256 bool isVecListFourDWordIndexed() const {
1257 if (!isSingleSpacedVectorIndexed()) return false;
1258 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1259 }
1260
Jim Grosbach460a9052011-10-07 23:56:00 +00001261 bool isVectorIndex8() const {
1262 if (Kind != k_VectorIndex) return false;
1263 return VectorIndex.Val < 8;
1264 }
1265 bool isVectorIndex16() const {
1266 if (Kind != k_VectorIndex) return false;
1267 return VectorIndex.Val < 4;
1268 }
1269 bool isVectorIndex32() const {
1270 if (Kind != k_VectorIndex) return false;
1271 return VectorIndex.Val < 2;
1272 }
1273
Jim Grosbach0e387b22011-10-17 22:26:03 +00001274 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001275 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001276 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1277 // Must be a constant.
1278 if (!CE) return false;
1279 int64_t Value = CE->getValue();
1280 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1281 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001282 return Value >= 0 && Value < 256;
1283 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001284
Jim Grosbachea461102011-10-17 23:09:09 +00001285 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001286 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001287 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1288 // Must be a constant.
1289 if (!CE) return false;
1290 int64_t Value = CE->getValue();
1291 // i16 value in the range [0,255] or [0x0100, 0xff00]
1292 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1293 }
1294
Jim Grosbach6248a542011-10-18 00:22:00 +00001295 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001296 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001297 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1298 // Must be a constant.
1299 if (!CE) return false;
1300 int64_t Value = CE->getValue();
1301 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1302 return (Value >= 0 && Value < 256) ||
1303 (Value >= 0x0100 && Value <= 0xff00) ||
1304 (Value >= 0x010000 && Value <= 0xff0000) ||
1305 (Value >= 0x01000000 && Value <= 0xff000000);
1306 }
1307
1308 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001309 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1311 // Must be a constant.
1312 if (!CE) return false;
1313 int64_t Value = CE->getValue();
1314 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1315 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1316 return (Value >= 0 && Value < 256) ||
1317 (Value >= 0x0100 && Value <= 0xff00) ||
1318 (Value >= 0x010000 && Value <= 0xff0000) ||
1319 (Value >= 0x01000000 && Value <= 0xff000000) ||
1320 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1321 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1322 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001323 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001324 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001325 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1326 // Must be a constant.
1327 if (!CE) return false;
1328 int64_t Value = ~CE->getValue();
1329 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1330 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1331 return (Value >= 0 && Value < 256) ||
1332 (Value >= 0x0100 && Value <= 0xff00) ||
1333 (Value >= 0x010000 && Value <= 0xff0000) ||
1334 (Value >= 0x01000000 && Value <= 0xff000000) ||
1335 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1336 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1337 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001338
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001339 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001340 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001341 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1342 // Must be a constant.
1343 if (!CE) return false;
1344 uint64_t Value = CE->getValue();
1345 // i64 value with each byte being either 0 or 0xff.
1346 for (unsigned i = 0; i < 8; ++i)
1347 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1348 return true;
1349 }
1350
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001351 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001352 // Add as immediates when possible. Null MCExpr = 0.
1353 if (Expr == 0)
1354 Inst.addOperand(MCOperand::CreateImm(0));
1355 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001356 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1357 else
1358 Inst.addOperand(MCOperand::CreateExpr(Expr));
1359 }
1360
Daniel Dunbar8462b302010-08-11 06:36:53 +00001361 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001362 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001363 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001364 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1365 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001366 }
1367
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001368 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1371 }
1372
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001373 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
1375 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1376 }
1377
1378 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
1380 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1381 }
1382
Jim Grosbach89df9962011-08-26 21:43:41 +00001383 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1386 }
1387
1388 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1391 }
1392
Jim Grosbachd67641b2010-12-06 18:21:12 +00001393 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 Inst.addOperand(MCOperand::CreateReg(getReg()));
1396 }
1397
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001398 void addRegOperands(MCInst &Inst, unsigned N) const {
1399 assert(N == 1 && "Invalid number of operands!");
1400 Inst.addOperand(MCOperand::CreateReg(getReg()));
1401 }
1402
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001403 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001404 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001405 assert(isRegShiftedReg() &&
1406 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001407 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1408 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001409 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001410 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001411 }
1412
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001413 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001414 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001415 assert(isRegShiftedImm() &&
1416 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001417 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001418 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001419 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001420 }
1421
Jim Grosbach580f4a92011-07-25 22:20:28 +00001422 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001423 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001424 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1425 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001426 }
1427
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001428 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001429 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001430 const SmallVectorImpl<unsigned> &RegList = getRegList();
1431 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001432 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1433 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001434 }
1435
Bill Wendling0f630752010-11-17 04:32:08 +00001436 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1437 addRegListOperands(Inst, N);
1438 }
1439
1440 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1441 addRegListOperands(Inst, N);
1442 }
1443
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001444 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1447 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1448 }
1449
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001450 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
1452 // Munge the lsb/width into a bitfield mask.
1453 unsigned lsb = Bitfield.LSB;
1454 unsigned width = Bitfield.Width;
1455 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1456 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1457 (32 - (lsb + width)));
1458 Inst.addOperand(MCOperand::CreateImm(Mask));
1459 }
1460
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001461 void addImmOperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
1463 addExpr(Inst, getImm());
1464 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001465
Jim Grosbach4050bc42011-12-22 22:19:05 +00001466 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
1468 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1469 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1470 }
1471
1472 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1475 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1476 }
1477
Jim Grosbach9d390362011-10-03 23:38:36 +00001478 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001480 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1481 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1482 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001483 }
1484
Jim Grosbacha77295d2011-09-08 22:07:06 +00001485 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1486 assert(N == 1 && "Invalid number of operands!");
1487 // FIXME: We really want to scale the value here, but the LDRD/STRD
1488 // instruction don't encode operands that way yet.
1489 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1490 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1491 }
1492
Jim Grosbach72f39f82011-08-24 21:22:15 +00001493 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1494 assert(N == 1 && "Invalid number of operands!");
1495 // The immediate is scaled by four in the encoding and is stored
1496 // in the MCInst as such. Lop off the low two bits here.
1497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1498 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1499 }
1500
1501 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
1503 // The immediate is scaled by four in the encoding and is stored
1504 // in the MCInst as such. Lop off the low two bits here.
1505 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1506 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1507 }
1508
Jim Grosbachf4943352011-07-25 23:09:14 +00001509 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1510 assert(N == 1 && "Invalid number of operands!");
1511 // The constant encodes as the immediate-1, and we store in the instruction
1512 // the bits as encoded, so subtract off one here.
1513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1514 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1515 }
1516
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001517 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1518 assert(N == 1 && "Invalid number of operands!");
1519 // The constant encodes as the immediate-1, and we store in the instruction
1520 // the bits as encoded, so subtract off one here.
1521 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1522 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1523 }
1524
Jim Grosbach70939ee2011-08-17 21:51:27 +00001525 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 // The constant encodes as the immediate, except for 32, which encodes as
1528 // zero.
1529 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1530 unsigned Imm = CE->getValue();
1531 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1532 }
1533
Jim Grosbachf6c05252011-07-21 17:23:04 +00001534 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 1 && "Invalid number of operands!");
1536 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1537 // the instruction as well.
1538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1539 int Val = CE->getValue();
1540 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1541 }
1542
Jim Grosbach89a63372011-10-28 22:36:30 +00001543 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545 // The operand is actually a t2_so_imm, but we have its bitwise
1546 // negation in the assembly source, so twiddle it here.
1547 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1548 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1549 }
1550
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001551 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553 // The operand is actually a t2_so_imm, but we have its
1554 // negation in the assembly source, so twiddle it here.
1555 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1556 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1557 }
1558
Jim Grosbache70ec842011-10-28 22:50:54 +00001559 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1560 assert(N == 1 && "Invalid number of operands!");
1561 // The operand is actually a so_imm, but we have its bitwise
1562 // negation in the assembly source, so twiddle it here.
1563 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1564 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1565 }
1566
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001567 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1568 assert(N == 1 && "Invalid number of operands!");
1569 // The operand is actually a so_imm, but we have its
1570 // negation in the assembly source, so twiddle it here.
1571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1572 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1573 }
1574
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001575 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1578 }
1579
Jim Grosbach7ce05792011-08-03 23:50:40 +00001580 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001582 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001583 }
1584
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001585 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1586 assert(N == 1 && "Invalid number of operands!");
1587 int32_t Imm = Memory.OffsetImm->getValue();
1588 // FIXME: Handle #-0
1589 if (Imm == INT32_MIN) Imm = 0;
1590 Inst.addOperand(MCOperand::CreateImm(Imm));
1591 }
1592
Jim Grosbach57dcb852011-10-11 17:29:55 +00001593 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 2 && "Invalid number of operands!");
1595 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1596 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1597 }
1598
Jim Grosbach7ce05792011-08-03 23:50:40 +00001599 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1600 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001601 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1602 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001603 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1604 // Special case for #-0
1605 if (Val == INT32_MIN) Val = 0;
1606 if (Val < 0) Val = -Val;
1607 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1608 } else {
1609 // For register offset, we encode the shift type and negation flag
1610 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001611 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1612 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001613 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001614 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1615 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001616 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001617 }
1618
Jim Grosbach039c2e12011-08-04 23:01:30 +00001619 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1620 assert(N == 2 && "Invalid number of operands!");
1621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1622 assert(CE && "non-constant AM2OffsetImm operand!");
1623 int32_t Val = CE->getValue();
1624 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1625 // Special case for #-0
1626 if (Val == INT32_MIN) Val = 0;
1627 if (Val < 0) Val = -Val;
1628 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1629 Inst.addOperand(MCOperand::CreateReg(0));
1630 Inst.addOperand(MCOperand::CreateImm(Val));
1631 }
1632
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001633 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1634 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001635 // If we have an immediate that's not a constant, treat it as a label
1636 // reference needing a fixup. If it is a constant, it's something else
1637 // and we reject it.
1638 if (isImm()) {
1639 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1640 Inst.addOperand(MCOperand::CreateReg(0));
1641 Inst.addOperand(MCOperand::CreateImm(0));
1642 return;
1643 }
1644
Jim Grosbache53c87b2011-10-11 15:59:20 +00001645 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1646 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001647 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1648 // Special case for #-0
1649 if (Val == INT32_MIN) Val = 0;
1650 if (Val < 0) Val = -Val;
1651 Val = ARM_AM::getAM3Opc(AddSub, Val);
1652 } else {
1653 // For register offset, we encode the shift type and negation flag
1654 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001655 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001656 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001657 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1658 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001659 Inst.addOperand(MCOperand::CreateImm(Val));
1660 }
1661
1662 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1663 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001664 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001665 int32_t Val =
1666 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1667 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1668 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001669 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001670 }
1671
1672 // Constant offset.
1673 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1674 int32_t Val = CE->getValue();
1675 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1676 // Special case for #-0
1677 if (Val == INT32_MIN) Val = 0;
1678 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001679 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001680 Inst.addOperand(MCOperand::CreateReg(0));
1681 Inst.addOperand(MCOperand::CreateImm(Val));
1682 }
1683
Jim Grosbach7ce05792011-08-03 23:50:40 +00001684 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1685 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001686 // If we have an immediate that's not a constant, treat it as a label
1687 // reference needing a fixup. If it is a constant, it's something else
1688 // and we reject it.
1689 if (isImm()) {
1690 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1691 Inst.addOperand(MCOperand::CreateImm(0));
1692 return;
1693 }
1694
Jim Grosbach7ce05792011-08-03 23:50:40 +00001695 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001696 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001697 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1698 // Special case for #-0
1699 if (Val == INT32_MIN) Val = 0;
1700 if (Val < 0) Val = -Val;
1701 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001702 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001703 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001704 }
1705
Jim Grosbacha77295d2011-09-08 22:07:06 +00001706 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1707 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001708 // If we have an immediate that's not a constant, treat it as a label
1709 // reference needing a fixup. If it is a constant, it's something else
1710 // and we reject it.
1711 if (isImm()) {
1712 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1713 Inst.addOperand(MCOperand::CreateImm(0));
1714 return;
1715 }
1716
Jim Grosbache53c87b2011-10-11 15:59:20 +00001717 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1718 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001719 Inst.addOperand(MCOperand::CreateImm(Val));
1720 }
1721
Jim Grosbachb6aed502011-09-09 18:37:27 +00001722 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1723 assert(N == 2 && "Invalid number of operands!");
1724 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001725 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1726 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001727 Inst.addOperand(MCOperand::CreateImm(Val));
1728 }
1729
Jim Grosbach7ce05792011-08-03 23:50:40 +00001730 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1731 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001732 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1733 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001734 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001735 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001736
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001737 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1738 addMemImm8OffsetOperands(Inst, N);
1739 }
1740
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001741 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001742 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001743 }
1744
1745 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1746 assert(N == 2 && "Invalid number of operands!");
1747 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001748 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001749 addExpr(Inst, getImm());
1750 Inst.addOperand(MCOperand::CreateImm(0));
1751 return;
1752 }
1753
1754 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001755 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1756 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001757 Inst.addOperand(MCOperand::CreateImm(Val));
1758 }
1759
Jim Grosbach7ce05792011-08-03 23:50:40 +00001760 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1761 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001762 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001763 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001764 addExpr(Inst, getImm());
1765 Inst.addOperand(MCOperand::CreateImm(0));
1766 return;
1767 }
1768
1769 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001770 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1771 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001772 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001773 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001774
Jim Grosbach7f739be2011-09-19 22:21:13 +00001775 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1776 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001777 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1778 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001779 }
1780
1781 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1782 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001783 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1784 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001785 }
1786
Jim Grosbach7ce05792011-08-03 23:50:40 +00001787 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1788 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001789 unsigned Val =
1790 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1791 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001792 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1793 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001794 Inst.addOperand(MCOperand::CreateImm(Val));
1795 }
1796
Jim Grosbachab899c12011-09-07 23:10:15 +00001797 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1798 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001799 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1800 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1801 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001802 }
1803
Jim Grosbach7ce05792011-08-03 23:50:40 +00001804 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1805 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001806 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1807 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001808 }
1809
Jim Grosbach60f91a32011-08-19 17:55:24 +00001810 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1811 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001812 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1813 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001814 Inst.addOperand(MCOperand::CreateImm(Val));
1815 }
1816
Jim Grosbach38466302011-08-19 18:55:51 +00001817 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1818 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001819 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1820 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001821 Inst.addOperand(MCOperand::CreateImm(Val));
1822 }
1823
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001824 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1825 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001826 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1827 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001828 Inst.addOperand(MCOperand::CreateImm(Val));
1829 }
1830
Jim Grosbachecd85892011-08-19 18:13:48 +00001831 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1832 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001833 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1834 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001835 Inst.addOperand(MCOperand::CreateImm(Val));
1836 }
1837
Jim Grosbach7ce05792011-08-03 23:50:40 +00001838 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1839 assert(N == 1 && "Invalid number of operands!");
1840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1841 assert(CE && "non-constant post-idx-imm8 operand!");
1842 int Imm = CE->getValue();
1843 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001844 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001845 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1846 Inst.addOperand(MCOperand::CreateImm(Imm));
1847 }
1848
Jim Grosbach2bd01182011-10-11 21:55:36 +00001849 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1850 assert(N == 1 && "Invalid number of operands!");
1851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1852 assert(CE && "non-constant post-idx-imm8s4 operand!");
1853 int Imm = CE->getValue();
1854 bool isAdd = Imm >= 0;
1855 if (Imm == INT32_MIN) Imm = 0;
1856 // Immediate is scaled by 4.
1857 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1858 Inst.addOperand(MCOperand::CreateImm(Imm));
1859 }
1860
Jim Grosbach7ce05792011-08-03 23:50:40 +00001861 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1862 assert(N == 2 && "Invalid number of operands!");
1863 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001864 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1865 }
1866
1867 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1868 assert(N == 2 && "Invalid number of operands!");
1869 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1870 // The sign, shift type, and shift amount are encoded in a single operand
1871 // using the AM2 encoding helpers.
1872 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1873 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1874 PostIdxReg.ShiftTy);
1875 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001876 }
1877
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001878 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1879 assert(N == 1 && "Invalid number of operands!");
1880 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1881 }
1882
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001883 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1884 assert(N == 1 && "Invalid number of operands!");
1885 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1886 }
1887
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001888 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001889 assert(N == 1 && "Invalid number of operands!");
1890 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1891 }
1892
Jim Grosbach7636bf62011-12-02 00:35:16 +00001893 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1894 assert(N == 2 && "Invalid number of operands!");
1895 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1896 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1897 }
1898
Jim Grosbach460a9052011-10-07 23:56:00 +00001899 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1900 assert(N == 1 && "Invalid number of operands!");
1901 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1902 }
1903
1904 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1905 assert(N == 1 && "Invalid number of operands!");
1906 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1907 }
1908
1909 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1910 assert(N == 1 && "Invalid number of operands!");
1911 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1912 }
1913
Jim Grosbach0e387b22011-10-17 22:26:03 +00001914 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1915 assert(N == 1 && "Invalid number of operands!");
1916 // The immediate encodes the type of constant as well as the value.
1917 // Mask in that this is an i8 splat.
1918 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1919 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1920 }
1921
Jim Grosbachea461102011-10-17 23:09:09 +00001922 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1923 assert(N == 1 && "Invalid number of operands!");
1924 // The immediate encodes the type of constant as well as the value.
1925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1926 unsigned Value = CE->getValue();
1927 if (Value >= 256)
1928 Value = (Value >> 8) | 0xa00;
1929 else
1930 Value |= 0x800;
1931 Inst.addOperand(MCOperand::CreateImm(Value));
1932 }
1933
Jim Grosbach6248a542011-10-18 00:22:00 +00001934 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1935 assert(N == 1 && "Invalid number of operands!");
1936 // The immediate encodes the type of constant as well as the value.
1937 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1938 unsigned Value = CE->getValue();
1939 if (Value >= 256 && Value <= 0xff00)
1940 Value = (Value >> 8) | 0x200;
1941 else if (Value > 0xffff && Value <= 0xff0000)
1942 Value = (Value >> 16) | 0x400;
1943 else if (Value > 0xffffff)
1944 Value = (Value >> 24) | 0x600;
1945 Inst.addOperand(MCOperand::CreateImm(Value));
1946 }
1947
1948 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1949 assert(N == 1 && "Invalid number of operands!");
1950 // The immediate encodes the type of constant as well as the value.
1951 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1952 unsigned Value = CE->getValue();
1953 if (Value >= 256 && Value <= 0xffff)
1954 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1955 else if (Value > 0xffff && Value <= 0xffffff)
1956 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1957 else if (Value > 0xffffff)
1958 Value = (Value >> 24) | 0x600;
1959 Inst.addOperand(MCOperand::CreateImm(Value));
1960 }
1961
Jim Grosbach9b087852011-12-19 23:51:07 +00001962 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1963 assert(N == 1 && "Invalid number of operands!");
1964 // The immediate encodes the type of constant as well as the value.
1965 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1966 unsigned Value = ~CE->getValue();
1967 if (Value >= 256 && Value <= 0xffff)
1968 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1969 else if (Value > 0xffff && Value <= 0xffffff)
1970 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1971 else if (Value > 0xffffff)
1972 Value = (Value >> 24) | 0x600;
1973 Inst.addOperand(MCOperand::CreateImm(Value));
1974 }
1975
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001976 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1977 assert(N == 1 && "Invalid number of operands!");
1978 // The immediate encodes the type of constant as well as the value.
1979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1980 uint64_t Value = CE->getValue();
1981 unsigned Imm = 0;
1982 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1983 Imm |= (Value & 1) << i;
1984 }
1985 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1986 }
1987
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001988 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001989
Jim Grosbach89df9962011-08-26 21:43:41 +00001990 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001991 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001992 Op->ITMask.Mask = Mask;
1993 Op->StartLoc = S;
1994 Op->EndLoc = S;
1995 return Op;
1996 }
1997
Chris Lattner3a697562010-10-28 17:20:03 +00001998 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001999 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002000 Op->CC.Val = CC;
2001 Op->StartLoc = S;
2002 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002003 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002004 }
2005
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002006 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002007 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002008 Op->Cop.Val = CopVal;
2009 Op->StartLoc = S;
2010 Op->EndLoc = S;
2011 return Op;
2012 }
2013
2014 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002015 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002016 Op->Cop.Val = CopVal;
2017 Op->StartLoc = S;
2018 Op->EndLoc = S;
2019 return Op;
2020 }
2021
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002022 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2023 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2024 Op->Cop.Val = Val;
2025 Op->StartLoc = S;
2026 Op->EndLoc = E;
2027 return Op;
2028 }
2029
Jim Grosbachd67641b2010-12-06 18:21:12 +00002030 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002031 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002032 Op->Reg.RegNum = RegNum;
2033 Op->StartLoc = S;
2034 Op->EndLoc = S;
2035 return Op;
2036 }
2037
Chris Lattner3a697562010-10-28 17:20:03 +00002038 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002039 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002040 Op->Tok.Data = Str.data();
2041 Op->Tok.Length = Str.size();
2042 Op->StartLoc = S;
2043 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002044 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002045 }
2046
Bill Wendling50d0f582010-11-18 23:43:05 +00002047 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002048 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002049 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002050 Op->StartLoc = S;
2051 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002052 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002053 }
2054
Jim Grosbache8606dc2011-07-13 17:50:29 +00002055 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2056 unsigned SrcReg,
2057 unsigned ShiftReg,
2058 unsigned ShiftImm,
2059 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002060 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002061 Op->RegShiftedReg.ShiftTy = ShTy;
2062 Op->RegShiftedReg.SrcReg = SrcReg;
2063 Op->RegShiftedReg.ShiftReg = ShiftReg;
2064 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002065 Op->StartLoc = S;
2066 Op->EndLoc = E;
2067 return Op;
2068 }
2069
Owen Anderson92a20222011-07-21 18:54:16 +00002070 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2071 unsigned SrcReg,
2072 unsigned ShiftImm,
2073 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002074 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002075 Op->RegShiftedImm.ShiftTy = ShTy;
2076 Op->RegShiftedImm.SrcReg = SrcReg;
2077 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002078 Op->StartLoc = S;
2079 Op->EndLoc = E;
2080 return Op;
2081 }
2082
Jim Grosbach580f4a92011-07-25 22:20:28 +00002083 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002084 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002085 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002086 Op->ShifterImm.isASR = isASR;
2087 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002088 Op->StartLoc = S;
2089 Op->EndLoc = E;
2090 return Op;
2091 }
2092
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002093 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002094 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002095 Op->RotImm.Imm = Imm;
2096 Op->StartLoc = S;
2097 Op->EndLoc = E;
2098 return Op;
2099 }
2100
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002101 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2102 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002103 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002104 Op->Bitfield.LSB = LSB;
2105 Op->Bitfield.Width = Width;
2106 Op->StartLoc = S;
2107 Op->EndLoc = E;
2108 return Op;
2109 }
2110
Bill Wendling7729e062010-11-09 22:44:22 +00002111 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002112 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002113 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002114 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002115
Jim Grosbachd300b942011-09-13 22:56:44 +00002116 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002117 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002118 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002119 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002120 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002121
2122 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002123 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002124 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002125 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002126 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002127 Op->StartLoc = StartLoc;
2128 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002129 return Op;
2130 }
2131
Jim Grosbach862019c2011-10-18 23:02:30 +00002132 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002133 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002134 ARMOperand *Op = new ARMOperand(k_VectorList);
2135 Op->VectorList.RegNum = RegNum;
2136 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002137 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002138 Op->StartLoc = S;
2139 Op->EndLoc = E;
2140 return Op;
2141 }
2142
Jim Grosbach98b05a52011-11-30 01:09:44 +00002143 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002144 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002145 SMLoc S, SMLoc E) {
2146 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2147 Op->VectorList.RegNum = RegNum;
2148 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002149 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002150 Op->StartLoc = S;
2151 Op->EndLoc = E;
2152 return Op;
2153 }
2154
Jim Grosbach7636bf62011-12-02 00:35:16 +00002155 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002156 unsigned Index,
2157 bool isDoubleSpaced,
2158 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002159 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2160 Op->VectorList.RegNum = RegNum;
2161 Op->VectorList.Count = Count;
2162 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002163 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002164 Op->StartLoc = S;
2165 Op->EndLoc = E;
2166 return Op;
2167 }
2168
Jim Grosbach460a9052011-10-07 23:56:00 +00002169 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2170 MCContext &Ctx) {
2171 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2172 Op->VectorIndex.Val = Idx;
2173 Op->StartLoc = S;
2174 Op->EndLoc = E;
2175 return Op;
2176 }
2177
Chris Lattner3a697562010-10-28 17:20:03 +00002178 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002179 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002180 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002181 Op->StartLoc = S;
2182 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002183 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002184 }
2185
Jim Grosbach7ce05792011-08-03 23:50:40 +00002186 static ARMOperand *CreateMem(unsigned BaseRegNum,
2187 const MCConstantExpr *OffsetImm,
2188 unsigned OffsetRegNum,
2189 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002190 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002191 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002192 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002193 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002194 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002195 Op->Memory.BaseRegNum = BaseRegNum;
2196 Op->Memory.OffsetImm = OffsetImm;
2197 Op->Memory.OffsetRegNum = OffsetRegNum;
2198 Op->Memory.ShiftType = ShiftType;
2199 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002200 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002201 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002202 Op->StartLoc = S;
2203 Op->EndLoc = E;
2204 return Op;
2205 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002206
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002207 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2208 ARM_AM::ShiftOpc ShiftTy,
2209 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002210 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002211 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002212 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002213 Op->PostIdxReg.isAdd = isAdd;
2214 Op->PostIdxReg.ShiftTy = ShiftTy;
2215 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002216 Op->StartLoc = S;
2217 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002218 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002219 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002220
2221 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002222 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002223 Op->MBOpt.Val = Opt;
2224 Op->StartLoc = S;
2225 Op->EndLoc = S;
2226 return Op;
2227 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002228
2229 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002230 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002231 Op->IFlags.Val = IFlags;
2232 Op->StartLoc = S;
2233 Op->EndLoc = S;
2234 return Op;
2235 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002236
2237 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002238 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002239 Op->MMask.Val = MMask;
2240 Op->StartLoc = S;
2241 Op->EndLoc = S;
2242 return Op;
2243 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002244};
2245
2246} // end anonymous namespace.
2247
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002248void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002249 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002250 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002251 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002252 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002253 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002254 OS << "<ccout " << getReg() << ">";
2255 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002256 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002257 static const char *MaskStr[] = {
2258 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2259 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2260 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002261 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2262 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2263 break;
2264 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002265 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002266 OS << "<coprocessor number: " << getCoproc() << ">";
2267 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002268 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002269 OS << "<coprocessor register: " << getCoproc() << ">";
2270 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002271 case k_CoprocOption:
2272 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2273 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002274 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002275 OS << "<mask: " << getMSRMask() << ">";
2276 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002277 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002278 getImm()->print(OS);
2279 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002280 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002281 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2282 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002283 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002284 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002285 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002286 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002287 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002288 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002289 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2290 << PostIdxReg.RegNum;
2291 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2292 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2293 << PostIdxReg.ShiftImm;
2294 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002295 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002296 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002297 OS << "<ARM_PROC::";
2298 unsigned IFlags = getProcIFlags();
2299 for (int i=2; i >= 0; --i)
2300 if (IFlags & (1 << i))
2301 OS << ARM_PROC::IFlagsToString(1 << i);
2302 OS << ">";
2303 break;
2304 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002305 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002306 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002307 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002308 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002309 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2310 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002311 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002312 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002313 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002314 << RegShiftedReg.SrcReg << " "
2315 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2316 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002317 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002318 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002319 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002320 << RegShiftedImm.SrcReg << " "
2321 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2322 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002323 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002324 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002325 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2326 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002327 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002328 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2329 << ", width: " << Bitfield.Width << ">";
2330 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002331 case k_RegisterList:
2332 case k_DPRRegisterList:
2333 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002334 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002335
Bill Wendling5fa22a12010-11-09 23:28:44 +00002336 const SmallVectorImpl<unsigned> &RegList = getRegList();
2337 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002338 I = RegList.begin(), E = RegList.end(); I != E; ) {
2339 OS << *I;
2340 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002341 }
2342
2343 OS << ">";
2344 break;
2345 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002346 case k_VectorList:
2347 OS << "<vector_list " << VectorList.Count << " * "
2348 << VectorList.RegNum << ">";
2349 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002350 case k_VectorListAllLanes:
2351 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2352 << VectorList.RegNum << ">";
2353 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002354 case k_VectorListIndexed:
2355 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2356 << VectorList.Count << " * " << VectorList.RegNum << ">";
2357 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002358 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002359 OS << "'" << getToken() << "'";
2360 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002361 case k_VectorIndex:
2362 OS << "<vectorindex " << getVectorIndex() << ">";
2363 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002364 }
2365}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002366
2367/// @name Auto-generated Match Functions
2368/// {
2369
2370static unsigned MatchRegisterName(StringRef Name);
2371
2372/// }
2373
Bob Wilson69df7232011-02-03 21:46:10 +00002374bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2375 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002376 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002377 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002378 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002379
2380 return (RegNo == (unsigned)-1);
2381}
2382
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002383/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002384/// and if it is a register name the token is eaten and the register number is
2385/// returned. Otherwise return -1.
2386///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002387int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002388 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002389 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002390
Benjamin Kramer59085362011-11-06 20:37:06 +00002391 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002392 unsigned RegNum = MatchRegisterName(lowerCase);
2393 if (!RegNum) {
2394 RegNum = StringSwitch<unsigned>(lowerCase)
2395 .Case("r13", ARM::SP)
2396 .Case("r14", ARM::LR)
2397 .Case("r15", ARM::PC)
2398 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002399 // Additional register name aliases for 'gas' compatibility.
2400 .Case("a1", ARM::R0)
2401 .Case("a2", ARM::R1)
2402 .Case("a3", ARM::R2)
2403 .Case("a4", ARM::R3)
2404 .Case("v1", ARM::R4)
2405 .Case("v2", ARM::R5)
2406 .Case("v3", ARM::R6)
2407 .Case("v4", ARM::R7)
2408 .Case("v5", ARM::R8)
2409 .Case("v6", ARM::R9)
2410 .Case("v7", ARM::R10)
2411 .Case("v8", ARM::R11)
2412 .Case("sb", ARM::R9)
2413 .Case("sl", ARM::R10)
2414 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002415 .Default(0);
2416 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002417 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002418 // Check for aliases registered via .req. Canonicalize to lower case.
2419 // That's more consistent since register names are case insensitive, and
2420 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2421 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002422 // If no match, return failure.
2423 if (Entry == RegisterReqs.end())
2424 return -1;
2425 Parser.Lex(); // Eat identifier token.
2426 return Entry->getValue();
2427 }
Bob Wilson69df7232011-02-03 21:46:10 +00002428
Chris Lattnere5658fa2010-10-30 04:09:10 +00002429 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002430
Chris Lattnere5658fa2010-10-30 04:09:10 +00002431 return RegNum;
2432}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002433
Jim Grosbach19906722011-07-13 18:49:30 +00002434// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2435// If a recoverable error occurs, return 1. If an irrecoverable error
2436// occurs, return -1. An irrecoverable error is one where tokens have been
2437// consumed in the process of trying to parse the shifter (i.e., when it is
2438// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002439int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002440 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2441 SMLoc S = Parser.getTok().getLoc();
2442 const AsmToken &Tok = Parser.getTok();
2443 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2444
Benjamin Kramer59085362011-11-06 20:37:06 +00002445 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002446 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002447 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002448 .Case("lsl", ARM_AM::lsl)
2449 .Case("lsr", ARM_AM::lsr)
2450 .Case("asr", ARM_AM::asr)
2451 .Case("ror", ARM_AM::ror)
2452 .Case("rrx", ARM_AM::rrx)
2453 .Default(ARM_AM::no_shift);
2454
2455 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002456 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002457
Jim Grosbache8606dc2011-07-13 17:50:29 +00002458 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002459
Jim Grosbache8606dc2011-07-13 17:50:29 +00002460 // The source register for the shift has already been added to the
2461 // operand list, so we need to pop it off and combine it into the shifted
2462 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002463 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002464 if (!PrevOp->isReg())
2465 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2466 int SrcReg = PrevOp->getReg();
2467 int64_t Imm = 0;
2468 int ShiftReg = 0;
2469 if (ShiftTy == ARM_AM::rrx) {
2470 // RRX Doesn't have an explicit shift amount. The encoder expects
2471 // the shift register to be the same as the source register. Seems odd,
2472 // but OK.
2473 ShiftReg = SrcReg;
2474 } else {
2475 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002476 if (Parser.getTok().is(AsmToken::Hash) ||
2477 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002478 Parser.Lex(); // Eat hash.
2479 SMLoc ImmLoc = Parser.getTok().getLoc();
2480 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002481 if (getParser().ParseExpression(ShiftExpr)) {
2482 Error(ImmLoc, "invalid immediate shift value");
2483 return -1;
2484 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002485 // The expression must be evaluatable as an immediate.
2486 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002487 if (!CE) {
2488 Error(ImmLoc, "invalid immediate shift value");
2489 return -1;
2490 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002491 // Range check the immediate.
2492 // lsl, ror: 0 <= imm <= 31
2493 // lsr, asr: 0 <= imm <= 32
2494 Imm = CE->getValue();
2495 if (Imm < 0 ||
2496 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2497 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002498 Error(ImmLoc, "immediate shift value out of range");
2499 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002500 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002501 // shift by zero is a nop. Always send it through as lsl.
2502 // ('as' compatibility)
2503 if (Imm == 0)
2504 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002505 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002506 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002507 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002508 if (ShiftReg == -1) {
2509 Error (L, "expected immediate or register in shift operand");
2510 return -1;
2511 }
2512 } else {
2513 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002514 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002515 return -1;
2516 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002517 }
2518
Owen Anderson92a20222011-07-21 18:54:16 +00002519 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2520 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002521 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002522 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002523 else
2524 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2525 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002526
Jim Grosbach19906722011-07-13 18:49:30 +00002527 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002528}
2529
2530
Bill Wendling50d0f582010-11-18 23:43:05 +00002531/// Try to parse a register name. The token must be an Identifier when called.
2532/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2533/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002534///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002535/// TODO this is likely to change to allow different register types and or to
2536/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002537bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002538tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002539 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002540 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002541 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002542 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002543
Bill Wendling50d0f582010-11-18 23:43:05 +00002544 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002545
Chris Lattnere5658fa2010-10-30 04:09:10 +00002546 const AsmToken &ExclaimTok = Parser.getTok();
2547 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002548 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2549 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002550 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002551 return false;
2552 }
2553
2554 // Also check for an index operand. This is only legal for vector registers,
2555 // but that'll get caught OK in operand matching, so we don't need to
2556 // explicitly filter everything else out here.
2557 if (Parser.getTok().is(AsmToken::LBrac)) {
2558 SMLoc SIdx = Parser.getTok().getLoc();
2559 Parser.Lex(); // Eat left bracket token.
2560
2561 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002562 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002563 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002564 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002565 if (!MCE)
2566 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002567
2568 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002569 if (Parser.getTok().isNot(AsmToken::RBrac))
2570 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002571
2572 Parser.Lex(); // Eat right bracket token.
2573
2574 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2575 SIdx, E,
2576 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002577 }
2578
Bill Wendling50d0f582010-11-18 23:43:05 +00002579 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002580}
2581
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002582/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2583/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2584/// "c5", ...
2585static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002586 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2587 // but efficient.
2588 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002589 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002590 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002591 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002592 return -1;
2593 switch (Name[1]) {
2594 default: return -1;
2595 case '0': return 0;
2596 case '1': return 1;
2597 case '2': return 2;
2598 case '3': return 3;
2599 case '4': return 4;
2600 case '5': return 5;
2601 case '6': return 6;
2602 case '7': return 7;
2603 case '8': return 8;
2604 case '9': return 9;
2605 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002606 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002607 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002608 return -1;
2609 switch (Name[2]) {
2610 default: return -1;
2611 case '0': return 10;
2612 case '1': return 11;
2613 case '2': return 12;
2614 case '3': return 13;
2615 case '4': return 14;
2616 case '5': return 15;
2617 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002618 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002619}
2620
Jim Grosbach89df9962011-08-26 21:43:41 +00002621/// parseITCondCode - Try to parse a condition code for an IT instruction.
2622ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2623parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2624 SMLoc S = Parser.getTok().getLoc();
2625 const AsmToken &Tok = Parser.getTok();
2626 if (!Tok.is(AsmToken::Identifier))
2627 return MatchOperand_NoMatch;
2628 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2629 .Case("eq", ARMCC::EQ)
2630 .Case("ne", ARMCC::NE)
2631 .Case("hs", ARMCC::HS)
2632 .Case("cs", ARMCC::HS)
2633 .Case("lo", ARMCC::LO)
2634 .Case("cc", ARMCC::LO)
2635 .Case("mi", ARMCC::MI)
2636 .Case("pl", ARMCC::PL)
2637 .Case("vs", ARMCC::VS)
2638 .Case("vc", ARMCC::VC)
2639 .Case("hi", ARMCC::HI)
2640 .Case("ls", ARMCC::LS)
2641 .Case("ge", ARMCC::GE)
2642 .Case("lt", ARMCC::LT)
2643 .Case("gt", ARMCC::GT)
2644 .Case("le", ARMCC::LE)
2645 .Case("al", ARMCC::AL)
2646 .Default(~0U);
2647 if (CC == ~0U)
2648 return MatchOperand_NoMatch;
2649 Parser.Lex(); // Eat the token.
2650
2651 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2652
2653 return MatchOperand_Success;
2654}
2655
Jim Grosbach43904292011-07-25 20:14:50 +00002656/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002657/// token must be an Identifier when called, and if it is a coprocessor
2658/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002659ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002660parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002661 SMLoc S = Parser.getTok().getLoc();
2662 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002663 if (Tok.isNot(AsmToken::Identifier))
2664 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002665
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002666 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002667 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002668 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002669
2670 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002671 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002672 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002673}
2674
Jim Grosbach43904292011-07-25 20:14:50 +00002675/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002676/// token must be an Identifier when called, and if it is a coprocessor
2677/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002678ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002679parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002680 SMLoc S = Parser.getTok().getLoc();
2681 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002682 if (Tok.isNot(AsmToken::Identifier))
2683 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002684
2685 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2686 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002687 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002688
2689 Parser.Lex(); // Eat identifier token.
2690 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002691 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002692}
2693
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002694/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2695/// coproc_option : '{' imm0_255 '}'
2696ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2697parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2698 SMLoc S = Parser.getTok().getLoc();
2699
2700 // If this isn't a '{', this isn't a coprocessor immediate operand.
2701 if (Parser.getTok().isNot(AsmToken::LCurly))
2702 return MatchOperand_NoMatch;
2703 Parser.Lex(); // Eat the '{'
2704
2705 const MCExpr *Expr;
2706 SMLoc Loc = Parser.getTok().getLoc();
2707 if (getParser().ParseExpression(Expr)) {
2708 Error(Loc, "illegal expression");
2709 return MatchOperand_ParseFail;
2710 }
2711 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2712 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2713 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2714 return MatchOperand_ParseFail;
2715 }
2716 int Val = CE->getValue();
2717
2718 // Check for and consume the closing '}'
2719 if (Parser.getTok().isNot(AsmToken::RCurly))
2720 return MatchOperand_ParseFail;
2721 SMLoc E = Parser.getTok().getLoc();
2722 Parser.Lex(); // Eat the '}'
2723
2724 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2725 return MatchOperand_Success;
2726}
2727
Jim Grosbachd0588e22011-09-14 18:08:35 +00002728// For register list parsing, we need to map from raw GPR register numbering
2729// to the enumeration values. The enumeration values aren't sorted by
2730// register number due to our using "sp", "lr" and "pc" as canonical names.
2731static unsigned getNextRegister(unsigned Reg) {
2732 // If this is a GPR, we need to do it manually, otherwise we can rely
2733 // on the sort ordering of the enumeration since the other reg-classes
2734 // are sane.
2735 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2736 return Reg + 1;
2737 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002738 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002739 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2740 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2741 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2742 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2743 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2744 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2745 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2746 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2747 }
2748}
2749
Jim Grosbachce485e72011-11-11 21:27:40 +00002750// Return the low-subreg of a given Q register.
2751static unsigned getDRegFromQReg(unsigned QReg) {
2752 switch (QReg) {
2753 default: llvm_unreachable("expected a Q register!");
2754 case ARM::Q0: return ARM::D0;
2755 case ARM::Q1: return ARM::D2;
2756 case ARM::Q2: return ARM::D4;
2757 case ARM::Q3: return ARM::D6;
2758 case ARM::Q4: return ARM::D8;
2759 case ARM::Q5: return ARM::D10;
2760 case ARM::Q6: return ARM::D12;
2761 case ARM::Q7: return ARM::D14;
2762 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002763 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002764 case ARM::Q10: return ARM::D20;
2765 case ARM::Q11: return ARM::D22;
2766 case ARM::Q12: return ARM::D24;
2767 case ARM::Q13: return ARM::D26;
2768 case ARM::Q14: return ARM::D28;
2769 case ARM::Q15: return ARM::D30;
2770 }
2771}
2772
Jim Grosbachd0588e22011-09-14 18:08:35 +00002773/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002774bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002775parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002776 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002777 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002778 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002779 Parser.Lex(); // Eat '{' token.
2780 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002781
Jim Grosbachd0588e22011-09-14 18:08:35 +00002782 // Check the first register in the list to see what register class
2783 // this is a list of.
2784 int Reg = tryParseRegister();
2785 if (Reg == -1)
2786 return Error(RegLoc, "register expected");
2787
Jim Grosbachce485e72011-11-11 21:27:40 +00002788 // The reglist instructions have at most 16 registers, so reserve
2789 // space for that many.
2790 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2791
2792 // Allow Q regs and just interpret them as the two D sub-registers.
2793 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2794 Reg = getDRegFromQReg(Reg);
2795 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2796 ++Reg;
2797 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002798 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002799 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2800 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2801 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2802 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2803 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2804 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2805 else
2806 return Error(RegLoc, "invalid register in register list");
2807
Jim Grosbachce485e72011-11-11 21:27:40 +00002808 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002809 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002810
Jim Grosbachd0588e22011-09-14 18:08:35 +00002811 // This starts immediately after the first register token in the list,
2812 // so we can see either a comma or a minus (range separator) as a legal
2813 // next token.
2814 while (Parser.getTok().is(AsmToken::Comma) ||
2815 Parser.getTok().is(AsmToken::Minus)) {
2816 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002817 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002818 SMLoc EndLoc = Parser.getTok().getLoc();
2819 int EndReg = tryParseRegister();
2820 if (EndReg == -1)
2821 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002822 // Allow Q regs and just interpret them as the two D sub-registers.
2823 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2824 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002825 // If the register is the same as the start reg, there's nothing
2826 // more to do.
2827 if (Reg == EndReg)
2828 continue;
2829 // The register must be in the same register class as the first.
2830 if (!RC->contains(EndReg))
2831 return Error(EndLoc, "invalid register in register list");
2832 // Ranges must go from low to high.
2833 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2834 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002835
Jim Grosbachd0588e22011-09-14 18:08:35 +00002836 // Add all the registers in the range to the register list.
2837 while (Reg != EndReg) {
2838 Reg = getNextRegister(Reg);
2839 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2840 }
2841 continue;
2842 }
2843 Parser.Lex(); // Eat the comma.
2844 RegLoc = Parser.getTok().getLoc();
2845 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002846 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002847 Reg = tryParseRegister();
2848 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002849 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002850 // Allow Q regs and just interpret them as the two D sub-registers.
2851 bool isQReg = false;
2852 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2853 Reg = getDRegFromQReg(Reg);
2854 isQReg = true;
2855 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002856 // The register must be in the same register class as the first.
2857 if (!RC->contains(Reg))
2858 return Error(RegLoc, "invalid register in register list");
2859 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002860 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002861 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002862 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2863 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2864 ") in register list");
2865 continue;
2866 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002867 // VFP register lists must also be contiguous.
2868 // It's OK to use the enumeration values directly here rather, as the
2869 // VFP register classes have the enum sorted properly.
2870 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2871 Reg != OldReg + 1)
2872 return Error(RegLoc, "non-contiguous register range");
2873 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002874 if (isQReg)
2875 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002876 }
2877
Jim Grosbachd0588e22011-09-14 18:08:35 +00002878 SMLoc E = Parser.getTok().getLoc();
2879 if (Parser.getTok().isNot(AsmToken::RCurly))
2880 return Error(E, "'}' expected");
2881 Parser.Lex(); // Eat '}' token.
2882
Jim Grosbach27debd62011-12-13 21:48:29 +00002883 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002884 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002885
2886 // The ARM system instruction variants for LDM/STM have a '^' token here.
2887 if (Parser.getTok().is(AsmToken::Caret)) {
2888 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2889 Parser.Lex(); // Eat '^' token.
2890 }
2891
Bill Wendling50d0f582010-11-18 23:43:05 +00002892 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002893}
2894
Jim Grosbach98b05a52011-11-30 01:09:44 +00002895// Helper function to parse the lane index for vector lists.
2896ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002897parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2898 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002899 if (Parser.getTok().is(AsmToken::LBrac)) {
2900 Parser.Lex(); // Eat the '['.
2901 if (Parser.getTok().is(AsmToken::RBrac)) {
2902 // "Dn[]" is the 'all lanes' syntax.
2903 LaneKind = AllLanes;
2904 Parser.Lex(); // Eat the ']'.
2905 return MatchOperand_Success;
2906 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002907 const MCExpr *LaneIndex;
2908 SMLoc Loc = Parser.getTok().getLoc();
2909 if (getParser().ParseExpression(LaneIndex)) {
2910 Error(Loc, "illegal expression");
2911 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002912 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002913 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2914 if (!CE) {
2915 Error(Loc, "lane index must be empty or an integer");
2916 return MatchOperand_ParseFail;
2917 }
2918 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2919 Error(Parser.getTok().getLoc(), "']' expected");
2920 return MatchOperand_ParseFail;
2921 }
2922 Parser.Lex(); // Eat the ']'.
2923 int64_t Val = CE->getValue();
2924
2925 // FIXME: Make this range check context sensitive for .8, .16, .32.
2926 if (Val < 0 || Val > 7) {
2927 Error(Parser.getTok().getLoc(), "lane index out of range");
2928 return MatchOperand_ParseFail;
2929 }
2930 Index = Val;
2931 LaneKind = IndexedLane;
2932 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002933 }
2934 LaneKind = NoLanes;
2935 return MatchOperand_Success;
2936}
2937
Jim Grosbach862019c2011-10-18 23:02:30 +00002938// parse a vector register list
2939ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2940parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002941 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002942 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002943 SMLoc S = Parser.getTok().getLoc();
2944 // As an extension (to match gas), support a plain D register or Q register
2945 // (without encosing curly braces) as a single or double entry list,
2946 // respectively.
2947 if (Parser.getTok().is(AsmToken::Identifier)) {
2948 int Reg = tryParseRegister();
2949 if (Reg == -1)
2950 return MatchOperand_NoMatch;
2951 SMLoc E = Parser.getTok().getLoc();
2952 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002953 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002954 if (Res != MatchOperand_Success)
2955 return Res;
2956 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002957 case NoLanes:
2958 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002959 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002960 break;
2961 case AllLanes:
2962 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002963 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2964 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002965 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002966 case IndexedLane:
2967 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002968 LaneIndex,
2969 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002970 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002971 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002972 return MatchOperand_Success;
2973 }
2974 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2975 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002976 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002977 if (Res != MatchOperand_Success)
2978 return Res;
2979 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002980 case NoLanes:
2981 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00002982 // VLD1 wants a DPair register.
2983 // FIXME: Make the rest of the two-reg instructions want the same
2984 // thing.
2985 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
2986 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
2987
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002988 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002989 break;
2990 case AllLanes:
2991 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002992 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2993 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002994 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002995 case IndexedLane:
2996 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002997 LaneIndex,
2998 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002999 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003000 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003001 return MatchOperand_Success;
3002 }
3003 Error(S, "vector register expected");
3004 return MatchOperand_ParseFail;
3005 }
3006
3007 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003008 return MatchOperand_NoMatch;
3009
Jim Grosbach862019c2011-10-18 23:02:30 +00003010 Parser.Lex(); // Eat '{' token.
3011 SMLoc RegLoc = Parser.getTok().getLoc();
3012
3013 int Reg = tryParseRegister();
3014 if (Reg == -1) {
3015 Error(RegLoc, "register expected");
3016 return MatchOperand_ParseFail;
3017 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003018 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003019 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003020 unsigned FirstReg = Reg;
3021 // The list is of D registers, but we also allow Q regs and just interpret
3022 // them as the two D sub-registers.
3023 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3024 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003025 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3026 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003027 ++Reg;
3028 ++Count;
3029 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003030 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003031 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003032
Jim Grosbache43862b2011-11-15 23:19:15 +00003033 while (Parser.getTok().is(AsmToken::Comma) ||
3034 Parser.getTok().is(AsmToken::Minus)) {
3035 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003036 if (!Spacing)
3037 Spacing = 1; // Register range implies a single spaced list.
3038 else if (Spacing == 2) {
3039 Error(Parser.getTok().getLoc(),
3040 "sequential registers in double spaced list");
3041 return MatchOperand_ParseFail;
3042 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003043 Parser.Lex(); // Eat the minus.
3044 SMLoc EndLoc = Parser.getTok().getLoc();
3045 int EndReg = tryParseRegister();
3046 if (EndReg == -1) {
3047 Error(EndLoc, "register expected");
3048 return MatchOperand_ParseFail;
3049 }
3050 // Allow Q regs and just interpret them as the two D sub-registers.
3051 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3052 EndReg = getDRegFromQReg(EndReg) + 1;
3053 // If the register is the same as the start reg, there's nothing
3054 // more to do.
3055 if (Reg == EndReg)
3056 continue;
3057 // The register must be in the same register class as the first.
3058 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3059 Error(EndLoc, "invalid register in register list");
3060 return MatchOperand_ParseFail;
3061 }
3062 // Ranges must go from low to high.
3063 if (Reg > EndReg) {
3064 Error(EndLoc, "bad range in register list");
3065 return MatchOperand_ParseFail;
3066 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003067 // Parse the lane specifier if present.
3068 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003069 unsigned NextLaneIndex;
3070 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003071 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003072 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003073 Error(EndLoc, "mismatched lane index in register list");
3074 return MatchOperand_ParseFail;
3075 }
3076 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003077
3078 // Add all the registers in the range to the register list.
3079 Count += EndReg - Reg;
3080 Reg = EndReg;
3081 continue;
3082 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003083 Parser.Lex(); // Eat the comma.
3084 RegLoc = Parser.getTok().getLoc();
3085 int OldReg = Reg;
3086 Reg = tryParseRegister();
3087 if (Reg == -1) {
3088 Error(RegLoc, "register expected");
3089 return MatchOperand_ParseFail;
3090 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003091 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003092 // It's OK to use the enumeration values directly here rather, as the
3093 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003094 //
3095 // The list is of D registers, but we also allow Q regs and just interpret
3096 // them as the two D sub-registers.
3097 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003098 if (!Spacing)
3099 Spacing = 1; // Register range implies a single spaced list.
3100 else if (Spacing == 2) {
3101 Error(RegLoc,
3102 "invalid register in double-spaced list (must be 'D' register')");
3103 return MatchOperand_ParseFail;
3104 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003105 Reg = getDRegFromQReg(Reg);
3106 if (Reg != OldReg + 1) {
3107 Error(RegLoc, "non-contiguous register range");
3108 return MatchOperand_ParseFail;
3109 }
3110 ++Reg;
3111 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003112 // Parse the lane specifier if present.
3113 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003114 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003115 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003116 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003117 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003118 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003119 Error(EndLoc, "mismatched lane index in register list");
3120 return MatchOperand_ParseFail;
3121 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003122 continue;
3123 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003124 // Normal D register.
3125 // Figure out the register spacing (single or double) of the list if
3126 // we don't know it already.
3127 if (!Spacing)
3128 Spacing = 1 + (Reg == OldReg + 2);
3129
3130 // Just check that it's contiguous and keep going.
3131 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003132 Error(RegLoc, "non-contiguous register range");
3133 return MatchOperand_ParseFail;
3134 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003135 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003136 // Parse the lane specifier if present.
3137 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003138 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003139 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003140 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003141 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003142 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003143 Error(EndLoc, "mismatched lane index in register list");
3144 return MatchOperand_ParseFail;
3145 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003146 }
3147
3148 SMLoc E = Parser.getTok().getLoc();
3149 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3150 Error(E, "'}' expected");
3151 return MatchOperand_ParseFail;
3152 }
3153 Parser.Lex(); // Eat '}' token.
3154
Jim Grosbach98b05a52011-11-30 01:09:44 +00003155 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003156 case NoLanes:
Jim Grosbach28f08c92012-03-05 19:33:30 +00003157 if (Count == 2 && Spacing == 1)
3158 // VLD1 wants a DPair register.
3159 // FIXME: Make the rest of the two-reg instructions want the same
3160 // thing.
3161 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0,
3162 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3163
3164
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003165 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3166 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003167 break;
3168 case AllLanes:
3169 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003170 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003171 S, E));
3172 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003173 case IndexedLane:
3174 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003175 LaneIndex,
3176 (Spacing == 2),
3177 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003178 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003179 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003180 return MatchOperand_Success;
3181}
3182
Jim Grosbach43904292011-07-25 20:14:50 +00003183/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003184ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003185parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003186 SMLoc S = Parser.getTok().getLoc();
3187 const AsmToken &Tok = Parser.getTok();
3188 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3189 StringRef OptStr = Tok.getString();
3190
3191 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3192 .Case("sy", ARM_MB::SY)
3193 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003194 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003195 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003196 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003197 .Case("ishst", ARM_MB::ISHST)
3198 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003199 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003200 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003201 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003202 .Case("osh", ARM_MB::OSH)
3203 .Case("oshst", ARM_MB::OSHST)
3204 .Default(~0U);
3205
3206 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003207 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003208
3209 Parser.Lex(); // Eat identifier token.
3210 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003211 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003212}
3213
Jim Grosbach43904292011-07-25 20:14:50 +00003214/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003215ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003216parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003217 SMLoc S = Parser.getTok().getLoc();
3218 const AsmToken &Tok = Parser.getTok();
3219 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3220 StringRef IFlagsStr = Tok.getString();
3221
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003222 // An iflags string of "none" is interpreted to mean that none of the AIF
3223 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003224 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003225 if (IFlagsStr != "none") {
3226 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3227 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3228 .Case("a", ARM_PROC::A)
3229 .Case("i", ARM_PROC::I)
3230 .Case("f", ARM_PROC::F)
3231 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003232
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003233 // If some specific iflag is already set, it means that some letter is
3234 // present more than once, this is not acceptable.
3235 if (Flag == ~0U || (IFlags & Flag))
3236 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003237
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003238 IFlags |= Flag;
3239 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003240 }
3241
3242 Parser.Lex(); // Eat identifier token.
3243 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3244 return MatchOperand_Success;
3245}
3246
Jim Grosbach43904292011-07-25 20:14:50 +00003247/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003248ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003249parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003250 SMLoc S = Parser.getTok().getLoc();
3251 const AsmToken &Tok = Parser.getTok();
3252 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3253 StringRef Mask = Tok.getString();
3254
James Molloyacad68d2011-09-28 14:21:38 +00003255 if (isMClass()) {
3256 // See ARMv6-M 10.1.1
3257 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3258 .Case("apsr", 0)
3259 .Case("iapsr", 1)
3260 .Case("eapsr", 2)
3261 .Case("xpsr", 3)
3262 .Case("ipsr", 5)
3263 .Case("epsr", 6)
3264 .Case("iepsr", 7)
3265 .Case("msp", 8)
3266 .Case("psp", 9)
3267 .Case("primask", 16)
3268 .Case("basepri", 17)
3269 .Case("basepri_max", 18)
3270 .Case("faultmask", 19)
3271 .Case("control", 20)
3272 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003273
James Molloyacad68d2011-09-28 14:21:38 +00003274 if (FlagsVal == ~0U)
3275 return MatchOperand_NoMatch;
3276
3277 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3278 // basepri, basepri_max and faultmask only valid for V7m.
3279 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003280
James Molloyacad68d2011-09-28 14:21:38 +00003281 Parser.Lex(); // Eat identifier token.
3282 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3283 return MatchOperand_Success;
3284 }
3285
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003286 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3287 size_t Start = 0, Next = Mask.find('_');
3288 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003289 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003290 if (Next != StringRef::npos)
3291 Flags = Mask.slice(Next+1, Mask.size());
3292
3293 // FlagsVal contains the complete mask:
3294 // 3-0: Mask
3295 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3296 unsigned FlagsVal = 0;
3297
3298 if (SpecReg == "apsr") {
3299 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003300 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003301 .Case("g", 0x4) // same as CPSR_s
3302 .Case("nzcvqg", 0xc) // same as CPSR_fs
3303 .Default(~0U);
3304
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003305 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003306 if (!Flags.empty())
3307 return MatchOperand_NoMatch;
3308 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003309 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003310 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003311 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003312 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3313 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003314 for (int i = 0, e = Flags.size(); i != e; ++i) {
3315 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3316 .Case("c", 1)
3317 .Case("x", 2)
3318 .Case("s", 4)
3319 .Case("f", 8)
3320 .Default(~0U);
3321
3322 // If some specific flag is already set, it means that some letter is
3323 // present more than once, this is not acceptable.
3324 if (FlagsVal == ~0U || (FlagsVal & Flag))
3325 return MatchOperand_NoMatch;
3326 FlagsVal |= Flag;
3327 }
3328 } else // No match for special register.
3329 return MatchOperand_NoMatch;
3330
Owen Anderson7784f1d2011-10-21 18:43:28 +00003331 // Special register without flags is NOT equivalent to "fc" flags.
3332 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3333 // two lines would enable gas compatibility at the expense of breaking
3334 // round-tripping.
3335 //
3336 // if (!FlagsVal)
3337 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003338
3339 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3340 if (SpecReg == "spsr")
3341 FlagsVal |= 16;
3342
3343 Parser.Lex(); // Eat identifier token.
3344 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3345 return MatchOperand_Success;
3346}
3347
Jim Grosbachf6c05252011-07-21 17:23:04 +00003348ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3349parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3350 int Low, int High) {
3351 const AsmToken &Tok = Parser.getTok();
3352 if (Tok.isNot(AsmToken::Identifier)) {
3353 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3354 return MatchOperand_ParseFail;
3355 }
3356 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003357 std::string LowerOp = Op.lower();
3358 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003359 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3360 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3361 return MatchOperand_ParseFail;
3362 }
3363 Parser.Lex(); // Eat shift type token.
3364
3365 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003366 if (Parser.getTok().isNot(AsmToken::Hash) &&
3367 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003368 Error(Parser.getTok().getLoc(), "'#' expected");
3369 return MatchOperand_ParseFail;
3370 }
3371 Parser.Lex(); // Eat hash token.
3372
3373 const MCExpr *ShiftAmount;
3374 SMLoc Loc = Parser.getTok().getLoc();
3375 if (getParser().ParseExpression(ShiftAmount)) {
3376 Error(Loc, "illegal expression");
3377 return MatchOperand_ParseFail;
3378 }
3379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3380 if (!CE) {
3381 Error(Loc, "constant expression expected");
3382 return MatchOperand_ParseFail;
3383 }
3384 int Val = CE->getValue();
3385 if (Val < Low || Val > High) {
3386 Error(Loc, "immediate value out of range");
3387 return MatchOperand_ParseFail;
3388 }
3389
3390 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3391
3392 return MatchOperand_Success;
3393}
3394
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003395ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3396parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3397 const AsmToken &Tok = Parser.getTok();
3398 SMLoc S = Tok.getLoc();
3399 if (Tok.isNot(AsmToken::Identifier)) {
3400 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3401 return MatchOperand_ParseFail;
3402 }
3403 int Val = StringSwitch<int>(Tok.getString())
3404 .Case("be", 1)
3405 .Case("le", 0)
3406 .Default(-1);
3407 Parser.Lex(); // Eat the token.
3408
3409 if (Val == -1) {
3410 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3411 return MatchOperand_ParseFail;
3412 }
3413 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3414 getContext()),
3415 S, Parser.getTok().getLoc()));
3416 return MatchOperand_Success;
3417}
3418
Jim Grosbach580f4a92011-07-25 22:20:28 +00003419/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3420/// instructions. Legal values are:
3421/// lsl #n 'n' in [0,31]
3422/// asr #n 'n' in [1,32]
3423/// n == 32 encoded as n == 0.
3424ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3425parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3426 const AsmToken &Tok = Parser.getTok();
3427 SMLoc S = Tok.getLoc();
3428 if (Tok.isNot(AsmToken::Identifier)) {
3429 Error(S, "shift operator 'asr' or 'lsl' expected");
3430 return MatchOperand_ParseFail;
3431 }
3432 StringRef ShiftName = Tok.getString();
3433 bool isASR;
3434 if (ShiftName == "lsl" || ShiftName == "LSL")
3435 isASR = false;
3436 else if (ShiftName == "asr" || ShiftName == "ASR")
3437 isASR = true;
3438 else {
3439 Error(S, "shift operator 'asr' or 'lsl' expected");
3440 return MatchOperand_ParseFail;
3441 }
3442 Parser.Lex(); // Eat the operator.
3443
3444 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003445 if (Parser.getTok().isNot(AsmToken::Hash) &&
3446 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003447 Error(Parser.getTok().getLoc(), "'#' expected");
3448 return MatchOperand_ParseFail;
3449 }
3450 Parser.Lex(); // Eat hash token.
3451
3452 const MCExpr *ShiftAmount;
3453 SMLoc E = Parser.getTok().getLoc();
3454 if (getParser().ParseExpression(ShiftAmount)) {
3455 Error(E, "malformed shift expression");
3456 return MatchOperand_ParseFail;
3457 }
3458 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3459 if (!CE) {
3460 Error(E, "shift amount must be an immediate");
3461 return MatchOperand_ParseFail;
3462 }
3463
3464 int64_t Val = CE->getValue();
3465 if (isASR) {
3466 // Shift amount must be in [1,32]
3467 if (Val < 1 || Val > 32) {
3468 Error(E, "'asr' shift amount must be in range [1,32]");
3469 return MatchOperand_ParseFail;
3470 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003471 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3472 if (isThumb() && Val == 32) {
3473 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3474 return MatchOperand_ParseFail;
3475 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003476 if (Val == 32) Val = 0;
3477 } else {
3478 // Shift amount must be in [1,32]
3479 if (Val < 0 || Val > 31) {
3480 Error(E, "'lsr' shift amount must be in range [0,31]");
3481 return MatchOperand_ParseFail;
3482 }
3483 }
3484
3485 E = Parser.getTok().getLoc();
3486 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3487
3488 return MatchOperand_Success;
3489}
3490
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003491/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3492/// of instructions. Legal values are:
3493/// ror #n 'n' in {0, 8, 16, 24}
3494ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3495parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3496 const AsmToken &Tok = Parser.getTok();
3497 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003498 if (Tok.isNot(AsmToken::Identifier))
3499 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003500 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003501 if (ShiftName != "ror" && ShiftName != "ROR")
3502 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003503 Parser.Lex(); // Eat the operator.
3504
3505 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003506 if (Parser.getTok().isNot(AsmToken::Hash) &&
3507 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003508 Error(Parser.getTok().getLoc(), "'#' expected");
3509 return MatchOperand_ParseFail;
3510 }
3511 Parser.Lex(); // Eat hash token.
3512
3513 const MCExpr *ShiftAmount;
3514 SMLoc E = Parser.getTok().getLoc();
3515 if (getParser().ParseExpression(ShiftAmount)) {
3516 Error(E, "malformed rotate expression");
3517 return MatchOperand_ParseFail;
3518 }
3519 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3520 if (!CE) {
3521 Error(E, "rotate amount must be an immediate");
3522 return MatchOperand_ParseFail;
3523 }
3524
3525 int64_t Val = CE->getValue();
3526 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3527 // normally, zero is represented in asm by omitting the rotate operand
3528 // entirely.
3529 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3530 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3531 return MatchOperand_ParseFail;
3532 }
3533
3534 E = Parser.getTok().getLoc();
3535 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3536
3537 return MatchOperand_Success;
3538}
3539
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003540ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3541parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3542 SMLoc S = Parser.getTok().getLoc();
3543 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003544 if (Parser.getTok().isNot(AsmToken::Hash) &&
3545 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003546 Error(Parser.getTok().getLoc(), "'#' expected");
3547 return MatchOperand_ParseFail;
3548 }
3549 Parser.Lex(); // Eat hash token.
3550
3551 const MCExpr *LSBExpr;
3552 SMLoc E = Parser.getTok().getLoc();
3553 if (getParser().ParseExpression(LSBExpr)) {
3554 Error(E, "malformed immediate expression");
3555 return MatchOperand_ParseFail;
3556 }
3557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3558 if (!CE) {
3559 Error(E, "'lsb' operand must be an immediate");
3560 return MatchOperand_ParseFail;
3561 }
3562
3563 int64_t LSB = CE->getValue();
3564 // The LSB must be in the range [0,31]
3565 if (LSB < 0 || LSB > 31) {
3566 Error(E, "'lsb' operand must be in the range [0,31]");
3567 return MatchOperand_ParseFail;
3568 }
3569 E = Parser.getTok().getLoc();
3570
3571 // Expect another immediate operand.
3572 if (Parser.getTok().isNot(AsmToken::Comma)) {
3573 Error(Parser.getTok().getLoc(), "too few operands");
3574 return MatchOperand_ParseFail;
3575 }
3576 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003577 if (Parser.getTok().isNot(AsmToken::Hash) &&
3578 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003579 Error(Parser.getTok().getLoc(), "'#' expected");
3580 return MatchOperand_ParseFail;
3581 }
3582 Parser.Lex(); // Eat hash token.
3583
3584 const MCExpr *WidthExpr;
3585 if (getParser().ParseExpression(WidthExpr)) {
3586 Error(E, "malformed immediate expression");
3587 return MatchOperand_ParseFail;
3588 }
3589 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3590 if (!CE) {
3591 Error(E, "'width' operand must be an immediate");
3592 return MatchOperand_ParseFail;
3593 }
3594
3595 int64_t Width = CE->getValue();
3596 // The LSB must be in the range [1,32-lsb]
3597 if (Width < 1 || Width > 32 - LSB) {
3598 Error(E, "'width' operand must be in the range [1,32-lsb]");
3599 return MatchOperand_ParseFail;
3600 }
3601 E = Parser.getTok().getLoc();
3602
3603 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3604
3605 return MatchOperand_Success;
3606}
3607
Jim Grosbach7ce05792011-08-03 23:50:40 +00003608ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3609parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3610 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003611 // postidx_reg := '+' register {, shift}
3612 // | '-' register {, shift}
3613 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003614
3615 // This method must return MatchOperand_NoMatch without consuming any tokens
3616 // in the case where there is no match, as other alternatives take other
3617 // parse methods.
3618 AsmToken Tok = Parser.getTok();
3619 SMLoc S = Tok.getLoc();
3620 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003621 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003622 int Reg = -1;
3623 if (Tok.is(AsmToken::Plus)) {
3624 Parser.Lex(); // Eat the '+' token.
3625 haveEaten = true;
3626 } else if (Tok.is(AsmToken::Minus)) {
3627 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003628 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003629 haveEaten = true;
3630 }
3631 if (Parser.getTok().is(AsmToken::Identifier))
3632 Reg = tryParseRegister();
3633 if (Reg == -1) {
3634 if (!haveEaten)
3635 return MatchOperand_NoMatch;
3636 Error(Parser.getTok().getLoc(), "register expected");
3637 return MatchOperand_ParseFail;
3638 }
3639 SMLoc E = Parser.getTok().getLoc();
3640
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003641 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3642 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003643 if (Parser.getTok().is(AsmToken::Comma)) {
3644 Parser.Lex(); // Eat the ','.
3645 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3646 return MatchOperand_ParseFail;
3647 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003648
3649 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3650 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003651
3652 return MatchOperand_Success;
3653}
3654
Jim Grosbach251bf252011-08-10 21:56:18 +00003655ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3656parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3657 // Check for a post-index addressing register operand. Specifically:
3658 // am3offset := '+' register
3659 // | '-' register
3660 // | register
3661 // | # imm
3662 // | # + imm
3663 // | # - imm
3664
3665 // This method must return MatchOperand_NoMatch without consuming any tokens
3666 // in the case where there is no match, as other alternatives take other
3667 // parse methods.
3668 AsmToken Tok = Parser.getTok();
3669 SMLoc S = Tok.getLoc();
3670
3671 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003672 if (Parser.getTok().is(AsmToken::Hash) ||
3673 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003674 Parser.Lex(); // Eat the '#'.
3675 // Explicitly look for a '-', as we need to encode negative zero
3676 // differently.
3677 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3678 const MCExpr *Offset;
3679 if (getParser().ParseExpression(Offset))
3680 return MatchOperand_ParseFail;
3681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3682 if (!CE) {
3683 Error(S, "constant expression expected");
3684 return MatchOperand_ParseFail;
3685 }
3686 SMLoc E = Tok.getLoc();
3687 // Negative zero is encoded as the flag value INT32_MIN.
3688 int32_t Val = CE->getValue();
3689 if (isNegative && Val == 0)
3690 Val = INT32_MIN;
3691
3692 Operands.push_back(
3693 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3694
3695 return MatchOperand_Success;
3696 }
3697
3698
3699 bool haveEaten = false;
3700 bool isAdd = true;
3701 int Reg = -1;
3702 if (Tok.is(AsmToken::Plus)) {
3703 Parser.Lex(); // Eat the '+' token.
3704 haveEaten = true;
3705 } else if (Tok.is(AsmToken::Minus)) {
3706 Parser.Lex(); // Eat the '-' token.
3707 isAdd = false;
3708 haveEaten = true;
3709 }
3710 if (Parser.getTok().is(AsmToken::Identifier))
3711 Reg = tryParseRegister();
3712 if (Reg == -1) {
3713 if (!haveEaten)
3714 return MatchOperand_NoMatch;
3715 Error(Parser.getTok().getLoc(), "register expected");
3716 return MatchOperand_ParseFail;
3717 }
3718 SMLoc E = Parser.getTok().getLoc();
3719
3720 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3721 0, S, E));
3722
3723 return MatchOperand_Success;
3724}
3725
Jim Grosbacha77295d2011-09-08 22:07:06 +00003726/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3727/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3728/// when they refer multiple MIOperands inside a single one.
3729bool ARMAsmParser::
3730cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3731 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3732 // Rt, Rt2
3733 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3734 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3735 // Create a writeback register dummy placeholder.
3736 Inst.addOperand(MCOperand::CreateReg(0));
3737 // addr
3738 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3739 // pred
3740 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3741 return true;
3742}
3743
3744/// cvtT2StrdPre - Convert parsed operands to MCInst.
3745/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3746/// when they refer multiple MIOperands inside a single one.
3747bool ARMAsmParser::
3748cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3749 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3750 // Create a writeback register dummy placeholder.
3751 Inst.addOperand(MCOperand::CreateReg(0));
3752 // Rt, Rt2
3753 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3754 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3755 // addr
3756 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3757 // pred
3758 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3759 return true;
3760}
3761
Jim Grosbacheeec0252011-09-08 00:39:19 +00003762/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3763/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3764/// when they refer multiple MIOperands inside a single one.
3765bool ARMAsmParser::
3766cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3767 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3768 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3769
3770 // Create a writeback register dummy placeholder.
3771 Inst.addOperand(MCOperand::CreateImm(0));
3772
3773 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3774 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3775 return true;
3776}
3777
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003778/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3779/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3780/// when they refer multiple MIOperands inside a single one.
3781bool ARMAsmParser::
3782cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3783 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3784 // Create a writeback register dummy placeholder.
3785 Inst.addOperand(MCOperand::CreateImm(0));
3786 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3787 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3788 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3789 return true;
3790}
3791
Jim Grosbach1355cf12011-07-26 17:10:22 +00003792/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003793/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3794/// when they refer multiple MIOperands inside a single one.
3795bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003796cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003797 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3798 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3799
3800 // Create a writeback register dummy placeholder.
3801 Inst.addOperand(MCOperand::CreateImm(0));
3802
Jim Grosbach7ce05792011-08-03 23:50:40 +00003803 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003804 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3805 return true;
3806}
3807
Owen Anderson9ab0f252011-08-26 20:43:14 +00003808/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3809/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3810/// when they refer multiple MIOperands inside a single one.
3811bool ARMAsmParser::
3812cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3813 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3814 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3815
3816 // Create a writeback register dummy placeholder.
3817 Inst.addOperand(MCOperand::CreateImm(0));
3818
3819 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3820 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3821 return true;
3822}
3823
3824
Jim Grosbach548340c2011-08-11 19:22:40 +00003825/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3826/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3827/// when they refer multiple MIOperands inside a single one.
3828bool ARMAsmParser::
3829cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3830 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3831 // Create a writeback register dummy placeholder.
3832 Inst.addOperand(MCOperand::CreateImm(0));
3833 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3834 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3835 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3836 return true;
3837}
3838
Jim Grosbach1355cf12011-07-26 17:10:22 +00003839/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003840/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3841/// when they refer multiple MIOperands inside a single one.
3842bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003843cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003844 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3845 // Create a writeback register dummy placeholder.
3846 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003847 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3848 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3849 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003850 return true;
3851}
3852
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003853/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3854/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3855/// when they refer multiple MIOperands inside a single one.
3856bool ARMAsmParser::
3857cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3858 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3859 // Create a writeback register dummy placeholder.
3860 Inst.addOperand(MCOperand::CreateImm(0));
3861 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3862 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3863 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3864 return true;
3865}
3866
Jim Grosbach7ce05792011-08-03 23:50:40 +00003867/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3868/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3869/// when they refer multiple MIOperands inside a single one.
3870bool ARMAsmParser::
3871cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3872 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3873 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003874 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003875 // Create a writeback register dummy placeholder.
3876 Inst.addOperand(MCOperand::CreateImm(0));
3877 // addr
3878 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3879 // offset
3880 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3881 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003882 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3883 return true;
3884}
3885
Jim Grosbach7ce05792011-08-03 23:50:40 +00003886/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003887/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3888/// when they refer multiple MIOperands inside a single one.
3889bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003890cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3891 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3892 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003893 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003894 // Create a writeback register dummy placeholder.
3895 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003896 // addr
3897 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3898 // offset
3899 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3900 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003901 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3902 return true;
3903}
3904
Jim Grosbach7ce05792011-08-03 23:50:40 +00003905/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003906/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3907/// when they refer multiple MIOperands inside a single one.
3908bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003909cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3910 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003911 // Create a writeback register dummy placeholder.
3912 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003913 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003914 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003915 // addr
3916 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3917 // offset
3918 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3919 // pred
3920 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3921 return true;
3922}
3923
3924/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3925/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3926/// when they refer multiple MIOperands inside a single one.
3927bool ARMAsmParser::
3928cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3929 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3930 // Create a writeback register dummy placeholder.
3931 Inst.addOperand(MCOperand::CreateImm(0));
3932 // Rt
3933 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3934 // addr
3935 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3936 // offset
3937 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3938 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003939 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3940 return true;
3941}
3942
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003943/// cvtLdrdPre - Convert parsed operands to MCInst.
3944/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3945/// when they refer multiple MIOperands inside a single one.
3946bool ARMAsmParser::
3947cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3948 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3949 // Rt, Rt2
3950 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3951 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3952 // Create a writeback register dummy placeholder.
3953 Inst.addOperand(MCOperand::CreateImm(0));
3954 // addr
3955 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3956 // pred
3957 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3958 return true;
3959}
3960
Jim Grosbach14605d12011-08-11 20:28:23 +00003961/// cvtStrdPre - Convert parsed operands to MCInst.
3962/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3963/// when they refer multiple MIOperands inside a single one.
3964bool ARMAsmParser::
3965cvtStrdPre(MCInst &Inst, unsigned Opcode,
3966 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3967 // Create a writeback register dummy placeholder.
3968 Inst.addOperand(MCOperand::CreateImm(0));
3969 // Rt, Rt2
3970 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3971 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3972 // addr
3973 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3974 // pred
3975 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3976 return true;
3977}
3978
Jim Grosbach623a4542011-08-10 22:42:16 +00003979/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3980/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3981/// when they refer multiple MIOperands inside a single one.
3982bool ARMAsmParser::
3983cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3984 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3985 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3986 // Create a writeback register dummy placeholder.
3987 Inst.addOperand(MCOperand::CreateImm(0));
3988 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3989 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3990 return true;
3991}
3992
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003993/// cvtThumbMultiple- Convert parsed operands to MCInst.
3994/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3995/// when they refer multiple MIOperands inside a single one.
3996bool ARMAsmParser::
3997cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3998 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3999 // The second source operand must be the same register as the destination
4000 // operand.
4001 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004002 (((ARMOperand*)Operands[3])->getReg() !=
4003 ((ARMOperand*)Operands[5])->getReg()) &&
4004 (((ARMOperand*)Operands[3])->getReg() !=
4005 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004006 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004007 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004008 return false;
4009 }
4010 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4011 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004012 // If we have a three-operand form, make sure to set Rn to be the operand
4013 // that isn't the same as Rd.
4014 unsigned RegOp = 4;
4015 if (Operands.size() == 6 &&
4016 ((ARMOperand*)Operands[4])->getReg() ==
4017 ((ARMOperand*)Operands[3])->getReg())
4018 RegOp = 5;
4019 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4020 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004021 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4022
4023 return true;
4024}
Jim Grosbach623a4542011-08-10 22:42:16 +00004025
Jim Grosbach12431322011-10-24 22:16:58 +00004026bool ARMAsmParser::
4027cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4028 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4029 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004030 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004031 // Create a writeback register dummy placeholder.
4032 Inst.addOperand(MCOperand::CreateImm(0));
4033 // Vn
4034 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4035 // pred
4036 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4037 return true;
4038}
4039
4040bool ARMAsmParser::
4041cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4042 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4043 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004044 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004045 // Create a writeback register dummy placeholder.
4046 Inst.addOperand(MCOperand::CreateImm(0));
4047 // Vn
4048 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4049 // Vm
4050 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4051 // pred
4052 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4053 return true;
4054}
4055
Jim Grosbach4334e032011-10-31 21:50:31 +00004056bool ARMAsmParser::
4057cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4058 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4059 // Create a writeback register dummy placeholder.
4060 Inst.addOperand(MCOperand::CreateImm(0));
4061 // Vn
4062 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4063 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004064 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004065 // pred
4066 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4067 return true;
4068}
4069
4070bool ARMAsmParser::
4071cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4072 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4073 // Create a writeback register dummy placeholder.
4074 Inst.addOperand(MCOperand::CreateImm(0));
4075 // Vn
4076 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4077 // Vm
4078 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4079 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004080 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004081 // pred
4082 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4083 return true;
4084}
4085
Bill Wendlinge7176102010-11-06 22:36:58 +00004086/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004087/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004088bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004089parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004090 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004091 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004092 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004093 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004094 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004095
Sean Callanan18b83232010-01-19 21:44:56 +00004096 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004097 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004098 if (BaseRegNum == -1)
4099 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004100
Daniel Dunbar05710932011-01-18 05:34:17 +00004101 // The next token must either be a comma or a closing bracket.
4102 const AsmToken &Tok = Parser.getTok();
4103 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004104 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004105
Jim Grosbach7ce05792011-08-03 23:50:40 +00004106 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004107 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004108 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004109
Jim Grosbach7ce05792011-08-03 23:50:40 +00004110 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004111 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004112
Jim Grosbachfb12f352011-09-19 18:42:21 +00004113 // If there's a pre-indexing writeback marker, '!', just add it as a token
4114 // operand. It's rather odd, but syntactically valid.
4115 if (Parser.getTok().is(AsmToken::Exclaim)) {
4116 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4117 Parser.Lex(); // Eat the '!'.
4118 }
4119
Jim Grosbach7ce05792011-08-03 23:50:40 +00004120 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004121 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004122
Jim Grosbach7ce05792011-08-03 23:50:40 +00004123 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4124 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004125
Jim Grosbach57dcb852011-10-11 17:29:55 +00004126 // If we have a ':', it's an alignment specifier.
4127 if (Parser.getTok().is(AsmToken::Colon)) {
4128 Parser.Lex(); // Eat the ':'.
4129 E = Parser.getTok().getLoc();
4130
4131 const MCExpr *Expr;
4132 if (getParser().ParseExpression(Expr))
4133 return true;
4134
4135 // The expression has to be a constant. Memory references with relocations
4136 // don't come through here, as they use the <label> forms of the relevant
4137 // instructions.
4138 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4139 if (!CE)
4140 return Error (E, "constant expression expected");
4141
4142 unsigned Align = 0;
4143 switch (CE->getValue()) {
4144 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004145 return Error(E,
4146 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4147 case 16: Align = 2; break;
4148 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004149 case 64: Align = 8; break;
4150 case 128: Align = 16; break;
4151 case 256: Align = 32; break;
4152 }
4153
4154 // Now we should have the closing ']'
4155 E = Parser.getTok().getLoc();
4156 if (Parser.getTok().isNot(AsmToken::RBrac))
4157 return Error(E, "']' expected");
4158 Parser.Lex(); // Eat right bracket token.
4159
4160 // Don't worry about range checking the value here. That's handled by
4161 // the is*() predicates.
4162 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4163 ARM_AM::no_shift, 0, Align,
4164 false, S, E));
4165
4166 // If there's a pre-indexing writeback marker, '!', just add it as a token
4167 // operand.
4168 if (Parser.getTok().is(AsmToken::Exclaim)) {
4169 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4170 Parser.Lex(); // Eat the '!'.
4171 }
4172
4173 return false;
4174 }
4175
4176 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004177 // offset. Be friendly and also accept a plain integer (without a leading
4178 // hash) for gas compatibility.
4179 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004180 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004181 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004182 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004183 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004184 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004185
Owen Anderson0da10cf2011-08-29 19:36:44 +00004186 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004187 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004188 if (getParser().ParseExpression(Offset))
4189 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004190
4191 // The expression has to be a constant. Memory references with relocations
4192 // don't come through here, as they use the <label> forms of the relevant
4193 // instructions.
4194 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4195 if (!CE)
4196 return Error (E, "constant expression expected");
4197
Owen Anderson0da10cf2011-08-29 19:36:44 +00004198 // If the constant was #-0, represent it as INT32_MIN.
4199 int32_t Val = CE->getValue();
4200 if (isNegative && Val == 0)
4201 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4202
Jim Grosbach7ce05792011-08-03 23:50:40 +00004203 // Now we should have the closing ']'
4204 E = Parser.getTok().getLoc();
4205 if (Parser.getTok().isNot(AsmToken::RBrac))
4206 return Error(E, "']' expected");
4207 Parser.Lex(); // Eat right bracket token.
4208
4209 // Don't worry about range checking the value here. That's handled by
4210 // the is*() predicates.
4211 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004212 ARM_AM::no_shift, 0, 0,
4213 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004214
4215 // If there's a pre-indexing writeback marker, '!', just add it as a token
4216 // operand.
4217 if (Parser.getTok().is(AsmToken::Exclaim)) {
4218 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4219 Parser.Lex(); // Eat the '!'.
4220 }
4221
4222 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004223 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004224
4225 // The register offset is optionally preceded by a '+' or '-'
4226 bool isNegative = false;
4227 if (Parser.getTok().is(AsmToken::Minus)) {
4228 isNegative = true;
4229 Parser.Lex(); // Eat the '-'.
4230 } else if (Parser.getTok().is(AsmToken::Plus)) {
4231 // Nothing to do.
4232 Parser.Lex(); // Eat the '+'.
4233 }
4234
4235 E = Parser.getTok().getLoc();
4236 int OffsetRegNum = tryParseRegister();
4237 if (OffsetRegNum == -1)
4238 return Error(E, "register expected");
4239
4240 // If there's a shift operator, handle it.
4241 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004242 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004243 if (Parser.getTok().is(AsmToken::Comma)) {
4244 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004245 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004246 return true;
4247 }
4248
4249 // Now we should have the closing ']'
4250 E = Parser.getTok().getLoc();
4251 if (Parser.getTok().isNot(AsmToken::RBrac))
4252 return Error(E, "']' expected");
4253 Parser.Lex(); // Eat right bracket token.
4254
4255 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004256 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004257 S, E));
4258
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004259 // If there's a pre-indexing writeback marker, '!', just add it as a token
4260 // operand.
4261 if (Parser.getTok().is(AsmToken::Exclaim)) {
4262 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4263 Parser.Lex(); // Eat the '!'.
4264 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004265
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004266 return false;
4267}
4268
Jim Grosbach7ce05792011-08-03 23:50:40 +00004269/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004270/// ( lsl | lsr | asr | ror ) , # shift_amount
4271/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004272/// return true if it parses a shift otherwise it returns false.
4273bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4274 unsigned &Amount) {
4275 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004276 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004277 if (Tok.isNot(AsmToken::Identifier))
4278 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004279 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004280 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4281 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004282 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004283 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004284 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004285 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004286 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004287 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004288 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004289 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004290 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004291 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004292 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004293 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004294
Jim Grosbach7ce05792011-08-03 23:50:40 +00004295 // rrx stands alone.
4296 Amount = 0;
4297 if (St != ARM_AM::rrx) {
4298 Loc = Parser.getTok().getLoc();
4299 // A '#' and a shift amount.
4300 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004301 if (HashTok.isNot(AsmToken::Hash) &&
4302 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004303 return Error(HashTok.getLoc(), "'#' expected");
4304 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004305
Jim Grosbach7ce05792011-08-03 23:50:40 +00004306 const MCExpr *Expr;
4307 if (getParser().ParseExpression(Expr))
4308 return true;
4309 // Range check the immediate.
4310 // lsl, ror: 0 <= imm <= 31
4311 // lsr, asr: 0 <= imm <= 32
4312 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4313 if (!CE)
4314 return Error(Loc, "shift amount must be an immediate");
4315 int64_t Imm = CE->getValue();
4316 if (Imm < 0 ||
4317 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4318 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4319 return Error(Loc, "immediate shift value out of range");
4320 Amount = Imm;
4321 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004322
4323 return false;
4324}
4325
Jim Grosbach9d390362011-10-03 23:38:36 +00004326/// parseFPImm - A floating point immediate expression operand.
4327ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4328parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004329 // Anything that can accept a floating point constant as an operand
4330 // needs to go through here, as the regular ParseExpression is
4331 // integer only.
4332 //
4333 // This routine still creates a generic Immediate operand, containing
4334 // a bitcast of the 64-bit floating point value. The various operands
4335 // that accept floats can check whether the value is valid for them
4336 // via the standard is*() predicates.
4337
Jim Grosbach9d390362011-10-03 23:38:36 +00004338 SMLoc S = Parser.getTok().getLoc();
4339
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004340 if (Parser.getTok().isNot(AsmToken::Hash) &&
4341 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004342 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004343
4344 // Disambiguate the VMOV forms that can accept an FP immediate.
4345 // vmov.f32 <sreg>, #imm
4346 // vmov.f64 <dreg>, #imm
4347 // vmov.f32 <dreg>, #imm @ vector f32x2
4348 // vmov.f32 <qreg>, #imm @ vector f32x4
4349 //
4350 // There are also the NEON VMOV instructions which expect an
4351 // integer constant. Make sure we don't try to parse an FPImm
4352 // for these:
4353 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4354 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4355 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4356 TyOp->getToken() != ".f64"))
4357 return MatchOperand_NoMatch;
4358
Jim Grosbach9d390362011-10-03 23:38:36 +00004359 Parser.Lex(); // Eat the '#'.
4360
4361 // Handle negation, as that still comes through as a separate token.
4362 bool isNegative = false;
4363 if (Parser.getTok().is(AsmToken::Minus)) {
4364 isNegative = true;
4365 Parser.Lex();
4366 }
4367 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004368 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004369 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004370 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004371 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4372 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004373 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004374 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004375 Operands.push_back(ARMOperand::CreateImm(
4376 MCConstantExpr::Create(IntVal, getContext()),
4377 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004378 return MatchOperand_Success;
4379 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004380 // Also handle plain integers. Instructions which allow floating point
4381 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004382 if (Tok.is(AsmToken::Integer)) {
4383 int64_t Val = Tok.getIntVal();
4384 Parser.Lex(); // Eat the token.
4385 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004386 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004387 return MatchOperand_ParseFail;
4388 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004389 double RealVal = ARM_AM::getFPImmFloat(Val);
4390 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4391 Operands.push_back(ARMOperand::CreateImm(
4392 MCConstantExpr::Create(Val, getContext()), S,
4393 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004394 return MatchOperand_Success;
4395 }
4396
Jim Grosbachae69f702012-01-19 02:47:30 +00004397 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004398 return MatchOperand_ParseFail;
4399}
Jim Grosbach51222d12012-01-20 18:09:51 +00004400
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004401/// Parse a arm instruction operand. For now this parses the operand regardless
4402/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004403bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004404 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004405 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004406
4407 // Check if the current operand has a custom associated parser, if so, try to
4408 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004409 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4410 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004411 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004412 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4413 // there was a match, but an error occurred, in which case, just return that
4414 // the operand parsing failed.
4415 if (ResTy == MatchOperand_ParseFail)
4416 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004417
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004418 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004419 default:
4420 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004421 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004422 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004423 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004424 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004425 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004426 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004427 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004428 else if (Res == -1) // irrecoverable error
4429 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004430 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004431 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4432 S = Parser.getTok().getLoc();
4433 Parser.Lex();
4434 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4435 return false;
4436 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004437
4438 // Fall though for the Identifier case that is not a register or a
4439 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004440 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004441 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004442 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004443 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004444 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004445 // This was not a register so parse other operands that start with an
4446 // identifier (like labels) as expressions and create them as immediates.
4447 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004448 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004449 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004450 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004451 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004452 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4453 return false;
4454 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004455 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004456 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004457 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004458 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004459 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004460 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004461 // #42 -> immediate.
4462 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004463 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004464 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004465 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004466 const MCExpr *ImmVal;
4467 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004468 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004469 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004470 if (CE) {
4471 int32_t Val = CE->getValue();
4472 if (isNegative && Val == 0)
4473 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004474 }
Sean Callanan76264762010-04-02 22:27:05 +00004475 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004476 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4477 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004478 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004479 case AsmToken::Colon: {
4480 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004481 // FIXME: Check it's an expression prefix,
4482 // e.g. (FOO - :lower16:BAR) isn't legal.
4483 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004484 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004485 return true;
4486
Evan Cheng75972122011-01-13 07:58:56 +00004487 const MCExpr *SubExprVal;
4488 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004489 return true;
4490
Evan Cheng75972122011-01-13 07:58:56 +00004491 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4492 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004493 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004494 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004495 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004496 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004497 }
4498}
4499
Jim Grosbach1355cf12011-07-26 17:10:22 +00004500// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004501// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004502bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004503 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004504
4505 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004506 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004507 Parser.Lex(); // Eat ':'
4508
4509 if (getLexer().isNot(AsmToken::Identifier)) {
4510 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4511 return true;
4512 }
4513
4514 StringRef IDVal = Parser.getTok().getIdentifier();
4515 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004516 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004517 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004518 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004519 } else {
4520 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4521 return true;
4522 }
4523 Parser.Lex();
4524
4525 if (getLexer().isNot(AsmToken::Colon)) {
4526 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4527 return true;
4528 }
4529 Parser.Lex(); // Eat the last ':'
4530 return false;
4531}
4532
Daniel Dunbar352e1482011-01-11 15:59:50 +00004533/// \brief Given a mnemonic, split out possible predication code and carry
4534/// setting letters to form a canonical mnemonic and flags.
4535//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004536// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004537// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004538StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004539 unsigned &PredicationCode,
4540 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004541 unsigned &ProcessorIMod,
4542 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004543 PredicationCode = ARMCC::AL;
4544 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004545 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004546
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004547 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004548 //
4549 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004550 if ((Mnemonic == "movs" && isThumb()) ||
4551 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4552 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4553 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4554 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4555 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4556 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004557 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4558 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004559 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004560
Jim Grosbach3f00e312011-07-11 17:09:57 +00004561 // First, split out any predication code. Ignore mnemonics we know aren't
4562 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004563 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004564 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004565 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004566 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004567 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4568 .Case("eq", ARMCC::EQ)
4569 .Case("ne", ARMCC::NE)
4570 .Case("hs", ARMCC::HS)
4571 .Case("cs", ARMCC::HS)
4572 .Case("lo", ARMCC::LO)
4573 .Case("cc", ARMCC::LO)
4574 .Case("mi", ARMCC::MI)
4575 .Case("pl", ARMCC::PL)
4576 .Case("vs", ARMCC::VS)
4577 .Case("vc", ARMCC::VC)
4578 .Case("hi", ARMCC::HI)
4579 .Case("ls", ARMCC::LS)
4580 .Case("ge", ARMCC::GE)
4581 .Case("lt", ARMCC::LT)
4582 .Case("gt", ARMCC::GT)
4583 .Case("le", ARMCC::LE)
4584 .Case("al", ARMCC::AL)
4585 .Default(~0U);
4586 if (CC != ~0U) {
4587 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4588 PredicationCode = CC;
4589 }
Bill Wendling52925b62010-10-29 23:50:21 +00004590 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004591
Daniel Dunbar352e1482011-01-11 15:59:50 +00004592 // Next, determine if we have a carry setting bit. We explicitly ignore all
4593 // the instructions we know end in 's'.
4594 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004595 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004596 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4597 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4598 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004599 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004600 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004601 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004602 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004603 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004604 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4605 CarrySetting = true;
4606 }
4607
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004608 // The "cps" instruction can have a interrupt mode operand which is glued into
4609 // the mnemonic. Check if this is the case, split it and parse the imod op
4610 if (Mnemonic.startswith("cps")) {
4611 // Split out any imod code.
4612 unsigned IMod =
4613 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4614 .Case("ie", ARM_PROC::IE)
4615 .Case("id", ARM_PROC::ID)
4616 .Default(~0U);
4617 if (IMod != ~0U) {
4618 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4619 ProcessorIMod = IMod;
4620 }
4621 }
4622
Jim Grosbach89df9962011-08-26 21:43:41 +00004623 // The "it" instruction has the condition mask on the end of the mnemonic.
4624 if (Mnemonic.startswith("it")) {
4625 ITMask = Mnemonic.slice(2, Mnemonic.size());
4626 Mnemonic = Mnemonic.slice(0, 2);
4627 }
4628
Daniel Dunbar352e1482011-01-11 15:59:50 +00004629 return Mnemonic;
4630}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004631
4632/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4633/// inclusion of carry set or predication code operands.
4634//
4635// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004636void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004637getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004638 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004639 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4640 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004641 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004642 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004643 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004644 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004645 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004646 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004647 Mnemonic == "mla" || Mnemonic == "smlal" ||
4648 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004649 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004650 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004651 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004652
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004653 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4654 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4655 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4656 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004657 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4658 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004659 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004660 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4661 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4662 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004663 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4664 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004665 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004666 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004667 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004668 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004669
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004670 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004671 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004672 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004673 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004674 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004675}
4676
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004677bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4678 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004679 // FIXME: This is all horribly hacky. We really need a better way to deal
4680 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004681
4682 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4683 // another does not. Specifically, the MOVW instruction does not. So we
4684 // special case it here and remove the defaulted (non-setting) cc_out
4685 // operand if that's the instruction we're trying to match.
4686 //
4687 // We do this as post-processing of the explicit operands rather than just
4688 // conditionally adding the cc_out in the first place because we need
4689 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004690 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004691 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4692 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4693 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4694 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004695
4696 // Register-register 'add' for thumb does not have a cc_out operand
4697 // when there are only two register operands.
4698 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4699 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4700 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4701 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4702 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004703 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004704 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4705 // have to check the immediate range here since Thumb2 has a variant
4706 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004707 if (((isThumb() && Mnemonic == "add") ||
4708 (isThumbTwo() && Mnemonic == "sub")) &&
4709 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004710 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4711 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4712 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004713 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4714 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4715 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004716 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004717 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4718 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004719 // selecting via the generic "add" mnemonic, so to know that we
4720 // should remove the cc_out operand, we have to explicitly check that
4721 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004722 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4723 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004724 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4725 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4726 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4727 // Nest conditions rather than one big 'if' statement for readability.
4728 //
4729 // If either register is a high reg, it's either one of the SP
4730 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004731 // check against T3. If the second register is the PC, this is an
4732 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004733 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4734 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004735 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004736 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4737 return false;
4738 // If both registers are low, we're in an IT block, and the immediate is
4739 // in range, we should use encoding T1 instead, which has a cc_out.
4740 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004741 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004742 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4743 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4744 return false;
4745
4746 // Otherwise, we use encoding T4, which does not have a cc_out
4747 // operand.
4748 return true;
4749 }
4750
Jim Grosbach64944f42011-09-14 21:00:40 +00004751 // The thumb2 multiply instruction doesn't have a CCOut register, so
4752 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4753 // use the 16-bit encoding or not.
4754 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4755 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4756 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4757 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4758 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4759 // If the registers aren't low regs, the destination reg isn't the
4760 // same as one of the source regs, or the cc_out operand is zero
4761 // outside of an IT block, we have to use the 32-bit encoding, so
4762 // remove the cc_out operand.
4763 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4764 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004765 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004766 !inITBlock() ||
4767 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4768 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4769 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4770 static_cast<ARMOperand*>(Operands[4])->getReg())))
4771 return true;
4772
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004773 // Also check the 'mul' syntax variant that doesn't specify an explicit
4774 // destination register.
4775 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4776 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4777 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4778 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4779 // If the registers aren't low regs or the cc_out operand is zero
4780 // outside of an IT block, we have to use the 32-bit encoding, so
4781 // remove the cc_out operand.
4782 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4783 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4784 !inITBlock()))
4785 return true;
4786
Jim Grosbach64944f42011-09-14 21:00:40 +00004787
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004788
Jim Grosbachf69c8042011-08-24 21:42:27 +00004789 // Register-register 'add/sub' for thumb does not have a cc_out operand
4790 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4791 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4792 // right, this will result in better diagnostics (which operand is off)
4793 // anyway.
4794 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4795 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004796 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4797 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4798 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4799 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004800
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004801 return false;
4802}
4803
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004804static bool isDataTypeToken(StringRef Tok) {
4805 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4806 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4807 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4808 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4809 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4810 Tok == ".f" || Tok == ".d";
4811}
4812
4813// FIXME: This bit should probably be handled via an explicit match class
4814// in the .td files that matches the suffix instead of having it be
4815// a literal string token the way it is now.
4816static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4817 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4818}
4819
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004820static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004821/// Parse an arm instruction mnemonic followed by its operands.
4822bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4823 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004824 // Apply mnemonic aliases before doing anything else, as the destination
4825 // mnemnonic may include suffices and we want to handle them normally.
4826 // The generic tblgen'erated code does this later, at the start of
4827 // MatchInstructionImpl(), but that's too late for aliases that include
4828 // any sort of suffix.
4829 unsigned AvailableFeatures = getAvailableFeatures();
4830 applyMnemonicAliases(Name, AvailableFeatures);
4831
Jim Grosbacha39cda72011-12-14 02:16:11 +00004832 // First check for the ARM-specific .req directive.
4833 if (Parser.getTok().is(AsmToken::Identifier) &&
4834 Parser.getTok().getIdentifier() == ".req") {
4835 parseDirectiveReq(Name, NameLoc);
4836 // We always return 'error' for this, as we're done with this
4837 // statement and don't need to match the 'instruction."
4838 return true;
4839 }
4840
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004841 // Create the leading tokens for the mnemonic, split by '.' characters.
4842 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004843 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004844
Daniel Dunbar352e1482011-01-11 15:59:50 +00004845 // Split out the predication code and carry setting flag from the mnemonic.
4846 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004847 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004848 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004849 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004850 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004851 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004852
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004853 // In Thumb1, only the branch (B) instruction can be predicated.
4854 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4855 Parser.EatToEndOfStatement();
4856 return Error(NameLoc, "conditional execution not supported in Thumb1");
4857 }
4858
Jim Grosbachffa32252011-07-19 19:13:28 +00004859 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4860
Jim Grosbach89df9962011-08-26 21:43:41 +00004861 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4862 // is the mask as it will be for the IT encoding if the conditional
4863 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4864 // where the conditional bit0 is zero, the instruction post-processing
4865 // will adjust the mask accordingly.
4866 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004867 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4868 if (ITMask.size() > 3) {
4869 Parser.EatToEndOfStatement();
4870 return Error(Loc, "too many conditions on IT instruction");
4871 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004872 unsigned Mask = 8;
4873 for (unsigned i = ITMask.size(); i != 0; --i) {
4874 char pos = ITMask[i - 1];
4875 if (pos != 't' && pos != 'e') {
4876 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004877 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004878 }
4879 Mask >>= 1;
4880 if (ITMask[i - 1] == 't')
4881 Mask |= 8;
4882 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004883 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004884 }
4885
Jim Grosbachffa32252011-07-19 19:13:28 +00004886 // FIXME: This is all a pretty gross hack. We should automatically handle
4887 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004888
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004889 // Next, add the CCOut and ConditionCode operands, if needed.
4890 //
4891 // For mnemonics which can ever incorporate a carry setting bit or predication
4892 // code, our matching model involves us always generating CCOut and
4893 // ConditionCode operands to match the mnemonic "as written" and then we let
4894 // the matcher deal with finding the right instruction or generating an
4895 // appropriate error.
4896 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004897 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004898
Jim Grosbach33c16a22011-07-14 22:04:21 +00004899 // If we had a carry-set on an instruction that can't do that, issue an
4900 // error.
4901 if (!CanAcceptCarrySet && CarrySetting) {
4902 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004903 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004904 "' can not set flags, but 's' suffix specified");
4905 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004906 // If we had a predication code on an instruction that can't do that, issue an
4907 // error.
4908 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4909 Parser.EatToEndOfStatement();
4910 return Error(NameLoc, "instruction '" + Mnemonic +
4911 "' is not predicable, but condition code specified");
4912 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004913
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004914 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004915 if (CanAcceptCarrySet) {
4916 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004917 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004918 Loc));
4919 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004920
4921 // Add the predication code operand, if necessary.
4922 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004923 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4924 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004925 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004926 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004927 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004928
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004929 // Add the processor imod operand, if necessary.
4930 if (ProcessorIMod) {
4931 Operands.push_back(ARMOperand::CreateImm(
4932 MCConstantExpr::Create(ProcessorIMod, getContext()),
4933 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004934 }
4935
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004936 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004937 while (Next != StringRef::npos) {
4938 Start = Next;
4939 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004940 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004941
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004942 // Some NEON instructions have an optional datatype suffix that is
4943 // completely ignored. Check for that.
4944 if (isDataTypeToken(ExtraToken) &&
4945 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4946 continue;
4947
Jim Grosbach81d2e392011-09-07 16:06:04 +00004948 if (ExtraToken != ".n") {
4949 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4950 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4951 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004952 }
4953
4954 // Read the remaining operands.
4955 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004956 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004957 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004958 Parser.EatToEndOfStatement();
4959 return true;
4960 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004961
4962 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004963 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004964
4965 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004966 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004967 Parser.EatToEndOfStatement();
4968 return true;
4969 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004970 }
4971 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004972
Chris Lattnercbf8a982010-09-11 16:18:25 +00004973 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004974 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004975 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004976 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004977 }
Bill Wendling146018f2010-11-06 21:42:12 +00004978
Chris Lattner34e53142010-09-08 05:10:46 +00004979 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004980
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004981 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4982 // do and don't have a cc_out optional-def operand. With some spot-checks
4983 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004984 // parse and adjust accordingly before actually matching. We shouldn't ever
4985 // try to remove a cc_out operand that was explicitly set on the the
4986 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4987 // table driven matcher doesn't fit well with the ARM instruction set.
4988 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004989 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4990 Operands.erase(Operands.begin() + 1);
4991 delete Op;
4992 }
4993
Jim Grosbachcf121c32011-07-28 21:57:55 +00004994 // ARM mode 'blx' need special handling, as the register operand version
4995 // is predicable, but the label operand version is not. So, we can't rely
4996 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004997 // a k_CondCode operand in the list. If we're trying to match the label
4998 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004999 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5000 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5001 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5002 Operands.erase(Operands.begin() + 1);
5003 delete Op;
5004 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005005
5006 // The vector-compare-to-zero instructions have a literal token "#0" at
5007 // the end that comes to here as an immediate operand. Convert it to a
5008 // token to play nicely with the matcher.
5009 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5010 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5011 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5012 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5014 if (CE && CE->getValue() == 0) {
5015 Operands.erase(Operands.begin() + 5);
5016 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5017 delete Op;
5018 }
5019 }
Jim Grosbach68259142011-10-03 22:30:24 +00005020 // VCMP{E} does the same thing, but with a different operand count.
5021 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5022 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5023 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5024 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5025 if (CE && CE->getValue() == 0) {
5026 Operands.erase(Operands.begin() + 4);
5027 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5028 delete Op;
5029 }
5030 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005031 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005032 // end. Convert it to a token here. Take care not to convert those
5033 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005034 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005035 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5036 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005037 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5038 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5039 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005040 if (CE && CE->getValue() == 0 &&
5041 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005042 // The cc_out operand matches the IT block.
5043 ((inITBlock() != CarrySetting) &&
5044 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005045 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005046 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005047 Operands.erase(Operands.begin() + 5);
5048 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5049 delete Op;
5050 }
5051 }
5052
Chris Lattner98986712010-01-14 22:21:20 +00005053 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005054}
5055
Jim Grosbach189610f2011-07-26 18:25:39 +00005056// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005057
5058// return 'true' if register list contains non-low GPR registers,
5059// 'false' otherwise. If Reg is in the register list or is HiReg, set
5060// 'containsReg' to true.
5061static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5062 unsigned HiReg, bool &containsReg) {
5063 containsReg = false;
5064 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5065 unsigned OpReg = Inst.getOperand(i).getReg();
5066 if (OpReg == Reg)
5067 containsReg = true;
5068 // Anything other than a low register isn't legal here.
5069 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5070 return true;
5071 }
5072 return false;
5073}
5074
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005075// Check if the specified regisgter is in the register list of the inst,
5076// starting at the indicated operand number.
5077static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5078 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5079 unsigned OpReg = Inst.getOperand(i).getReg();
5080 if (OpReg == Reg)
5081 return true;
5082 }
5083 return false;
5084}
5085
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005086// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5087// the ARMInsts array) instead. Getting that here requires awkward
5088// API changes, though. Better way?
5089namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005090extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005091}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005092static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005093 return ARMInsts[Opcode];
5094}
5095
Jim Grosbach189610f2011-07-26 18:25:39 +00005096// FIXME: We would really like to be able to tablegen'erate this.
5097bool ARMAsmParser::
5098validateInstruction(MCInst &Inst,
5099 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005100 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005101 SMLoc Loc = Operands[0]->getStartLoc();
5102 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005103 // NOTE: BKPT instruction has the interesting property of being
5104 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005105 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005106 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5107 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005108 unsigned bit = 1;
5109 if (ITState.FirstCond)
5110 ITState.FirstCond = false;
5111 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005112 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005113 // The instruction must be predicable.
5114 if (!MCID.isPredicable())
5115 return Error(Loc, "instructions in IT block must be predicable");
5116 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5117 unsigned ITCond = bit ? ITState.Cond :
5118 ARMCC::getOppositeCondition(ITState.Cond);
5119 if (Cond != ITCond) {
5120 // Find the condition code Operand to get its SMLoc information.
5121 SMLoc CondLoc;
5122 for (unsigned i = 1; i < Operands.size(); ++i)
5123 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5124 CondLoc = Operands[i]->getStartLoc();
5125 return Error(CondLoc, "incorrect condition in IT block; got '" +
5126 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5127 "', but expected '" +
5128 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5129 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005130 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005131 } else if (isThumbTwo() && MCID.isPredicable() &&
5132 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005133 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5134 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005135 return Error(Loc, "predicated instructions must be in IT block");
5136
Jim Grosbach189610f2011-07-26 18:25:39 +00005137 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005138 case ARM::LDRD:
5139 case ARM::LDRD_PRE:
5140 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005141 case ARM::LDREXD: {
5142 // Rt2 must be Rt + 1.
5143 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5144 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5145 if (Rt2 != Rt + 1)
5146 return Error(Operands[3]->getStartLoc(),
5147 "destination operands must be sequential");
5148 return false;
5149 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005150 case ARM::STRD: {
5151 // Rt2 must be Rt + 1.
5152 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5153 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5154 if (Rt2 != Rt + 1)
5155 return Error(Operands[3]->getStartLoc(),
5156 "source operands must be sequential");
5157 return false;
5158 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005159 case ARM::STRD_PRE:
5160 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005161 case ARM::STREXD: {
5162 // Rt2 must be Rt + 1.
5163 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5164 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5165 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005166 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005167 "source operands must be sequential");
5168 return false;
5169 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005170 case ARM::SBFX:
5171 case ARM::UBFX: {
5172 // width must be in range [1, 32-lsb]
5173 unsigned lsb = Inst.getOperand(2).getImm();
5174 unsigned widthm1 = Inst.getOperand(3).getImm();
5175 if (widthm1 >= 32 - lsb)
5176 return Error(Operands[5]->getStartLoc(),
5177 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005178 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005179 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005180 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005181 // If we're parsing Thumb2, the .w variant is available and handles
5182 // most cases that are normally illegal for a Thumb1 LDM
5183 // instruction. We'll make the transformation in processInstruction()
5184 // if necessary.
5185 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005186 // Thumb LDM instructions are writeback iff the base register is not
5187 // in the register list.
5188 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005189 bool hasWritebackToken =
5190 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5191 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005192 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005193 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005194 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5195 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005196 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005197 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005198 return Error(Operands[2]->getStartLoc(),
5199 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005200 // If we should not have writeback, there must not be a '!'. This is
5201 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005202 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005203 return Error(Operands[3]->getStartLoc(),
5204 "writeback operator '!' not allowed when base register "
5205 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005206
5207 break;
5208 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005209 case ARM::t2LDMIA_UPD: {
5210 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5211 return Error(Operands[4]->getStartLoc(),
5212 "writeback operator '!' not allowed when base register "
5213 "in register list");
5214 break;
5215 }
Jim Grosbach54026372011-11-10 23:17:11 +00005216 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5217 // so only issue a diagnostic for thumb1. The instructions will be
5218 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005219 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005220 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005221 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5222 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005223 return Error(Operands[2]->getStartLoc(),
5224 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005225 break;
5226 }
5227 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005228 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005229 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5230 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005231 return Error(Operands[2]->getStartLoc(),
5232 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005233 break;
5234 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005235 case ARM::tSTMIA_UPD: {
5236 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005237 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005238 return Error(Operands[4]->getStartLoc(),
5239 "registers must be in range r0-r7");
5240 break;
5241 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005242 }
5243
5244 return false;
5245}
5246
Jim Grosbachd7433e22012-01-23 23:45:44 +00005247static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005248 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005249 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005250 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005251 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5252 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5253 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5254 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5255 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5256 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5257 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5258 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5259 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005260
5261 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005262 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5263 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5264 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5265 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5266 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005267
Jim Grosbach7945ead2012-01-24 00:43:12 +00005268 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5269 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5270 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5271 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5272 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005273
Jim Grosbach7945ead2012-01-24 00:43:12 +00005274 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5275 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5276 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5277 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5278 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005279
Jim Grosbach4adb1822012-01-24 00:07:41 +00005280 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005281 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5282 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5283 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5284 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5285 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5286 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5287 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5288 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5289 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5290 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5291 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5292 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5293 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5294 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5295 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005296
Jim Grosbachd7433e22012-01-23 23:45:44 +00005297 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005298 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5299 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5300 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5301 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5302 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5303 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5304 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5305 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5306 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5307 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5308 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5309 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5310 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5311 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5312 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5313 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5314 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5315 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005316
Jim Grosbach88a54de2012-01-24 18:53:13 +00005317 // VST4LN
5318 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5319 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5320 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5321 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5322 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5323 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5324 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5325 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5326 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5327 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5328 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5329 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5330 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5331 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5332 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5333
Jim Grosbach539aab72012-01-24 00:58:13 +00005334 // VST4
5335 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5336 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5337 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5338 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5339 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5340 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5341 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5342 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5343 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5344 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5345 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5346 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5347 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5348 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5349 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5350 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5351 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5352 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005353 }
5354}
5355
Jim Grosbachd7433e22012-01-23 23:45:44 +00005356static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005357 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005358 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005359 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005360 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5361 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5362 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5363 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5364 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5365 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5366 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5367 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5368 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005369
5370 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005371 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5372 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5373 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5374 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5375 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5376 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5377 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5378 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5379 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5380 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5381 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5382 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5383 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5384 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5385 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005386
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005387 // VLD3DUP
5388 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5389 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5390 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5391 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5392 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5393 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5394 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5395 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5396 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5397 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5398 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5399 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5400 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5401 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5402 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5403 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5404 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5405 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5406
Jim Grosbach3a678af2012-01-23 21:53:26 +00005407 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005408 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5409 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5410 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5411 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5412 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5413 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5414 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5415 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5416 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5417 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5418 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5419 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5420 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5421 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5422 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005423
5424 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005425 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5426 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5427 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5428 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5429 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5430 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5431 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5432 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5433 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5434 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5435 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5436 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5437 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5438 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5439 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5440 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5441 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5442 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005443
Jim Grosbache983a132012-01-24 18:37:25 +00005444 // VLD4LN
5445 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5446 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5447 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5448 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5449 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5450 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5451 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5452 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5453 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5454 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5455 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5456 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5457 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5458 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5459 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5460
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005461 // VLD4DUP
5462 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5463 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5464 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5465 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5466 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5467 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5468 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5469 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5470 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5471 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5472 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5473 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5474 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5475 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5476 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5477 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5478 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5479 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5480
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005481 // VLD4
5482 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5483 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5484 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5485 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5486 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5487 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5488 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5489 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5490 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5491 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5492 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5493 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5494 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5495 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5496 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5497 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5498 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5499 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005500 }
5501}
5502
Jim Grosbach83ec8772011-11-10 23:42:14 +00005503bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005504processInstruction(MCInst &Inst,
5505 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5506 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005507 // Aliases for alternate PC+imm syntax of LDR instructions.
5508 case ARM::t2LDRpcrel:
5509 Inst.setOpcode(ARM::t2LDRpci);
5510 return true;
5511 case ARM::t2LDRBpcrel:
5512 Inst.setOpcode(ARM::t2LDRBpci);
5513 return true;
5514 case ARM::t2LDRHpcrel:
5515 Inst.setOpcode(ARM::t2LDRHpci);
5516 return true;
5517 case ARM::t2LDRSBpcrel:
5518 Inst.setOpcode(ARM::t2LDRSBpci);
5519 return true;
5520 case ARM::t2LDRSHpcrel:
5521 Inst.setOpcode(ARM::t2LDRSHpci);
5522 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005523 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005524 case ARM::VST1LNdWB_register_Asm_8:
5525 case ARM::VST1LNdWB_register_Asm_16:
5526 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005527 MCInst TmpInst;
5528 // Shuffle the operands around so the lane index operand is in the
5529 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005530 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005531 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005532 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5533 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5534 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5535 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5536 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5537 TmpInst.addOperand(Inst.getOperand(1)); // lane
5538 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5539 TmpInst.addOperand(Inst.getOperand(6));
5540 Inst = TmpInst;
5541 return true;
5542 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005543
Jim Grosbach8b31f952012-01-23 19:39:08 +00005544 case ARM::VST2LNdWB_register_Asm_8:
5545 case ARM::VST2LNdWB_register_Asm_16:
5546 case ARM::VST2LNdWB_register_Asm_32:
5547 case ARM::VST2LNqWB_register_Asm_16:
5548 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005549 MCInst TmpInst;
5550 // Shuffle the operands around so the lane index operand is in the
5551 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005552 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005553 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005554 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5555 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5556 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5557 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5558 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005559 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5560 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005561 TmpInst.addOperand(Inst.getOperand(1)); // lane
5562 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5563 TmpInst.addOperand(Inst.getOperand(6));
5564 Inst = TmpInst;
5565 return true;
5566 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005567
5568 case ARM::VST3LNdWB_register_Asm_8:
5569 case ARM::VST3LNdWB_register_Asm_16:
5570 case ARM::VST3LNdWB_register_Asm_32:
5571 case ARM::VST3LNqWB_register_Asm_16:
5572 case ARM::VST3LNqWB_register_Asm_32: {
5573 MCInst TmpInst;
5574 // Shuffle the operands around so the lane index operand is in the
5575 // right place.
5576 unsigned Spacing;
5577 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5578 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5579 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5580 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5581 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5582 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5583 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5584 Spacing));
5585 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5586 Spacing * 2));
5587 TmpInst.addOperand(Inst.getOperand(1)); // lane
5588 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5589 TmpInst.addOperand(Inst.getOperand(6));
5590 Inst = TmpInst;
5591 return true;
5592 }
5593
Jim Grosbach88a54de2012-01-24 18:53:13 +00005594 case ARM::VST4LNdWB_register_Asm_8:
5595 case ARM::VST4LNdWB_register_Asm_16:
5596 case ARM::VST4LNdWB_register_Asm_32:
5597 case ARM::VST4LNqWB_register_Asm_16:
5598 case ARM::VST4LNqWB_register_Asm_32: {
5599 MCInst TmpInst;
5600 // Shuffle the operands around so the lane index operand is in the
5601 // right place.
5602 unsigned Spacing;
5603 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5604 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5605 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5606 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5607 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5608 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5609 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5610 Spacing));
5611 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5612 Spacing * 2));
5613 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5614 Spacing * 3));
5615 TmpInst.addOperand(Inst.getOperand(1)); // lane
5616 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5617 TmpInst.addOperand(Inst.getOperand(6));
5618 Inst = TmpInst;
5619 return true;
5620 }
5621
Jim Grosbach8b31f952012-01-23 19:39:08 +00005622 case ARM::VST1LNdWB_fixed_Asm_8:
5623 case ARM::VST1LNdWB_fixed_Asm_16:
5624 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005625 MCInst TmpInst;
5626 // Shuffle the operands around so the lane index operand is in the
5627 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005628 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005629 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005630 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5631 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5632 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5633 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5634 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5635 TmpInst.addOperand(Inst.getOperand(1)); // lane
5636 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5637 TmpInst.addOperand(Inst.getOperand(5));
5638 Inst = TmpInst;
5639 return true;
5640 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005641
Jim Grosbach8b31f952012-01-23 19:39:08 +00005642 case ARM::VST2LNdWB_fixed_Asm_8:
5643 case ARM::VST2LNdWB_fixed_Asm_16:
5644 case ARM::VST2LNdWB_fixed_Asm_32:
5645 case ARM::VST2LNqWB_fixed_Asm_16:
5646 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005647 MCInst TmpInst;
5648 // Shuffle the operands around so the lane index operand is in the
5649 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005650 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005651 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005652 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5653 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5654 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5655 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5656 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005657 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5658 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005659 TmpInst.addOperand(Inst.getOperand(1)); // lane
5660 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5661 TmpInst.addOperand(Inst.getOperand(5));
5662 Inst = TmpInst;
5663 return true;
5664 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005665
5666 case ARM::VST3LNdWB_fixed_Asm_8:
5667 case ARM::VST3LNdWB_fixed_Asm_16:
5668 case ARM::VST3LNdWB_fixed_Asm_32:
5669 case ARM::VST3LNqWB_fixed_Asm_16:
5670 case ARM::VST3LNqWB_fixed_Asm_32: {
5671 MCInst TmpInst;
5672 // Shuffle the operands around so the lane index operand is in the
5673 // right place.
5674 unsigned Spacing;
5675 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5676 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5677 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5678 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5679 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5680 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5681 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5682 Spacing));
5683 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5684 Spacing * 2));
5685 TmpInst.addOperand(Inst.getOperand(1)); // lane
5686 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5687 TmpInst.addOperand(Inst.getOperand(5));
5688 Inst = TmpInst;
5689 return true;
5690 }
5691
Jim Grosbach88a54de2012-01-24 18:53:13 +00005692 case ARM::VST4LNdWB_fixed_Asm_8:
5693 case ARM::VST4LNdWB_fixed_Asm_16:
5694 case ARM::VST4LNdWB_fixed_Asm_32:
5695 case ARM::VST4LNqWB_fixed_Asm_16:
5696 case ARM::VST4LNqWB_fixed_Asm_32: {
5697 MCInst TmpInst;
5698 // Shuffle the operands around so the lane index operand is in the
5699 // right place.
5700 unsigned Spacing;
5701 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5702 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5703 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5704 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5705 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5706 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5707 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5708 Spacing));
5709 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5710 Spacing * 2));
5711 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5712 Spacing * 3));
5713 TmpInst.addOperand(Inst.getOperand(1)); // lane
5714 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5715 TmpInst.addOperand(Inst.getOperand(5));
5716 Inst = TmpInst;
5717 return true;
5718 }
5719
Jim Grosbach8b31f952012-01-23 19:39:08 +00005720 case ARM::VST1LNdAsm_8:
5721 case ARM::VST1LNdAsm_16:
5722 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005723 MCInst TmpInst;
5724 // Shuffle the operands around so the lane index operand is in the
5725 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005726 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005727 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005728 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5729 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5730 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5731 TmpInst.addOperand(Inst.getOperand(1)); // lane
5732 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5733 TmpInst.addOperand(Inst.getOperand(5));
5734 Inst = TmpInst;
5735 return true;
5736 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005737
Jim Grosbach8b31f952012-01-23 19:39:08 +00005738 case ARM::VST2LNdAsm_8:
5739 case ARM::VST2LNdAsm_16:
5740 case ARM::VST2LNdAsm_32:
5741 case ARM::VST2LNqAsm_16:
5742 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005743 MCInst TmpInst;
5744 // Shuffle the operands around so the lane index operand is in the
5745 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005746 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005747 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005748 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5749 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5750 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005751 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5752 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005753 TmpInst.addOperand(Inst.getOperand(1)); // lane
5754 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5755 TmpInst.addOperand(Inst.getOperand(5));
5756 Inst = TmpInst;
5757 return true;
5758 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005759
5760 case ARM::VST3LNdAsm_8:
5761 case ARM::VST3LNdAsm_16:
5762 case ARM::VST3LNdAsm_32:
5763 case ARM::VST3LNqAsm_16:
5764 case ARM::VST3LNqAsm_32: {
5765 MCInst TmpInst;
5766 // Shuffle the operands around so the lane index operand is in the
5767 // right place.
5768 unsigned Spacing;
5769 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5770 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5771 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5772 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5773 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5774 Spacing));
5775 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5776 Spacing * 2));
5777 TmpInst.addOperand(Inst.getOperand(1)); // lane
5778 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5779 TmpInst.addOperand(Inst.getOperand(5));
5780 Inst = TmpInst;
5781 return true;
5782 }
5783
Jim Grosbach88a54de2012-01-24 18:53:13 +00005784 case ARM::VST4LNdAsm_8:
5785 case ARM::VST4LNdAsm_16:
5786 case ARM::VST4LNdAsm_32:
5787 case ARM::VST4LNqAsm_16:
5788 case ARM::VST4LNqAsm_32: {
5789 MCInst TmpInst;
5790 // Shuffle the operands around so the lane index operand is in the
5791 // right place.
5792 unsigned Spacing;
5793 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5794 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5795 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5796 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5797 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5798 Spacing));
5799 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5800 Spacing * 2));
5801 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5802 Spacing * 3));
5803 TmpInst.addOperand(Inst.getOperand(1)); // lane
5804 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5805 TmpInst.addOperand(Inst.getOperand(5));
5806 Inst = TmpInst;
5807 return true;
5808 }
5809
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005810 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005811 case ARM::VLD1LNdWB_register_Asm_8:
5812 case ARM::VLD1LNdWB_register_Asm_16:
5813 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005814 MCInst TmpInst;
5815 // Shuffle the operands around so the lane index operand is in the
5816 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005817 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005818 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005819 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5820 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5821 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5822 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5823 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5824 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5825 TmpInst.addOperand(Inst.getOperand(1)); // lane
5826 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5827 TmpInst.addOperand(Inst.getOperand(6));
5828 Inst = TmpInst;
5829 return true;
5830 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005831
Jim Grosbach8b31f952012-01-23 19:39:08 +00005832 case ARM::VLD2LNdWB_register_Asm_8:
5833 case ARM::VLD2LNdWB_register_Asm_16:
5834 case ARM::VLD2LNdWB_register_Asm_32:
5835 case ARM::VLD2LNqWB_register_Asm_16:
5836 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005837 MCInst TmpInst;
5838 // Shuffle the operands around so the lane index operand is in the
5839 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005840 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005841 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005842 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005843 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5844 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005845 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5846 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5847 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5848 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5849 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005850 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5851 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005852 TmpInst.addOperand(Inst.getOperand(1)); // lane
5853 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5854 TmpInst.addOperand(Inst.getOperand(6));
5855 Inst = TmpInst;
5856 return true;
5857 }
5858
Jim Grosbach3a678af2012-01-23 21:53:26 +00005859 case ARM::VLD3LNdWB_register_Asm_8:
5860 case ARM::VLD3LNdWB_register_Asm_16:
5861 case ARM::VLD3LNdWB_register_Asm_32:
5862 case ARM::VLD3LNqWB_register_Asm_16:
5863 case ARM::VLD3LNqWB_register_Asm_32: {
5864 MCInst TmpInst;
5865 // Shuffle the operands around so the lane index operand is in the
5866 // right place.
5867 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005868 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005869 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5870 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5871 Spacing));
5872 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005873 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005874 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5875 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5876 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5877 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5878 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5879 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5880 Spacing));
5881 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005882 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005883 TmpInst.addOperand(Inst.getOperand(1)); // lane
5884 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5885 TmpInst.addOperand(Inst.getOperand(6));
5886 Inst = TmpInst;
5887 return true;
5888 }
5889
Jim Grosbache983a132012-01-24 18:37:25 +00005890 case ARM::VLD4LNdWB_register_Asm_8:
5891 case ARM::VLD4LNdWB_register_Asm_16:
5892 case ARM::VLD4LNdWB_register_Asm_32:
5893 case ARM::VLD4LNqWB_register_Asm_16:
5894 case ARM::VLD4LNqWB_register_Asm_32: {
5895 MCInst TmpInst;
5896 // Shuffle the operands around so the lane index operand is in the
5897 // right place.
5898 unsigned Spacing;
5899 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5900 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5901 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5902 Spacing));
5903 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5904 Spacing * 2));
5905 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5906 Spacing * 3));
5907 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5908 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5909 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5910 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5911 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5912 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5913 Spacing));
5914 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5915 Spacing * 2));
5916 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5917 Spacing * 3));
5918 TmpInst.addOperand(Inst.getOperand(1)); // lane
5919 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5920 TmpInst.addOperand(Inst.getOperand(6));
5921 Inst = TmpInst;
5922 return true;
5923 }
5924
Jim Grosbach8b31f952012-01-23 19:39:08 +00005925 case ARM::VLD1LNdWB_fixed_Asm_8:
5926 case ARM::VLD1LNdWB_fixed_Asm_16:
5927 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005928 MCInst TmpInst;
5929 // Shuffle the operands around so the lane index operand is in the
5930 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005931 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005932 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005933 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5934 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5935 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5936 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5937 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5938 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5939 TmpInst.addOperand(Inst.getOperand(1)); // lane
5940 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5941 TmpInst.addOperand(Inst.getOperand(5));
5942 Inst = TmpInst;
5943 return true;
5944 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005945
Jim Grosbach8b31f952012-01-23 19:39:08 +00005946 case ARM::VLD2LNdWB_fixed_Asm_8:
5947 case ARM::VLD2LNdWB_fixed_Asm_16:
5948 case ARM::VLD2LNdWB_fixed_Asm_32:
5949 case ARM::VLD2LNqWB_fixed_Asm_16:
5950 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005951 MCInst TmpInst;
5952 // Shuffle the operands around so the lane index operand is in the
5953 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005954 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005955 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005956 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005957 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5958 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005959 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5960 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5961 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5962 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5963 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005964 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5965 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005966 TmpInst.addOperand(Inst.getOperand(1)); // lane
5967 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5968 TmpInst.addOperand(Inst.getOperand(5));
5969 Inst = TmpInst;
5970 return true;
5971 }
5972
Jim Grosbach3a678af2012-01-23 21:53:26 +00005973 case ARM::VLD3LNdWB_fixed_Asm_8:
5974 case ARM::VLD3LNdWB_fixed_Asm_16:
5975 case ARM::VLD3LNdWB_fixed_Asm_32:
5976 case ARM::VLD3LNqWB_fixed_Asm_16:
5977 case ARM::VLD3LNqWB_fixed_Asm_32: {
5978 MCInst TmpInst;
5979 // Shuffle the operands around so the lane index operand is in the
5980 // right place.
5981 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005982 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005983 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5984 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5985 Spacing));
5986 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005987 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005988 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5989 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5990 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5991 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5992 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5993 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5994 Spacing));
5995 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005996 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005997 TmpInst.addOperand(Inst.getOperand(1)); // lane
5998 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5999 TmpInst.addOperand(Inst.getOperand(5));
6000 Inst = TmpInst;
6001 return true;
6002 }
6003
Jim Grosbache983a132012-01-24 18:37:25 +00006004 case ARM::VLD4LNdWB_fixed_Asm_8:
6005 case ARM::VLD4LNdWB_fixed_Asm_16:
6006 case ARM::VLD4LNdWB_fixed_Asm_32:
6007 case ARM::VLD4LNqWB_fixed_Asm_16:
6008 case ARM::VLD4LNqWB_fixed_Asm_32: {
6009 MCInst TmpInst;
6010 // Shuffle the operands around so the lane index operand is in the
6011 // right place.
6012 unsigned Spacing;
6013 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6014 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6015 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6016 Spacing));
6017 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6018 Spacing * 2));
6019 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6020 Spacing * 3));
6021 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6022 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6023 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6024 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6025 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6026 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6027 Spacing));
6028 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6029 Spacing * 2));
6030 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6031 Spacing * 3));
6032 TmpInst.addOperand(Inst.getOperand(1)); // lane
6033 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6034 TmpInst.addOperand(Inst.getOperand(5));
6035 Inst = TmpInst;
6036 return true;
6037 }
6038
Jim Grosbach8b31f952012-01-23 19:39:08 +00006039 case ARM::VLD1LNdAsm_8:
6040 case ARM::VLD1LNdAsm_16:
6041 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006042 MCInst TmpInst;
6043 // Shuffle the operands around so the lane index operand is in the
6044 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006045 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006046 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006047 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6048 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6049 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6050 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6051 TmpInst.addOperand(Inst.getOperand(1)); // lane
6052 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6053 TmpInst.addOperand(Inst.getOperand(5));
6054 Inst = TmpInst;
6055 return true;
6056 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006057
Jim Grosbach8b31f952012-01-23 19:39:08 +00006058 case ARM::VLD2LNdAsm_8:
6059 case ARM::VLD2LNdAsm_16:
6060 case ARM::VLD2LNdAsm_32:
6061 case ARM::VLD2LNqAsm_16:
6062 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006063 MCInst TmpInst;
6064 // Shuffle the operands around so the lane index operand is in the
6065 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006066 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006067 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006068 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006069 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6070 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006071 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6072 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6073 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006074 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6075 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006076 TmpInst.addOperand(Inst.getOperand(1)); // lane
6077 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6078 TmpInst.addOperand(Inst.getOperand(5));
6079 Inst = TmpInst;
6080 return true;
6081 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006082
6083 case ARM::VLD3LNdAsm_8:
6084 case ARM::VLD3LNdAsm_16:
6085 case ARM::VLD3LNdAsm_32:
6086 case ARM::VLD3LNqAsm_16:
6087 case ARM::VLD3LNqAsm_32: {
6088 MCInst TmpInst;
6089 // Shuffle the operands around so the lane index operand is in the
6090 // right place.
6091 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006092 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006093 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6094 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6095 Spacing));
6096 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006097 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006098 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6099 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6100 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6101 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6102 Spacing));
6103 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006104 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006105 TmpInst.addOperand(Inst.getOperand(1)); // lane
6106 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6107 TmpInst.addOperand(Inst.getOperand(5));
6108 Inst = TmpInst;
6109 return true;
6110 }
6111
Jim Grosbache983a132012-01-24 18:37:25 +00006112 case ARM::VLD4LNdAsm_8:
6113 case ARM::VLD4LNdAsm_16:
6114 case ARM::VLD4LNdAsm_32:
6115 case ARM::VLD4LNqAsm_16:
6116 case ARM::VLD4LNqAsm_32: {
6117 MCInst TmpInst;
6118 // Shuffle the operands around so the lane index operand is in the
6119 // right place.
6120 unsigned Spacing;
6121 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6122 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6123 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6124 Spacing));
6125 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6126 Spacing * 2));
6127 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6128 Spacing * 3));
6129 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6130 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6131 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6132 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6133 Spacing));
6134 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6135 Spacing * 2));
6136 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6137 Spacing * 3));
6138 TmpInst.addOperand(Inst.getOperand(1)); // lane
6139 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6140 TmpInst.addOperand(Inst.getOperand(5));
6141 Inst = TmpInst;
6142 return true;
6143 }
6144
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006145 // VLD3DUP single 3-element structure to all lanes instructions.
6146 case ARM::VLD3DUPdAsm_8:
6147 case ARM::VLD3DUPdAsm_16:
6148 case ARM::VLD3DUPdAsm_32:
6149 case ARM::VLD3DUPqAsm_8:
6150 case ARM::VLD3DUPqAsm_16:
6151 case ARM::VLD3DUPqAsm_32: {
6152 MCInst TmpInst;
6153 unsigned Spacing;
6154 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6155 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6156 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6157 Spacing));
6158 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6159 Spacing * 2));
6160 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6161 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6162 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6163 TmpInst.addOperand(Inst.getOperand(4));
6164 Inst = TmpInst;
6165 return true;
6166 }
6167
6168 case ARM::VLD3DUPdWB_fixed_Asm_8:
6169 case ARM::VLD3DUPdWB_fixed_Asm_16:
6170 case ARM::VLD3DUPdWB_fixed_Asm_32:
6171 case ARM::VLD3DUPqWB_fixed_Asm_8:
6172 case ARM::VLD3DUPqWB_fixed_Asm_16:
6173 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6174 MCInst TmpInst;
6175 unsigned Spacing;
6176 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6177 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6178 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6179 Spacing));
6180 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6181 Spacing * 2));
6182 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6183 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6184 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6185 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6186 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6187 TmpInst.addOperand(Inst.getOperand(4));
6188 Inst = TmpInst;
6189 return true;
6190 }
6191
6192 case ARM::VLD3DUPdWB_register_Asm_8:
6193 case ARM::VLD3DUPdWB_register_Asm_16:
6194 case ARM::VLD3DUPdWB_register_Asm_32:
6195 case ARM::VLD3DUPqWB_register_Asm_8:
6196 case ARM::VLD3DUPqWB_register_Asm_16:
6197 case ARM::VLD3DUPqWB_register_Asm_32: {
6198 MCInst TmpInst;
6199 unsigned Spacing;
6200 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6201 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6202 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6203 Spacing));
6204 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6205 Spacing * 2));
6206 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6207 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6208 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6209 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6210 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6211 TmpInst.addOperand(Inst.getOperand(5));
6212 Inst = TmpInst;
6213 return true;
6214 }
6215
Jim Grosbachc387fc62012-01-23 23:20:46 +00006216 // VLD3 multiple 3-element structure instructions.
6217 case ARM::VLD3dAsm_8:
6218 case ARM::VLD3dAsm_16:
6219 case ARM::VLD3dAsm_32:
6220 case ARM::VLD3qAsm_8:
6221 case ARM::VLD3qAsm_16:
6222 case ARM::VLD3qAsm_32: {
6223 MCInst TmpInst;
6224 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006225 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006226 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6227 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6228 Spacing));
6229 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6230 Spacing * 2));
6231 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6232 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6233 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6234 TmpInst.addOperand(Inst.getOperand(4));
6235 Inst = TmpInst;
6236 return true;
6237 }
6238
6239 case ARM::VLD3dWB_fixed_Asm_8:
6240 case ARM::VLD3dWB_fixed_Asm_16:
6241 case ARM::VLD3dWB_fixed_Asm_32:
6242 case ARM::VLD3qWB_fixed_Asm_8:
6243 case ARM::VLD3qWB_fixed_Asm_16:
6244 case ARM::VLD3qWB_fixed_Asm_32: {
6245 MCInst TmpInst;
6246 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006247 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006248 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6249 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6250 Spacing));
6251 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6252 Spacing * 2));
6253 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6254 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6255 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6256 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6257 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6258 TmpInst.addOperand(Inst.getOperand(4));
6259 Inst = TmpInst;
6260 return true;
6261 }
6262
6263 case ARM::VLD3dWB_register_Asm_8:
6264 case ARM::VLD3dWB_register_Asm_16:
6265 case ARM::VLD3dWB_register_Asm_32:
6266 case ARM::VLD3qWB_register_Asm_8:
6267 case ARM::VLD3qWB_register_Asm_16:
6268 case ARM::VLD3qWB_register_Asm_32: {
6269 MCInst TmpInst;
6270 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006271 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006272 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6273 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6274 Spacing));
6275 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6276 Spacing * 2));
6277 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6278 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6279 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6280 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6281 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6282 TmpInst.addOperand(Inst.getOperand(5));
6283 Inst = TmpInst;
6284 return true;
6285 }
6286
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006287 // VLD4DUP single 3-element structure to all lanes instructions.
6288 case ARM::VLD4DUPdAsm_8:
6289 case ARM::VLD4DUPdAsm_16:
6290 case ARM::VLD4DUPdAsm_32:
6291 case ARM::VLD4DUPqAsm_8:
6292 case ARM::VLD4DUPqAsm_16:
6293 case ARM::VLD4DUPqAsm_32: {
6294 MCInst TmpInst;
6295 unsigned Spacing;
6296 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6297 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6298 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6299 Spacing));
6300 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6301 Spacing * 2));
6302 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6303 Spacing * 3));
6304 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6305 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6306 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6307 TmpInst.addOperand(Inst.getOperand(4));
6308 Inst = TmpInst;
6309 return true;
6310 }
6311
6312 case ARM::VLD4DUPdWB_fixed_Asm_8:
6313 case ARM::VLD4DUPdWB_fixed_Asm_16:
6314 case ARM::VLD4DUPdWB_fixed_Asm_32:
6315 case ARM::VLD4DUPqWB_fixed_Asm_8:
6316 case ARM::VLD4DUPqWB_fixed_Asm_16:
6317 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6318 MCInst TmpInst;
6319 unsigned Spacing;
6320 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6321 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6322 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6323 Spacing));
6324 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6325 Spacing * 2));
6326 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6327 Spacing * 3));
6328 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6329 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6330 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6331 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6332 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6333 TmpInst.addOperand(Inst.getOperand(4));
6334 Inst = TmpInst;
6335 return true;
6336 }
6337
6338 case ARM::VLD4DUPdWB_register_Asm_8:
6339 case ARM::VLD4DUPdWB_register_Asm_16:
6340 case ARM::VLD4DUPdWB_register_Asm_32:
6341 case ARM::VLD4DUPqWB_register_Asm_8:
6342 case ARM::VLD4DUPqWB_register_Asm_16:
6343 case ARM::VLD4DUPqWB_register_Asm_32: {
6344 MCInst TmpInst;
6345 unsigned Spacing;
6346 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6347 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6348 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6349 Spacing));
6350 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6351 Spacing * 2));
6352 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6353 Spacing * 3));
6354 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6355 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6356 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6357 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6358 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6359 TmpInst.addOperand(Inst.getOperand(5));
6360 Inst = TmpInst;
6361 return true;
6362 }
6363
6364 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006365 case ARM::VLD4dAsm_8:
6366 case ARM::VLD4dAsm_16:
6367 case ARM::VLD4dAsm_32:
6368 case ARM::VLD4qAsm_8:
6369 case ARM::VLD4qAsm_16:
6370 case ARM::VLD4qAsm_32: {
6371 MCInst TmpInst;
6372 unsigned Spacing;
6373 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6374 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6375 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6376 Spacing));
6377 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6378 Spacing * 2));
6379 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6380 Spacing * 3));
6381 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6382 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6383 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6384 TmpInst.addOperand(Inst.getOperand(4));
6385 Inst = TmpInst;
6386 return true;
6387 }
6388
6389 case ARM::VLD4dWB_fixed_Asm_8:
6390 case ARM::VLD4dWB_fixed_Asm_16:
6391 case ARM::VLD4dWB_fixed_Asm_32:
6392 case ARM::VLD4qWB_fixed_Asm_8:
6393 case ARM::VLD4qWB_fixed_Asm_16:
6394 case ARM::VLD4qWB_fixed_Asm_32: {
6395 MCInst TmpInst;
6396 unsigned Spacing;
6397 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6398 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6399 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6400 Spacing));
6401 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6402 Spacing * 2));
6403 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6404 Spacing * 3));
6405 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6406 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6407 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6408 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6409 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6410 TmpInst.addOperand(Inst.getOperand(4));
6411 Inst = TmpInst;
6412 return true;
6413 }
6414
6415 case ARM::VLD4dWB_register_Asm_8:
6416 case ARM::VLD4dWB_register_Asm_16:
6417 case ARM::VLD4dWB_register_Asm_32:
6418 case ARM::VLD4qWB_register_Asm_8:
6419 case ARM::VLD4qWB_register_Asm_16:
6420 case ARM::VLD4qWB_register_Asm_32: {
6421 MCInst TmpInst;
6422 unsigned Spacing;
6423 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6424 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6425 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6426 Spacing));
6427 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6428 Spacing * 2));
6429 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6430 Spacing * 3));
6431 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6432 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6433 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6434 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6435 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6436 TmpInst.addOperand(Inst.getOperand(5));
6437 Inst = TmpInst;
6438 return true;
6439 }
6440
Jim Grosbachd7433e22012-01-23 23:45:44 +00006441 // VST3 multiple 3-element structure instructions.
6442 case ARM::VST3dAsm_8:
6443 case ARM::VST3dAsm_16:
6444 case ARM::VST3dAsm_32:
6445 case ARM::VST3qAsm_8:
6446 case ARM::VST3qAsm_16:
6447 case ARM::VST3qAsm_32: {
6448 MCInst TmpInst;
6449 unsigned Spacing;
6450 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6451 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6452 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6453 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6454 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6455 Spacing));
6456 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6457 Spacing * 2));
6458 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6459 TmpInst.addOperand(Inst.getOperand(4));
6460 Inst = TmpInst;
6461 return true;
6462 }
6463
6464 case ARM::VST3dWB_fixed_Asm_8:
6465 case ARM::VST3dWB_fixed_Asm_16:
6466 case ARM::VST3dWB_fixed_Asm_32:
6467 case ARM::VST3qWB_fixed_Asm_8:
6468 case ARM::VST3qWB_fixed_Asm_16:
6469 case ARM::VST3qWB_fixed_Asm_32: {
6470 MCInst TmpInst;
6471 unsigned Spacing;
6472 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6473 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6474 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6475 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6476 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6477 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6478 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6479 Spacing));
6480 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6481 Spacing * 2));
6482 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6483 TmpInst.addOperand(Inst.getOperand(4));
6484 Inst = TmpInst;
6485 return true;
6486 }
6487
6488 case ARM::VST3dWB_register_Asm_8:
6489 case ARM::VST3dWB_register_Asm_16:
6490 case ARM::VST3dWB_register_Asm_32:
6491 case ARM::VST3qWB_register_Asm_8:
6492 case ARM::VST3qWB_register_Asm_16:
6493 case ARM::VST3qWB_register_Asm_32: {
6494 MCInst TmpInst;
6495 unsigned Spacing;
6496 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6497 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6498 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6499 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6500 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6501 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6502 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6503 Spacing));
6504 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6505 Spacing * 2));
6506 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6507 TmpInst.addOperand(Inst.getOperand(5));
6508 Inst = TmpInst;
6509 return true;
6510 }
6511
Jim Grosbach539aab72012-01-24 00:58:13 +00006512 // VST4 multiple 3-element structure instructions.
6513 case ARM::VST4dAsm_8:
6514 case ARM::VST4dAsm_16:
6515 case ARM::VST4dAsm_32:
6516 case ARM::VST4qAsm_8:
6517 case ARM::VST4qAsm_16:
6518 case ARM::VST4qAsm_32: {
6519 MCInst TmpInst;
6520 unsigned Spacing;
6521 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6522 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6523 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6524 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6525 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6526 Spacing));
6527 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6528 Spacing * 2));
6529 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6530 Spacing * 3));
6531 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6532 TmpInst.addOperand(Inst.getOperand(4));
6533 Inst = TmpInst;
6534 return true;
6535 }
6536
6537 case ARM::VST4dWB_fixed_Asm_8:
6538 case ARM::VST4dWB_fixed_Asm_16:
6539 case ARM::VST4dWB_fixed_Asm_32:
6540 case ARM::VST4qWB_fixed_Asm_8:
6541 case ARM::VST4qWB_fixed_Asm_16:
6542 case ARM::VST4qWB_fixed_Asm_32: {
6543 MCInst TmpInst;
6544 unsigned Spacing;
6545 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6546 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6547 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6548 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6549 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6550 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6551 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6552 Spacing));
6553 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6554 Spacing * 2));
6555 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6556 Spacing * 3));
6557 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6558 TmpInst.addOperand(Inst.getOperand(4));
6559 Inst = TmpInst;
6560 return true;
6561 }
6562
6563 case ARM::VST4dWB_register_Asm_8:
6564 case ARM::VST4dWB_register_Asm_16:
6565 case ARM::VST4dWB_register_Asm_32:
6566 case ARM::VST4qWB_register_Asm_8:
6567 case ARM::VST4qWB_register_Asm_16:
6568 case ARM::VST4qWB_register_Asm_32: {
6569 MCInst TmpInst;
6570 unsigned Spacing;
6571 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6572 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6573 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6574 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6575 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6576 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6577 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6578 Spacing));
6579 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6580 Spacing * 2));
6581 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6582 Spacing * 3));
6583 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6584 TmpInst.addOperand(Inst.getOperand(5));
6585 Inst = TmpInst;
6586 return true;
6587 }
6588
Jim Grosbach863d2af2011-12-13 22:45:11 +00006589 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006590 case ARM::t2MOVsr:
6591 case ARM::t2MOVSsr: {
6592 // Which instruction to expand to depends on the CCOut operand and
6593 // whether we're in an IT block if the register operands are low
6594 // registers.
6595 bool isNarrow = false;
6596 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6597 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6598 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6599 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6600 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6601 isNarrow = true;
6602 MCInst TmpInst;
6603 unsigned newOpc;
6604 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6605 default: llvm_unreachable("unexpected opcode!");
6606 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6607 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6608 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6609 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6610 }
6611 TmpInst.setOpcode(newOpc);
6612 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6613 if (isNarrow)
6614 TmpInst.addOperand(MCOperand::CreateReg(
6615 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6616 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6617 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6618 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6619 TmpInst.addOperand(Inst.getOperand(5));
6620 if (!isNarrow)
6621 TmpInst.addOperand(MCOperand::CreateReg(
6622 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6623 Inst = TmpInst;
6624 return true;
6625 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006626 case ARM::t2MOVsi:
6627 case ARM::t2MOVSsi: {
6628 // Which instruction to expand to depends on the CCOut operand and
6629 // whether we're in an IT block if the register operands are low
6630 // registers.
6631 bool isNarrow = false;
6632 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6633 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6634 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6635 isNarrow = true;
6636 MCInst TmpInst;
6637 unsigned newOpc;
6638 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6639 default: llvm_unreachable("unexpected opcode!");
6640 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6641 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6642 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6643 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006644 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006645 }
6646 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6647 if (Ammount == 32) Ammount = 0;
6648 TmpInst.setOpcode(newOpc);
6649 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6650 if (isNarrow)
6651 TmpInst.addOperand(MCOperand::CreateReg(
6652 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6653 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006654 if (newOpc != ARM::t2RRX)
6655 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006656 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6657 TmpInst.addOperand(Inst.getOperand(4));
6658 if (!isNarrow)
6659 TmpInst.addOperand(MCOperand::CreateReg(
6660 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6661 Inst = TmpInst;
6662 return true;
6663 }
6664 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006665 case ARM::ASRr:
6666 case ARM::LSRr:
6667 case ARM::LSLr:
6668 case ARM::RORr: {
6669 ARM_AM::ShiftOpc ShiftTy;
6670 switch(Inst.getOpcode()) {
6671 default: llvm_unreachable("unexpected opcode!");
6672 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6673 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6674 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6675 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6676 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006677 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6678 MCInst TmpInst;
6679 TmpInst.setOpcode(ARM::MOVsr);
6680 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6681 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6682 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6683 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6684 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6685 TmpInst.addOperand(Inst.getOperand(4));
6686 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6687 Inst = TmpInst;
6688 return true;
6689 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006690 case ARM::ASRi:
6691 case ARM::LSRi:
6692 case ARM::LSLi:
6693 case ARM::RORi: {
6694 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006695 switch(Inst.getOpcode()) {
6696 default: llvm_unreachable("unexpected opcode!");
6697 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6698 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6699 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6700 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6701 }
6702 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006703 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006704 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6705 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006706 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006707 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006708 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6709 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006710 if (Opc == ARM::MOVsi)
6711 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006712 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6713 TmpInst.addOperand(Inst.getOperand(4));
6714 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6715 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006716 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006717 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006718 case ARM::RRXi: {
6719 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6720 MCInst TmpInst;
6721 TmpInst.setOpcode(ARM::MOVsi);
6722 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6723 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6724 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6725 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6726 TmpInst.addOperand(Inst.getOperand(3));
6727 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6728 Inst = TmpInst;
6729 return true;
6730 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006731 case ARM::t2LDMIA_UPD: {
6732 // If this is a load of a single register, then we should use
6733 // a post-indexed LDR instruction instead, per the ARM ARM.
6734 if (Inst.getNumOperands() != 5)
6735 return false;
6736 MCInst TmpInst;
6737 TmpInst.setOpcode(ARM::t2LDR_POST);
6738 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6739 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6740 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6741 TmpInst.addOperand(MCOperand::CreateImm(4));
6742 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6743 TmpInst.addOperand(Inst.getOperand(3));
6744 Inst = TmpInst;
6745 return true;
6746 }
6747 case ARM::t2STMDB_UPD: {
6748 // If this is a store of a single register, then we should use
6749 // a pre-indexed STR instruction instead, per the ARM ARM.
6750 if (Inst.getNumOperands() != 5)
6751 return false;
6752 MCInst TmpInst;
6753 TmpInst.setOpcode(ARM::t2STR_PRE);
6754 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6755 TmpInst.addOperand(Inst.getOperand(4)); // Rt
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 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006763 case ARM::LDMIA_UPD:
6764 // If this is a load of a single register via a 'pop', then we should use
6765 // a post-indexed LDR instruction instead, per the ARM ARM.
6766 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6767 Inst.getNumOperands() == 5) {
6768 MCInst TmpInst;
6769 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6770 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6771 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6772 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6773 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6774 TmpInst.addOperand(MCOperand::CreateImm(4));
6775 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6776 TmpInst.addOperand(Inst.getOperand(3));
6777 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006778 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006779 }
6780 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006781 case ARM::STMDB_UPD:
6782 // If this is a store of a single register via a 'push', then we should use
6783 // a pre-indexed STR instruction instead, per the ARM ARM.
6784 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6785 Inst.getNumOperands() == 5) {
6786 MCInst TmpInst;
6787 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6788 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6789 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6790 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6791 TmpInst.addOperand(MCOperand::CreateImm(-4));
6792 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6793 TmpInst.addOperand(Inst.getOperand(3));
6794 Inst = TmpInst;
6795 }
6796 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006797 case ARM::t2ADDri12:
6798 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6799 // mnemonic was used (not "addw"), encoding T3 is preferred.
6800 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6801 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6802 break;
6803 Inst.setOpcode(ARM::t2ADDri);
6804 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6805 break;
6806 case ARM::t2SUBri12:
6807 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6808 // mnemonic was used (not "subw"), encoding T3 is preferred.
6809 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6810 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6811 break;
6812 Inst.setOpcode(ARM::t2SUBri);
6813 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6814 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006815 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006816 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6817 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6818 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6819 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006820 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006821 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006822 return true;
6823 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006824 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006825 case ARM::tSUBi8:
6826 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6827 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6828 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6829 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006830 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006831 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006832 return true;
6833 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006834 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006835 case ARM::t2ADDrr: {
6836 // If the destination and first source operand are the same, and
6837 // there's no setting of the flags, use encoding T2 instead of T3.
6838 // Note that this is only for ADD, not SUB. This mirrors the system
6839 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6840 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6841 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006842 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6843 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006844 break;
6845 MCInst TmpInst;
6846 TmpInst.setOpcode(ARM::tADDhirr);
6847 TmpInst.addOperand(Inst.getOperand(0));
6848 TmpInst.addOperand(Inst.getOperand(0));
6849 TmpInst.addOperand(Inst.getOperand(2));
6850 TmpInst.addOperand(Inst.getOperand(3));
6851 TmpInst.addOperand(Inst.getOperand(4));
6852 Inst = TmpInst;
6853 return true;
6854 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006855 case ARM::tB:
6856 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006857 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006858 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006859 return true;
6860 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006861 break;
6862 case ARM::t2B:
6863 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006864 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006865 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006866 return true;
6867 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006868 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006869 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006870 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006871 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006872 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006873 return true;
6874 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006875 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006876 case ARM::tBcc:
6877 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006878 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006879 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006880 return true;
6881 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006882 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006883 case ARM::tLDMIA: {
6884 // If the register list contains any high registers, or if the writeback
6885 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6886 // instead if we're in Thumb2. Otherwise, this should have generated
6887 // an error in validateInstruction().
6888 unsigned Rn = Inst.getOperand(0).getReg();
6889 bool hasWritebackToken =
6890 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6891 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6892 bool listContainsBase;
6893 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6894 (!listContainsBase && !hasWritebackToken) ||
6895 (listContainsBase && hasWritebackToken)) {
6896 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6897 assert (isThumbTwo());
6898 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6899 // If we're switching to the updating version, we need to insert
6900 // the writeback tied operand.
6901 if (hasWritebackToken)
6902 Inst.insert(Inst.begin(),
6903 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006904 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006905 }
6906 break;
6907 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006908 case ARM::tSTMIA_UPD: {
6909 // If the register list contains any high registers, we need to use
6910 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6911 // should have generated an error in validateInstruction().
6912 unsigned Rn = Inst.getOperand(0).getReg();
6913 bool listContainsBase;
6914 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6915 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6916 assert (isThumbTwo());
6917 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006918 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006919 }
6920 break;
6921 }
Jim Grosbach54026372011-11-10 23:17:11 +00006922 case ARM::tPOP: {
6923 bool listContainsBase;
6924 // If the register list contains any high registers, we need to use
6925 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6926 // should have generated an error in validateInstruction().
6927 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006928 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006929 assert (isThumbTwo());
6930 Inst.setOpcode(ARM::t2LDMIA_UPD);
6931 // Add the base register and writeback operands.
6932 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6933 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006934 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006935 }
6936 case ARM::tPUSH: {
6937 bool listContainsBase;
6938 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006939 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006940 assert (isThumbTwo());
6941 Inst.setOpcode(ARM::t2STMDB_UPD);
6942 // Add the base register and writeback operands.
6943 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6944 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006945 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006946 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006947 case ARM::t2MOVi: {
6948 // If we can use the 16-bit encoding and the user didn't explicitly
6949 // request the 32-bit variant, transform it here.
6950 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6951 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006952 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6953 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6954 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006955 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6956 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6957 // The operands aren't in the same order for tMOVi8...
6958 MCInst TmpInst;
6959 TmpInst.setOpcode(ARM::tMOVi8);
6960 TmpInst.addOperand(Inst.getOperand(0));
6961 TmpInst.addOperand(Inst.getOperand(4));
6962 TmpInst.addOperand(Inst.getOperand(1));
6963 TmpInst.addOperand(Inst.getOperand(2));
6964 TmpInst.addOperand(Inst.getOperand(3));
6965 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006966 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006967 }
6968 break;
6969 }
6970 case ARM::t2MOVr: {
6971 // If we can use the 16-bit encoding and the user didn't explicitly
6972 // request the 32-bit variant, transform it here.
6973 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6974 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6975 Inst.getOperand(2).getImm() == ARMCC::AL &&
6976 Inst.getOperand(4).getReg() == ARM::CPSR &&
6977 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6978 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6979 // The operands aren't the same for tMOV[S]r... (no cc_out)
6980 MCInst TmpInst;
6981 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6982 TmpInst.addOperand(Inst.getOperand(0));
6983 TmpInst.addOperand(Inst.getOperand(1));
6984 TmpInst.addOperand(Inst.getOperand(2));
6985 TmpInst.addOperand(Inst.getOperand(3));
6986 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006987 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006988 }
6989 break;
6990 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006991 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006992 case ARM::t2SXTB:
6993 case ARM::t2UXTH:
6994 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006995 // If we can use the 16-bit encoding and the user didn't explicitly
6996 // request the 32-bit variant, transform it here.
6997 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6998 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6999 Inst.getOperand(2).getImm() == 0 &&
7000 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7001 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007002 unsigned NewOpc;
7003 switch (Inst.getOpcode()) {
7004 default: llvm_unreachable("Illegal opcode!");
7005 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7006 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7007 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7008 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7009 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007010 // The operands aren't the same for thumb1 (no rotate operand).
7011 MCInst TmpInst;
7012 TmpInst.setOpcode(NewOpc);
7013 TmpInst.addOperand(Inst.getOperand(0));
7014 TmpInst.addOperand(Inst.getOperand(1));
7015 TmpInst.addOperand(Inst.getOperand(3));
7016 TmpInst.addOperand(Inst.getOperand(4));
7017 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007018 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007019 }
7020 break;
7021 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007022 case ARM::MOVsi: {
7023 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7024 if (SOpc == ARM_AM::rrx) return false;
7025 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7026 // Shifting by zero is accepted as a vanilla 'MOVr'
7027 MCInst TmpInst;
7028 TmpInst.setOpcode(ARM::MOVr);
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 TmpInst.addOperand(Inst.getOperand(5));
7034 Inst = TmpInst;
7035 return true;
7036 }
7037 return false;
7038 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007039 case ARM::ANDrsi:
7040 case ARM::ORRrsi:
7041 case ARM::EORrsi:
7042 case ARM::BICrsi:
7043 case ARM::SUBrsi:
7044 case ARM::ADDrsi: {
7045 unsigned newOpc;
7046 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7047 if (SOpc == ARM_AM::rrx) return false;
7048 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007049 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007050 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7051 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7052 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7053 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7054 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7055 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7056 }
7057 // If the shift is by zero, use the non-shifted instruction definition.
7058 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7059 MCInst TmpInst;
7060 TmpInst.setOpcode(newOpc);
7061 TmpInst.addOperand(Inst.getOperand(0));
7062 TmpInst.addOperand(Inst.getOperand(1));
7063 TmpInst.addOperand(Inst.getOperand(2));
7064 TmpInst.addOperand(Inst.getOperand(4));
7065 TmpInst.addOperand(Inst.getOperand(5));
7066 TmpInst.addOperand(Inst.getOperand(6));
7067 Inst = TmpInst;
7068 return true;
7069 }
7070 return false;
7071 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007072 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007073 case ARM::t2IT: {
7074 // The mask bits for all but the first condition are represented as
7075 // the low bit of the condition code value implies 't'. We currently
7076 // always have 1 implies 't', so XOR toggle the bits if the low bit
7077 // of the condition code is zero. The encoding also expects the low
7078 // bit of the condition to be encoded as bit 4 of the mask operand,
7079 // so mask that in if needed
7080 MCOperand &MO = Inst.getOperand(1);
7081 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007082 unsigned OrigMask = Mask;
7083 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007084 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007085 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7086 for (unsigned i = 3; i != TZ; --i)
7087 Mask ^= 1 << i;
7088 } else
7089 Mask |= 0x10;
7090 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007091
7092 // Set up the IT block state according to the IT instruction we just
7093 // matched.
7094 assert(!inITBlock() && "nested IT blocks?!");
7095 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7096 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7097 ITState.CurPosition = 0;
7098 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007099 break;
7100 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007101 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007102 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007103}
7104
Jim Grosbach47a0d522011-08-16 20:45:50 +00007105unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7106 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7107 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007108 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007109 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007110 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7111 assert(MCID.hasOptionalDef() &&
7112 "optionally flag setting instruction missing optional def operand");
7113 assert(MCID.NumOperands == Inst.getNumOperands() &&
7114 "operand count mismatch!");
7115 // Find the optional-def operand (cc_out).
7116 unsigned OpNo;
7117 for (OpNo = 0;
7118 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7119 ++OpNo)
7120 ;
7121 // If we're parsing Thumb1, reject it completely.
7122 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7123 return Match_MnemonicFail;
7124 // If we're parsing Thumb2, which form is legal depends on whether we're
7125 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007126 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7127 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007128 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007129 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7130 inITBlock())
7131 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007132 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007133 // Some high-register supporting Thumb1 encodings only allow both registers
7134 // to be from r0-r7 when in Thumb2.
7135 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7136 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7137 isARMLowRegister(Inst.getOperand(2).getReg()))
7138 return Match_RequiresThumb2;
7139 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007140 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007141 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7142 isARMLowRegister(Inst.getOperand(1).getReg()))
7143 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007144 return Match_Success;
7145}
7146
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007147bool ARMAsmParser::
7148MatchAndEmitInstruction(SMLoc IDLoc,
7149 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7150 MCStreamer &Out) {
7151 MCInst Inst;
7152 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007153 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007154 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007155 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007156 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007157 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007158 // Context sensitive operand constraints aren't handled by the matcher,
7159 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007160 if (validateInstruction(Inst, Operands)) {
7161 // Still progress the IT block, otherwise one wrong condition causes
7162 // nasty cascading errors.
7163 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007164 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007165 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007166
Jim Grosbachf8fce712011-08-11 17:35:48 +00007167 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007168 // encoding is selected. Loop on it while changes happen so the
7169 // individual transformations can chain off each other. E.g.,
7170 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7171 while (processInstruction(Inst, Operands))
7172 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007173
Jim Grosbacha1109882011-09-02 23:22:08 +00007174 // Only move forward at the very end so that everything in validate
7175 // and process gets a consistent answer about whether we're in an IT
7176 // block.
7177 forwardITPosition();
7178
Jim Grosbach74423e32012-01-25 19:52:01 +00007179 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7180 // doesn't actually encode.
7181 if (Inst.getOpcode() == ARM::ITasm)
7182 return false;
7183
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007184 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007185 Out.EmitInstruction(Inst);
7186 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007187 case Match_MissingFeature:
7188 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7189 return true;
7190 case Match_InvalidOperand: {
7191 SMLoc ErrorLoc = IDLoc;
7192 if (ErrorInfo != ~0U) {
7193 if (ErrorInfo >= Operands.size())
7194 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007195
Chris Lattnere73d4f82010-10-28 21:41:58 +00007196 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7197 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7198 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007199
Chris Lattnere73d4f82010-10-28 21:41:58 +00007200 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007201 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007202 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007203 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007204 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007205 // The converter function will have already emited a diagnostic.
7206 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007207 case Match_RequiresNotITBlock:
7208 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007209 case Match_RequiresITBlock:
7210 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007211 case Match_RequiresV6:
7212 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7213 case Match_RequiresThumb2:
7214 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007215 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007216
Eric Christopherc223e2b2010-10-29 09:26:59 +00007217 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007218}
7219
Jim Grosbach1355cf12011-07-26 17:10:22 +00007220/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007221bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7222 StringRef IDVal = DirectiveID.getIdentifier();
7223 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007224 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007225 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007226 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007227 else if (IDVal == ".arm")
7228 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007229 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007230 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007231 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007232 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007233 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007234 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007235 else if (IDVal == ".unreq")
7236 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007237 else if (IDVal == ".arch")
7238 return parseDirectiveArch(DirectiveID.getLoc());
7239 else if (IDVal == ".eabi_attribute")
7240 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007241 return true;
7242}
7243
Jim Grosbach1355cf12011-07-26 17:10:22 +00007244/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007245/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007246bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007247 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7248 for (;;) {
7249 const MCExpr *Value;
7250 if (getParser().ParseExpression(Value))
7251 return true;
7252
Chris Lattneraaec2052010-01-19 19:46:13 +00007253 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007254
7255 if (getLexer().is(AsmToken::EndOfStatement))
7256 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007257
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007258 // FIXME: Improve diagnostic.
7259 if (getLexer().isNot(AsmToken::Comma))
7260 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007261 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007262 }
7263 }
7264
Sean Callananb9a25b72010-01-19 20:27:46 +00007265 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007266 return false;
7267}
7268
Jim Grosbach1355cf12011-07-26 17:10:22 +00007269/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007270/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007271bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007272 if (getLexer().isNot(AsmToken::EndOfStatement))
7273 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007274 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007275
Jim Grosbach9a70df92011-12-07 18:04:19 +00007276 if (!isThumb())
7277 SwitchMode();
7278 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7279 return false;
7280}
7281
7282/// parseDirectiveARM
7283/// ::= .arm
7284bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7285 if (getLexer().isNot(AsmToken::EndOfStatement))
7286 return Error(L, "unexpected token in directive");
7287 Parser.Lex();
7288
7289 if (isThumb())
7290 SwitchMode();
7291 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007292 return false;
7293}
7294
Jim Grosbach1355cf12011-07-26 17:10:22 +00007295/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007296/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007297bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007298 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7299 bool isMachO = MAI.hasSubsectionsViaSymbols();
7300 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007301 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007302
Jim Grosbachde4d8392011-12-21 22:30:16 +00007303 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007304 // ELF doesn't
7305 if (isMachO) {
7306 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007307 if (Tok.isNot(AsmToken::EndOfStatement)) {
7308 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7309 return Error(L, "unexpected token in .thumb_func directive");
7310 Name = Tok.getIdentifier();
7311 Parser.Lex(); // Consume the identifier token.
7312 needFuncName = false;
7313 }
Rafael Espindola64695402011-05-16 16:17:21 +00007314 }
7315
Jim Grosbachde4d8392011-12-21 22:30:16 +00007316 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007317 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007318
7319 // Eat the end of statement and any blank lines that follow.
7320 while (getLexer().is(AsmToken::EndOfStatement))
7321 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007322
Rafael Espindola64695402011-05-16 16:17:21 +00007323 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007324 // We really should be checking the next symbol definition even if there's
7325 // stuff in between.
7326 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007327 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007328 }
7329
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007330 // Mark symbol as a thumb symbol.
7331 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7332 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007333 return false;
7334}
7335
Jim Grosbach1355cf12011-07-26 17:10:22 +00007336/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007337/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007338bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007339 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007340 if (Tok.isNot(AsmToken::Identifier))
7341 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007342 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007343 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007344 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007345 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007346 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007347 else
7348 return Error(L, "unrecognized syntax mode in .syntax directive");
7349
7350 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007351 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007352 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007353
7354 // TODO tell the MC streamer the mode
7355 // getParser().getStreamer().Emit???();
7356 return false;
7357}
7358
Jim Grosbach1355cf12011-07-26 17:10:22 +00007359/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007360/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007361bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007362 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007363 if (Tok.isNot(AsmToken::Integer))
7364 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007365 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007366 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007367 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007368 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007369 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007370 else
7371 return Error(L, "invalid operand to .code directive");
7372
7373 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007374 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007375 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007376
Evan Cheng32869202011-07-08 22:36:29 +00007377 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007378 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007379 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007380 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007381 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007382 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007383 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007384 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007385 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007386
Kevin Enderby515d5092009-10-15 20:48:48 +00007387 return false;
7388}
7389
Jim Grosbacha39cda72011-12-14 02:16:11 +00007390/// parseDirectiveReq
7391/// ::= name .req registername
7392bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7393 Parser.Lex(); // Eat the '.req' token.
7394 unsigned Reg;
7395 SMLoc SRegLoc, ERegLoc;
7396 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7397 Parser.EatToEndOfStatement();
7398 return Error(SRegLoc, "register name expected");
7399 }
7400
7401 // Shouldn't be anything else.
7402 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7403 Parser.EatToEndOfStatement();
7404 return Error(Parser.getTok().getLoc(),
7405 "unexpected input in .req directive.");
7406 }
7407
7408 Parser.Lex(); // Consume the EndOfStatement
7409
7410 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7411 return Error(SRegLoc, "redefinition of '" + Name +
7412 "' does not match original.");
7413
7414 return false;
7415}
7416
7417/// parseDirectiveUneq
7418/// ::= .unreq registername
7419bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7420 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7421 Parser.EatToEndOfStatement();
7422 return Error(L, "unexpected input in .unreq directive.");
7423 }
7424 RegisterReqs.erase(Parser.getTok().getIdentifier());
7425 Parser.Lex(); // Eat the identifier.
7426 return false;
7427}
7428
Jason W Kimd7c9e082011-12-20 17:38:12 +00007429/// parseDirectiveArch
7430/// ::= .arch token
7431bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7432 return true;
7433}
7434
7435/// parseDirectiveEabiAttr
7436/// ::= .eabi_attribute int, int
7437bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7438 return true;
7439}
7440
Sean Callanan90b70972010-04-07 20:29:34 +00007441extern "C" void LLVMInitializeARMAsmLexer();
7442
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007443/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007444extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007445 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7446 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007447 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007448}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007449
Chris Lattner0692ee62010-09-06 19:11:01 +00007450#define GET_REGISTER_MATCHER
7451#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007452#include "ARMGenAsmMatcher.inc"