blob: b3e7e45b8c0d10ee160ae644b72087782110cba5 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
Jim Grosbach28f08c92012-03-05 19:33:30 +000047 const MCRegisterInfo *MRI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000048
Jim Grosbacha39cda72011-12-14 02:16:11 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<unsigned> RegisterReqs;
51
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000052 struct {
53 ARMCC::CondCodes Cond; // Condition for IT block.
54 unsigned Mask:4; // Condition mask for instructions.
55 // Starting at first 1 (from lsb).
56 // '1' condition as indicated in IT.
57 // '0' inverse of condition (else).
58 // Count of instructions in IT block is
59 // 4 - trailingzeroes(mask)
60
61 bool FirstCond; // Explicit flag for when we're parsing the
62 // First instruction in the IT block. It's
63 // implied in the mask, so needs special
64 // handling.
65
66 unsigned CurPosition; // Current position in parsing of IT
67 // block. In range [0,3]. Initialized
68 // according to count of instructions in block.
69 // ~0U if no active IT block.
70 } ITState;
71 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000072 void forwardITPosition() {
73 if (!inITBlock()) return;
74 // Move to the next instruction in the IT block, if there is one. If not,
75 // mark the block as done.
76 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77 if (++ITState.CurPosition == 5 - TZ)
78 ITState.CurPosition = ~0U; // Done with the IT block after this.
79 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000080
81
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000083 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84
85 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000086 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
87
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 int tryParseRegister();
89 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000090 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000091 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000092 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000093 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
94 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000095 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
96 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 bool parseDirectiveWord(unsigned Size, SMLoc L);
98 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000099 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 bool parseDirectiveThumbFunc(SMLoc L);
101 bool parseDirectiveCode(SMLoc L);
102 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000103 bool parseDirectiveReq(StringRef Name, SMLoc L);
104 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000105 bool parseDirectiveArch(SMLoc L);
106 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000107
Jim Grosbach1355cf12011-07-26 17:10:22 +0000108 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000109 bool &CarrySetting, unsigned &ProcessorIMod,
110 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000111 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000112 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000113
Evan Chengebdeeab2011-07-08 01:53:10 +0000114 bool isThumb() const {
115 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000116 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000118 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000119 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000120 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000121 bool isThumbTwo() const {
122 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
123 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000124 bool hasV6Ops() const {
125 return STI.getFeatureBits() & ARM::HasV6Ops;
126 }
James Molloyacad68d2011-09-28 14:21:38 +0000127 bool hasV7Ops() const {
128 return STI.getFeatureBits() & ARM::HasV7Ops;
129 }
Evan Cheng32869202011-07-08 22:36:29 +0000130 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000131 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
132 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000133 }
James Molloyacad68d2011-09-28 14:21:38 +0000134 bool isMClass() const {
135 return STI.getFeatureBits() & ARM::FeatureMClass;
136 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000137
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000138 /// @name Auto-generated Match Functions
139 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000140
Chris Lattner0692ee62010-09-06 19:11:01 +0000141#define GET_ASSEMBLER_HEADER
142#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 /// }
145
Jim Grosbach89df9962011-08-26 21:43:41 +0000146 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000149 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000151 OperandMatchResultTy parseCoprocOptionOperand(
152 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000153 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000155 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000157 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000159 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
160 StringRef Op, int Low, int High);
161 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
162 return parsePKHImm(O, "lsl", 0, 31);
163 }
164 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
165 return parsePKHImm(O, "asr", 1, 32);
166 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000167 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000168 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000169 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000170 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000171 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000172 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000173 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000174 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000175 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000176
177 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000178 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
180 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000182 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000184 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000186 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000188 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000190 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000192 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000194 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000196 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
198 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
200 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000204 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000206 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000208 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000210 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000212 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
214 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000216 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
218 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000220
221 bool validateInstruction(MCInst &Inst,
222 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000223 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000224 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000225 bool shouldOmitCCOutOperand(StringRef Mnemonic,
226 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000227
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000228public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000229 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000230 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000231 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000232 Match_RequiresV6,
233 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000234 };
235
Evan Chengffc0e732011-07-09 05:47:46 +0000236 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000237 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000238 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000239
Jim Grosbach28f08c92012-03-05 19:33:30 +0000240 // Cache the MCRegisterInfo.
241 MRI = &getContext().getRegisterInfo();
242
Evan Chengebdeeab2011-07-08 01:53:10 +0000243 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000244 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000245
246 // Not in an ITBlock to start with.
247 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000248 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000249
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 // Implementation of the MCTargetAsmParser interface:
251 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
252 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000253 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool ParseDirective(AsmToken DirectiveID);
255
Jim Grosbach47a0d522011-08-16 20:45:50 +0000256 unsigned checkTargetMatchPredicate(MCInst &Inst);
257
Jim Grosbach1355cf12011-07-26 17:10:22 +0000258 bool MatchAndEmitInstruction(SMLoc IDLoc,
259 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
260 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000261};
Jim Grosbach16c74252010-10-29 14:46:02 +0000262} // end anonymous namespace
263
Chris Lattner3a697562010-10-28 17:20:03 +0000264namespace {
265
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000266/// ARMOperand - Instances of this class represent a parsed ARM machine
267/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000268class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000269 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000270 k_CondCode,
271 k_CCOut,
272 k_ITCondMask,
273 k_CoprocNum,
274 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000275 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000276 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000277 k_MemBarrierOpt,
278 k_Memory,
279 k_PostIndexRegister,
280 k_MSRMask,
281 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000282 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000283 k_Register,
284 k_RegisterList,
285 k_DPRRegisterList,
286 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000287 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000288 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000289 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000290 k_ShiftedRegister,
291 k_ShiftedImmediate,
292 k_ShifterImmediate,
293 k_RotateImmediate,
294 k_BitfieldDescriptor,
295 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296 } Kind;
297
Sean Callanan76264762010-04-02 22:27:05 +0000298 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000299 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000300
301 union {
302 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000303 ARMCC::CondCodes Val;
304 } CC;
305
306 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000307 unsigned Val;
308 } Cop;
309
310 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000311 unsigned Val;
312 } CoprocOption;
313
314 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000315 unsigned Mask:4;
316 } ITMask;
317
318 struct {
319 ARM_MB::MemBOpt Val;
320 } MBOpt;
321
322 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000323 ARM_PROC::IFlags Val;
324 } IFlags;
325
326 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000327 unsigned Val;
328 } MMask;
329
330 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000331 const char *Data;
332 unsigned Length;
333 } Tok;
334
335 struct {
336 unsigned RegNum;
337 } Reg;
338
Jim Grosbach862019c2011-10-18 23:02:30 +0000339 // A vector register list is a sequential list of 1 to 4 registers.
340 struct {
341 unsigned RegNum;
342 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000343 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000344 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000345 } VectorList;
346
Bill Wendling8155e5b2010-11-06 22:19:43 +0000347 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000348 unsigned Val;
349 } VectorIndex;
350
351 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000352 const MCExpr *Val;
353 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000354
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000355 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000356 struct {
357 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000358 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
359 // was specified.
360 const MCConstantExpr *OffsetImm; // Offset immediate value
361 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
362 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000363 unsigned ShiftImm; // shift for OffsetReg.
364 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000365 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000367 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000368
369 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000370 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000371 bool isAdd;
372 ARM_AM::ShiftOpc ShiftTy;
373 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000374 } PostIdxReg;
375
376 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000377 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000378 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000379 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000380 struct {
381 ARM_AM::ShiftOpc ShiftTy;
382 unsigned SrcReg;
383 unsigned ShiftReg;
384 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000385 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000386 struct {
387 ARM_AM::ShiftOpc ShiftTy;
388 unsigned SrcReg;
389 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000390 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000391 struct {
392 unsigned Imm;
393 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000394 struct {
395 unsigned LSB;
396 unsigned Width;
397 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000398 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000399
Bill Wendling146018f2010-11-06 21:42:12 +0000400 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
401public:
Sean Callanan76264762010-04-02 22:27:05 +0000402 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
403 Kind = o.Kind;
404 StartLoc = o.StartLoc;
405 EndLoc = o.EndLoc;
406 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000407 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000408 CC = o.CC;
409 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000410 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000411 ITMask = o.ITMask;
412 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000414 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_CCOut:
417 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000418 Reg = o.Reg;
419 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000420 case k_RegisterList:
421 case k_DPRRegisterList:
422 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000423 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000424 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000425 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000426 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000427 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000428 VectorList = o.VectorList;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_CoprocNum:
431 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000432 Cop = o.Cop;
433 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000434 case k_CoprocOption:
435 CoprocOption = o.CoprocOption;
436 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000437 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000438 Imm = o.Imm;
439 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000440 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000441 MBOpt = o.MBOpt;
442 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000443 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000444 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000447 PostIdxReg = o.PostIdxReg;
448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000450 MMask = o.MMask;
451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000453 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000456 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000457 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000458 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000459 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000460 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000462 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000463 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000464 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000465 RotImm = o.RotImm;
466 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000468 Bitfield = o.Bitfield;
469 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000470 case k_VectorIndex:
471 VectorIndex = o.VectorIndex;
472 break;
Sean Callanan76264762010-04-02 22:27:05 +0000473 }
474 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000475
Sean Callanan76264762010-04-02 22:27:05 +0000476 /// getStartLoc - Get the location of the first token of this operand.
477 SMLoc getStartLoc() const { return StartLoc; }
478 /// getEndLoc - Get the location of the last token of this operand.
479 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000480
Daniel Dunbar8462b302010-08-11 06:36:53 +0000481 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000483 return CC.Val;
484 }
485
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000486 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000487 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000488 return Cop.Val;
489 }
490
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000491 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000493 return StringRef(Tok.Data, Tok.Length);
494 }
495
496 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000498 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000499 }
500
Bill Wendling5fa22a12010-11-09 23:28:44 +0000501 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000502 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
503 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000504 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000505 }
506
Kevin Enderbycfe07242009-10-13 22:19:02 +0000507 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000508 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000509 return Imm.Val;
510 }
511
Jim Grosbach460a9052011-10-07 23:56:00 +0000512 unsigned getVectorIndex() const {
513 assert(Kind == k_VectorIndex && "Invalid access!");
514 return VectorIndex.Val;
515 }
516
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000517 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000518 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000519 return MBOpt.Val;
520 }
521
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000522 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000523 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000524 return IFlags.Val;
525 }
526
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000527 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000529 return MMask.Val;
530 }
531
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 bool isCoprocNum() const { return Kind == k_CoprocNum; }
533 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000534 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000535 bool isCondCode() const { return Kind == k_CondCode; }
536 bool isCCOut() const { return Kind == k_CCOut; }
537 bool isITMask() const { return Kind == k_ITCondMask; }
538 bool isITCondCode() const { return Kind == k_CondCode; }
539 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000540 bool isFPImm() const {
541 if (!isImm()) return false;
542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
543 if (!CE) return false;
544 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
545 return Val != -1;
546 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000547 bool isFBits16() const {
548 if (!isImm()) return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return Value >= 0 && Value <= 16;
553 }
554 bool isFBits32() const {
555 if (!isImm()) return false;
556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
557 if (!CE) return false;
558 int64_t Value = CE->getValue();
559 return Value >= 1 && Value <= 32;
560 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000561 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000562 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000563 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
564 if (!CE) return false;
565 int64_t Value = CE->getValue();
566 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
567 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000568 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000569 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
571 if (!CE) return false;
572 int64_t Value = CE->getValue();
573 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
574 }
575 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000576 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
581 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000582 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000583 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 256;
588 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000589 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000590 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
592 if (!CE) return false;
593 int64_t Value = CE->getValue();
594 return Value >= 0 && Value < 2;
595 }
596 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000597 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 if (!CE) return false;
600 int64_t Value = CE->getValue();
601 return Value >= 0 && Value < 4;
602 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000603 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000604 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value >= 0 && Value < 8;
609 }
610 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000611 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
613 if (!CE) return false;
614 int64_t Value = CE->getValue();
615 return Value >= 0 && Value < 16;
616 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000617 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000618 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000619 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
620 if (!CE) return false;
621 int64_t Value = CE->getValue();
622 return Value >= 0 && Value < 32;
623 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000624 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000625 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
627 if (!CE) return false;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 64;
630 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000631 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000632 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000639 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return Value == 16;
644 }
645 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000646 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value == 32;
651 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000652 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000653 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
655 if (!CE) return false;
656 int64_t Value = CE->getValue();
657 return Value > 0 && Value <= 8;
658 }
659 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000660 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000661 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
662 if (!CE) return false;
663 int64_t Value = CE->getValue();
664 return Value > 0 && Value <= 16;
665 }
666 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000667 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000668 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
669 if (!CE) return false;
670 int64_t Value = CE->getValue();
671 return Value > 0 && Value <= 32;
672 }
673 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000674 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
676 if (!CE) return false;
677 int64_t Value = CE->getValue();
678 return Value > 0 && Value <= 64;
679 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000680 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000681 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return Value > 0 && Value < 8;
686 }
687 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000688 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 16;
693 }
694 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000695 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000696 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
697 if (!CE) return false;
698 int64_t Value = CE->getValue();
699 return Value > 0 && Value < 32;
700 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000701 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000702 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000703 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
704 if (!CE) return false;
705 int64_t Value = CE->getValue();
706 return Value > 0 && Value < 17;
707 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000708 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000709 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000710 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
711 if (!CE) return false;
712 int64_t Value = CE->getValue();
713 return Value > 0 && Value < 33;
714 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000715 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000716 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000717 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
718 if (!CE) return false;
719 int64_t Value = CE->getValue();
720 return Value >= 0 && Value < 33;
721 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000722 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000723 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000724 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
725 if (!CE) return false;
726 int64_t Value = CE->getValue();
727 return Value >= 0 && Value < 65536;
728 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000729 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000730 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 // If it's not a constant expression, it'll generate a fixup and be
733 // handled later.
734 if (!CE) return true;
735 int64_t Value = CE->getValue();
736 return Value >= 0 && Value < 65536;
737 }
Jim Grosbached838482011-07-26 16:24:27 +0000738 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000739 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
741 if (!CE) return false;
742 int64_t Value = CE->getValue();
743 return Value >= 0 && Value <= 0xffffff;
744 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000745 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000746 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value > 0 && Value < 33;
751 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000752 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000753 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000754 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
755 if (!CE) return false;
756 int64_t Value = CE->getValue();
757 return Value >= 0 && Value < 32;
758 }
759 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000760 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 if (!CE) return false;
763 int64_t Value = CE->getValue();
764 return Value > 0 && Value <= 32;
765 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000766 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000767 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000768 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
769 if (!CE) return false;
770 int64_t Value = CE->getValue();
771 return ARM_AM::getSOImmVal(Value) != -1;
772 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000773 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000774 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000775 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
776 if (!CE) return false;
777 int64_t Value = CE->getValue();
778 return ARM_AM::getSOImmVal(~Value) != -1;
779 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000780 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000781 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000782 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
783 if (!CE) return false;
784 int64_t Value = CE->getValue();
785 return ARM_AM::getSOImmVal(-Value) != -1;
786 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000787 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000788 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000789 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
790 if (!CE) return false;
791 int64_t Value = CE->getValue();
792 return ARM_AM::getT2SOImmVal(Value) != -1;
793 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000794 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000795 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000796 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
797 if (!CE) return false;
798 int64_t Value = CE->getValue();
799 return ARM_AM::getT2SOImmVal(~Value) != -1;
800 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000801 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000802 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getT2SOImmVal(-Value) != -1;
807 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000808 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000809 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000810 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
811 if (!CE) return false;
812 int64_t Value = CE->getValue();
813 return Value == 1 || Value == 0;
814 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000815 bool isReg() const { return Kind == k_Register; }
816 bool isRegList() const { return Kind == k_RegisterList; }
817 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
818 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
819 bool isToken() const { return Kind == k_Token; }
820 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
821 bool isMemory() const { return Kind == k_Memory; }
822 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
823 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
824 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
825 bool isRotImm() const { return Kind == k_RotateImmediate; }
826 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
827 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000828 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000829 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000830 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000832 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000833 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000834 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000835 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
836 (alignOK || Memory.Alignment == 0);
837 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000838 bool isMemPCRelImm12() const {
839 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
840 return false;
841 // Base register must be PC.
842 if (Memory.BaseRegNum != ARM::PC)
843 return false;
844 // Immediate offset in range [-4095, 4095].
845 if (!Memory.OffsetImm) return true;
846 int64_t Val = Memory.OffsetImm->getValue();
847 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
848 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 bool isAlignedMemory() const {
850 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000851 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000853 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000854 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000856 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000857 if (!Memory.OffsetImm) return true;
858 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000860 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000861 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000862 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000863 // Immediate offset in range [-4095, 4095].
864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
865 if (!CE) return false;
866 int64_t Val = CE->getValue();
867 return Val > -4096 && Val < 4096;
868 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000869 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000870 // If we have an immediate that's not a constant, treat it as a label
871 // reference needing a fixup. If it is a constant, it's something else
872 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000873 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000874 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000875 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000878 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000880 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (!Memory.OffsetImm) return true;
882 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 return Val > -256 && Val < 256;
884 }
885 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000886 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000887 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000888 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000889 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
890 // Immediate offset in range [-255, 255].
891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
892 if (!CE) return false;
893 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000894 // Special case, #-0 is INT32_MIN.
895 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000896 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000897 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000898 // If we have an immediate that's not a constant, treat it as a label
899 // reference needing a fixup. If it is a constant, it's something else
900 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000901 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000902 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000903 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000904 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000905 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000906 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000907 if (!Memory.OffsetImm) return true;
908 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000909 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000910 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000911 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000912 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000913 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000914 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000915 return false;
916 return true;
917 }
918 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000919 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000920 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
921 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000922 return false;
923 return true;
924 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000925 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000926 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000927 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000928 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000929 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000930 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000931 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
932 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000933 return false;
934 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000935 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000936 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000937 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000938 return false;
939 return true;
940 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000941 bool isMemThumbRR() const {
942 // Thumb reg+reg addressing is simple. Just two registers, a base and
943 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000945 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000946 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 return isARMLowRegister(Memory.BaseRegNum) &&
948 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000949 }
950 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000952 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000953 return false;
954 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000955 if (!Memory.OffsetImm) return true;
956 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000957 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
958 }
Jim Grosbach38466302011-08-19 18:55:51 +0000959 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000961 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000962 return false;
963 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000964 if (!Memory.OffsetImm) return true;
965 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000966 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
967 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000968 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000970 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 return false;
972 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000973 if (!Memory.OffsetImm) return true;
974 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000975 return Val >= 0 && Val <= 31;
976 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000977 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000978 if (!isMemory() || Memory.OffsetRegNum != 0 ||
979 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 return false;
981 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000982 if (!Memory.OffsetImm) return true;
983 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000984 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000985 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000986 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000987 // If we have an immediate that's not a constant, treat it as a label
988 // reference needing a fixup. If it is a constant, it's something else
989 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000990 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000991 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000992 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 return false;
994 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000995 if (!Memory.OffsetImm) return true;
996 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000997 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
998 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000999 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001000 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 return false;
1002 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!Memory.OffsetImm) return true;
1004 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001005 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1006 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001007 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001008 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001009 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001010 // Base reg of PC isn't allowed for these encodings.
1011 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001013 if (!Memory.OffsetImm) return true;
1014 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001015 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001016 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001017 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001018 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return false;
1020 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001023 return Val >= 0 && Val < 256;
1024 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001025 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001027 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001028 // Base reg of PC isn't allowed for these encodings.
1029 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001031 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001032 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001033 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001034 }
1035 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001036 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 return false;
1038 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001039 if (!Memory.OffsetImm) return true;
1040 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001041 return (Val >= 0 && Val < 4096);
1042 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001043 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001044 // If we have an immediate that's not a constant, treat it as a label
1045 // reference needing a fixup. If it is a constant, it's something else
1046 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001047 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001048 return true;
1049
Jim Grosbach57dcb852011-10-11 17:29:55 +00001050 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001051 return false;
1052 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001053 if (!Memory.OffsetImm) return true;
1054 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001055 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001056 }
1057 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001058 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1060 if (!CE) return false;
1061 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001062 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001063 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001064 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001065 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 if (!CE) return false;
1068 int64_t Val = CE->getValue();
1069 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1070 (Val == INT32_MIN);
1071 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001072
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001073 bool isMSRMask() const { return Kind == k_MSRMask; }
1074 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001075
Jim Grosbach0e387b22011-10-17 22:26:03 +00001076 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001077 bool isSingleSpacedVectorList() const {
1078 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1079 }
1080 bool isDoubleSpacedVectorList() const {
1081 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1082 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001083 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001084 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001085 return VectorList.Count == 1;
1086 }
1087
Jim Grosbach28f08c92012-03-05 19:33:30 +00001088 bool isVecListDPair() const {
1089 if (!isSingleSpacedVectorList()) return false;
1090 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1091 .contains(VectorList.RegNum));
1092 }
1093
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001094 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001096 return VectorList.Count == 3;
1097 }
1098
Jim Grosbachb6310312011-10-21 20:35:01 +00001099 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001101 return VectorList.Count == 4;
1102 }
1103
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001104 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001107 }
1108
Jim Grosbachc387fc62012-01-23 23:20:46 +00001109 bool isVecListThreeQ() const {
1110 if (!isDoubleSpacedVectorList()) return false;
1111 return VectorList.Count == 3;
1112 }
1113
Jim Grosbach7945ead2012-01-24 00:43:12 +00001114 bool isVecListFourQ() const {
1115 if (!isDoubleSpacedVectorList()) return false;
1116 return VectorList.Count == 4;
1117 }
1118
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001119 bool isSingleSpacedVectorAllLanes() const {
1120 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1121 }
1122 bool isDoubleSpacedVectorAllLanes() const {
1123 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1124 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001125 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001126 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001127 return VectorList.Count == 1;
1128 }
1129
Jim Grosbach13af2222011-11-30 18:21:25 +00001130 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001131 if (!isSingleSpacedVectorAllLanes()) return false;
1132 return VectorList.Count == 2;
1133 }
1134
1135 bool isVecListTwoQAllLanes() const {
1136 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001137 return VectorList.Count == 2;
1138 }
1139
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001140 bool isVecListThreeDAllLanes() const {
1141 if (!isSingleSpacedVectorAllLanes()) return false;
1142 return VectorList.Count == 3;
1143 }
1144
1145 bool isVecListThreeQAllLanes() const {
1146 if (!isDoubleSpacedVectorAllLanes()) return false;
1147 return VectorList.Count == 3;
1148 }
1149
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001150 bool isVecListFourDAllLanes() const {
1151 if (!isSingleSpacedVectorAllLanes()) return false;
1152 return VectorList.Count == 4;
1153 }
1154
1155 bool isVecListFourQAllLanes() const {
1156 if (!isDoubleSpacedVectorAllLanes()) return false;
1157 return VectorList.Count == 4;
1158 }
1159
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001160 bool isSingleSpacedVectorIndexed() const {
1161 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1162 }
1163 bool isDoubleSpacedVectorIndexed() const {
1164 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1165 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001166 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001167 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001168 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1169 }
1170
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001171 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001172 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001173 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1174 }
1175
1176 bool isVecListOneDWordIndexed() 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 <= 1;
1179 }
1180
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001181 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001182 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001183 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1184 }
1185
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001186 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001187 if (!isSingleSpacedVectorIndexed()) return false;
1188 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1189 }
1190
1191 bool isVecListTwoQWordIndexed() const {
1192 if (!isDoubleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1194 }
1195
1196 bool isVecListTwoQHWordIndexed() const {
1197 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001198 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1199 }
1200
1201 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001202 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001203 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1204 }
1205
Jim Grosbach3a678af2012-01-23 21:53:26 +00001206 bool isVecListThreeDByteIndexed() const {
1207 if (!isSingleSpacedVectorIndexed()) return false;
1208 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1209 }
1210
1211 bool isVecListThreeDHWordIndexed() const {
1212 if (!isSingleSpacedVectorIndexed()) return false;
1213 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1214 }
1215
1216 bool isVecListThreeQWordIndexed() const {
1217 if (!isDoubleSpacedVectorIndexed()) return false;
1218 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1219 }
1220
1221 bool isVecListThreeQHWordIndexed() const {
1222 if (!isDoubleSpacedVectorIndexed()) return false;
1223 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1224 }
1225
1226 bool isVecListThreeDWordIndexed() const {
1227 if (!isSingleSpacedVectorIndexed()) return false;
1228 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1229 }
1230
Jim Grosbache983a132012-01-24 18:37:25 +00001231 bool isVecListFourDByteIndexed() const {
1232 if (!isSingleSpacedVectorIndexed()) return false;
1233 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1234 }
1235
1236 bool isVecListFourDHWordIndexed() const {
1237 if (!isSingleSpacedVectorIndexed()) return false;
1238 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1239 }
1240
1241 bool isVecListFourQWordIndexed() const {
1242 if (!isDoubleSpacedVectorIndexed()) return false;
1243 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1244 }
1245
1246 bool isVecListFourQHWordIndexed() const {
1247 if (!isDoubleSpacedVectorIndexed()) return false;
1248 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1249 }
1250
1251 bool isVecListFourDWordIndexed() const {
1252 if (!isSingleSpacedVectorIndexed()) return false;
1253 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1254 }
1255
Jim Grosbach460a9052011-10-07 23:56:00 +00001256 bool isVectorIndex8() const {
1257 if (Kind != k_VectorIndex) return false;
1258 return VectorIndex.Val < 8;
1259 }
1260 bool isVectorIndex16() const {
1261 if (Kind != k_VectorIndex) return false;
1262 return VectorIndex.Val < 4;
1263 }
1264 bool isVectorIndex32() const {
1265 if (Kind != k_VectorIndex) return false;
1266 return VectorIndex.Val < 2;
1267 }
1268
Jim Grosbach0e387b22011-10-17 22:26:03 +00001269 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001270 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001271 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1272 // Must be a constant.
1273 if (!CE) return false;
1274 int64_t Value = CE->getValue();
1275 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1276 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001277 return Value >= 0 && Value < 256;
1278 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001279
Jim Grosbachea461102011-10-17 23:09:09 +00001280 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001281 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001282 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1283 // Must be a constant.
1284 if (!CE) return false;
1285 int64_t Value = CE->getValue();
1286 // i16 value in the range [0,255] or [0x0100, 0xff00]
1287 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1288 }
1289
Jim Grosbach6248a542011-10-18 00:22:00 +00001290 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001291 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001292 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1293 // Must be a constant.
1294 if (!CE) return false;
1295 int64_t Value = CE->getValue();
1296 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1297 return (Value >= 0 && Value < 256) ||
1298 (Value >= 0x0100 && Value <= 0xff00) ||
1299 (Value >= 0x010000 && Value <= 0xff0000) ||
1300 (Value >= 0x01000000 && Value <= 0xff000000);
1301 }
1302
1303 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001304 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001305 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1306 // Must be a constant.
1307 if (!CE) return false;
1308 int64_t Value = CE->getValue();
1309 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1310 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1311 return (Value >= 0 && Value < 256) ||
1312 (Value >= 0x0100 && Value <= 0xff00) ||
1313 (Value >= 0x010000 && Value <= 0xff0000) ||
1314 (Value >= 0x01000000 && Value <= 0xff000000) ||
1315 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1316 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1317 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001318 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001319 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001320 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1321 // Must be a constant.
1322 if (!CE) return false;
1323 int64_t Value = ~CE->getValue();
1324 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1325 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1326 return (Value >= 0 && Value < 256) ||
1327 (Value >= 0x0100 && Value <= 0xff00) ||
1328 (Value >= 0x010000 && Value <= 0xff0000) ||
1329 (Value >= 0x01000000 && Value <= 0xff000000) ||
1330 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1331 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1332 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001333
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001334 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001335 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001336 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1337 // Must be a constant.
1338 if (!CE) return false;
1339 uint64_t Value = CE->getValue();
1340 // i64 value with each byte being either 0 or 0xff.
1341 for (unsigned i = 0; i < 8; ++i)
1342 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1343 return true;
1344 }
1345
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001346 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001347 // Add as immediates when possible. Null MCExpr = 0.
1348 if (Expr == 0)
1349 Inst.addOperand(MCOperand::CreateImm(0));
1350 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001351 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1352 else
1353 Inst.addOperand(MCOperand::CreateExpr(Expr));
1354 }
1355
Daniel Dunbar8462b302010-08-11 06:36:53 +00001356 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001357 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001358 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001359 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1360 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001361 }
1362
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001363 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1366 }
1367
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001368 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1371 }
1372
1373 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
1375 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1376 }
1377
Jim Grosbach89df9962011-08-26 21:43:41 +00001378 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
1380 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1381 }
1382
1383 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1386 }
1387
Jim Grosbachd67641b2010-12-06 18:21:12 +00001388 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 Inst.addOperand(MCOperand::CreateReg(getReg()));
1391 }
1392
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001393 void addRegOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 Inst.addOperand(MCOperand::CreateReg(getReg()));
1396 }
1397
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001398 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001399 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001400 assert(isRegShiftedReg() &&
1401 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001402 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1403 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001404 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001405 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001406 }
1407
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001408 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001409 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001410 assert(isRegShiftedImm() &&
1411 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001412 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001413 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001414 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001415 }
1416
Jim Grosbach580f4a92011-07-25 22:20:28 +00001417 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001418 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001419 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1420 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001421 }
1422
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001423 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001424 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001425 const SmallVectorImpl<unsigned> &RegList = getRegList();
1426 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001427 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1428 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001429 }
1430
Bill Wendling0f630752010-11-17 04:32:08 +00001431 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1432 addRegListOperands(Inst, N);
1433 }
1434
1435 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1436 addRegListOperands(Inst, N);
1437 }
1438
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001439 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1442 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1443 }
1444
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001445 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447 // Munge the lsb/width into a bitfield mask.
1448 unsigned lsb = Bitfield.LSB;
1449 unsigned width = Bitfield.Width;
1450 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1451 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1452 (32 - (lsb + width)));
1453 Inst.addOperand(MCOperand::CreateImm(Mask));
1454 }
1455
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001456 void addImmOperands(MCInst &Inst, unsigned N) const {
1457 assert(N == 1 && "Invalid number of operands!");
1458 addExpr(Inst, getImm());
1459 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001460
Jim Grosbach4050bc42011-12-22 22:19:05 +00001461 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1462 assert(N == 1 && "Invalid number of operands!");
1463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1464 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1465 }
1466
1467 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1470 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1471 }
1472
Jim Grosbach9d390362011-10-03 23:38:36 +00001473 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1476 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1477 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001478 }
1479
Jim Grosbacha77295d2011-09-08 22:07:06 +00001480 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 // FIXME: We really want to scale the value here, but the LDRD/STRD
1483 // instruction don't encode operands that way yet.
1484 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1485 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1486 }
1487
Jim Grosbach72f39f82011-08-24 21:22:15 +00001488 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 // The immediate is scaled by four in the encoding and is stored
1491 // in the MCInst as such. Lop off the low two bits here.
1492 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1493 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1494 }
1495
1496 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1497 assert(N == 1 && "Invalid number of operands!");
1498 // The immediate is scaled by four in the encoding and is stored
1499 // in the MCInst as such. Lop off the low two bits here.
1500 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1501 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1502 }
1503
Jim Grosbachf4943352011-07-25 23:09:14 +00001504 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 // The constant encodes as the immediate-1, and we store in the instruction
1507 // the bits as encoded, so subtract off one here.
1508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1509 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1510 }
1511
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001512 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
1514 // The constant encodes as the immediate-1, and we store in the instruction
1515 // the bits as encoded, so subtract off one here.
1516 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1517 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1518 }
1519
Jim Grosbach70939ee2011-08-17 21:51:27 +00001520 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 // The constant encodes as the immediate, except for 32, which encodes as
1523 // zero.
1524 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1525 unsigned Imm = CE->getValue();
1526 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1527 }
1528
Jim Grosbachf6c05252011-07-21 17:23:04 +00001529 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1530 assert(N == 1 && "Invalid number of operands!");
1531 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1532 // the instruction as well.
1533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1534 int Val = CE->getValue();
1535 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1536 }
1537
Jim Grosbach89a63372011-10-28 22:36:30 +00001538 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 1 && "Invalid number of operands!");
1540 // The operand is actually a t2_so_imm, but we have its bitwise
1541 // negation in the assembly source, so twiddle it here.
1542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1543 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1544 }
1545
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001546 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1547 assert(N == 1 && "Invalid number of operands!");
1548 // The operand is actually a t2_so_imm, but we have its
1549 // negation in the assembly source, so twiddle it here.
1550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1551 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1552 }
1553
Jim Grosbache70ec842011-10-28 22:50:54 +00001554 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 1 && "Invalid number of operands!");
1556 // The operand is actually a so_imm, but we have its bitwise
1557 // negation in the assembly source, so twiddle it here.
1558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1559 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1560 }
1561
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001562 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 1 && "Invalid number of operands!");
1564 // The operand is actually a so_imm, but we have its
1565 // negation in the assembly source, so twiddle it here.
1566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1567 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1568 }
1569
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001570 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
1572 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1573 }
1574
Jim Grosbach7ce05792011-08-03 23:50:40 +00001575 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001577 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001578 }
1579
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001580 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 int32_t Imm = Memory.OffsetImm->getValue();
1583 // FIXME: Handle #-0
1584 if (Imm == INT32_MIN) Imm = 0;
1585 Inst.addOperand(MCOperand::CreateImm(Imm));
1586 }
1587
Jim Grosbach57dcb852011-10-11 17:29:55 +00001588 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 2 && "Invalid number of operands!");
1590 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1591 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1592 }
1593
Jim Grosbach7ce05792011-08-03 23:50:40 +00001594 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1595 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001596 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1597 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001598 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1599 // Special case for #-0
1600 if (Val == INT32_MIN) Val = 0;
1601 if (Val < 0) Val = -Val;
1602 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1603 } else {
1604 // For register offset, we encode the shift type and negation flag
1605 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001606 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1607 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001608 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001609 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1610 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001611 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001612 }
1613
Jim Grosbach039c2e12011-08-04 23:01:30 +00001614 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 2 && "Invalid number of operands!");
1616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617 assert(CE && "non-constant AM2OffsetImm operand!");
1618 int32_t Val = CE->getValue();
1619 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1620 // Special case for #-0
1621 if (Val == INT32_MIN) Val = 0;
1622 if (Val < 0) Val = -Val;
1623 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1624 Inst.addOperand(MCOperand::CreateReg(0));
1625 Inst.addOperand(MCOperand::CreateImm(Val));
1626 }
1627
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001628 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1629 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001630 // If we have an immediate that's not a constant, treat it as a label
1631 // reference needing a fixup. If it is a constant, it's something else
1632 // and we reject it.
1633 if (isImm()) {
1634 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1635 Inst.addOperand(MCOperand::CreateReg(0));
1636 Inst.addOperand(MCOperand::CreateImm(0));
1637 return;
1638 }
1639
Jim Grosbache53c87b2011-10-11 15:59:20 +00001640 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1641 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001642 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1643 // Special case for #-0
1644 if (Val == INT32_MIN) Val = 0;
1645 if (Val < 0) Val = -Val;
1646 Val = ARM_AM::getAM3Opc(AddSub, Val);
1647 } else {
1648 // For register offset, we encode the shift type and negation flag
1649 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001650 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001651 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001652 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1653 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001654 Inst.addOperand(MCOperand::CreateImm(Val));
1655 }
1656
1657 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1658 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001659 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001660 int32_t Val =
1661 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1662 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1663 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001664 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001665 }
1666
1667 // Constant offset.
1668 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1669 int32_t Val = CE->getValue();
1670 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1671 // Special case for #-0
1672 if (Val == INT32_MIN) Val = 0;
1673 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001674 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001675 Inst.addOperand(MCOperand::CreateReg(0));
1676 Inst.addOperand(MCOperand::CreateImm(Val));
1677 }
1678
Jim Grosbach7ce05792011-08-03 23:50:40 +00001679 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1680 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001681 // If we have an immediate that's not a constant, treat it as a label
1682 // reference needing a fixup. If it is a constant, it's something else
1683 // and we reject it.
1684 if (isImm()) {
1685 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1686 Inst.addOperand(MCOperand::CreateImm(0));
1687 return;
1688 }
1689
Jim Grosbach7ce05792011-08-03 23:50:40 +00001690 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001691 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001692 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1693 // Special case for #-0
1694 if (Val == INT32_MIN) Val = 0;
1695 if (Val < 0) Val = -Val;
1696 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001697 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001698 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001699 }
1700
Jim Grosbacha77295d2011-09-08 22:07:06 +00001701 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1702 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001703 // If we have an immediate that's not a constant, treat it as a label
1704 // reference needing a fixup. If it is a constant, it's something else
1705 // and we reject it.
1706 if (isImm()) {
1707 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1708 Inst.addOperand(MCOperand::CreateImm(0));
1709 return;
1710 }
1711
Jim Grosbache53c87b2011-10-11 15:59:20 +00001712 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1713 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001714 Inst.addOperand(MCOperand::CreateImm(Val));
1715 }
1716
Jim Grosbachb6aed502011-09-09 18:37:27 +00001717 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1718 assert(N == 2 && "Invalid number of operands!");
1719 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001720 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1721 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001722 Inst.addOperand(MCOperand::CreateImm(Val));
1723 }
1724
Jim Grosbach7ce05792011-08-03 23:50:40 +00001725 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1726 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001727 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1728 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001729 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001730 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001731
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001732 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1733 addMemImm8OffsetOperands(Inst, N);
1734 }
1735
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001736 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001737 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001738 }
1739
1740 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1741 assert(N == 2 && "Invalid number of operands!");
1742 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001743 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001744 addExpr(Inst, getImm());
1745 Inst.addOperand(MCOperand::CreateImm(0));
1746 return;
1747 }
1748
1749 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001750 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1751 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001752 Inst.addOperand(MCOperand::CreateImm(Val));
1753 }
1754
Jim Grosbach7ce05792011-08-03 23:50:40 +00001755 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1756 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001757 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001758 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001759 addExpr(Inst, getImm());
1760 Inst.addOperand(MCOperand::CreateImm(0));
1761 return;
1762 }
1763
1764 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001765 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1766 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001767 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001768 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001769
Jim Grosbach7f739be2011-09-19 22:21:13 +00001770 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1771 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1773 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001774 }
1775
1776 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001778 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1779 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001780 }
1781
Jim Grosbach7ce05792011-08-03 23:50:40 +00001782 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1783 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001784 unsigned Val =
1785 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1786 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001787 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1788 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001789 Inst.addOperand(MCOperand::CreateImm(Val));
1790 }
1791
Jim Grosbachab899c12011-09-07 23:10:15 +00001792 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1793 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001794 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1795 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1796 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001797 }
1798
Jim Grosbach7ce05792011-08-03 23:50:40 +00001799 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001801 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1802 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001803 }
1804
Jim Grosbach60f91a32011-08-19 17:55:24 +00001805 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1806 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001807 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1808 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001809 Inst.addOperand(MCOperand::CreateImm(Val));
1810 }
1811
Jim Grosbach38466302011-08-19 18:55:51 +00001812 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1813 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001814 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1815 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001816 Inst.addOperand(MCOperand::CreateImm(Val));
1817 }
1818
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001819 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1820 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001821 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1822 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001823 Inst.addOperand(MCOperand::CreateImm(Val));
1824 }
1825
Jim Grosbachecd85892011-08-19 18:13:48 +00001826 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1827 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001828 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1829 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001830 Inst.addOperand(MCOperand::CreateImm(Val));
1831 }
1832
Jim Grosbach7ce05792011-08-03 23:50:40 +00001833 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1834 assert(N == 1 && "Invalid number of operands!");
1835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1836 assert(CE && "non-constant post-idx-imm8 operand!");
1837 int Imm = CE->getValue();
1838 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001839 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001840 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1841 Inst.addOperand(MCOperand::CreateImm(Imm));
1842 }
1843
Jim Grosbach2bd01182011-10-11 21:55:36 +00001844 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1845 assert(N == 1 && "Invalid number of operands!");
1846 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1847 assert(CE && "non-constant post-idx-imm8s4 operand!");
1848 int Imm = CE->getValue();
1849 bool isAdd = Imm >= 0;
1850 if (Imm == INT32_MIN) Imm = 0;
1851 // Immediate is scaled by 4.
1852 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1853 Inst.addOperand(MCOperand::CreateImm(Imm));
1854 }
1855
Jim Grosbach7ce05792011-08-03 23:50:40 +00001856 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1857 assert(N == 2 && "Invalid number of operands!");
1858 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001859 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1860 }
1861
1862 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1863 assert(N == 2 && "Invalid number of operands!");
1864 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1865 // The sign, shift type, and shift amount are encoded in a single operand
1866 // using the AM2 encoding helpers.
1867 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1868 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1869 PostIdxReg.ShiftTy);
1870 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001871 }
1872
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001873 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1874 assert(N == 1 && "Invalid number of operands!");
1875 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1876 }
1877
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001878 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1879 assert(N == 1 && "Invalid number of operands!");
1880 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1881 }
1882
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001883 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001884 assert(N == 1 && "Invalid number of operands!");
1885 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1886 }
1887
Jim Grosbach7636bf62011-12-02 00:35:16 +00001888 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1889 assert(N == 2 && "Invalid number of operands!");
1890 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1891 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1892 }
1893
Jim Grosbach460a9052011-10-07 23:56:00 +00001894 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1895 assert(N == 1 && "Invalid number of operands!");
1896 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1897 }
1898
1899 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1900 assert(N == 1 && "Invalid number of operands!");
1901 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1902 }
1903
1904 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1905 assert(N == 1 && "Invalid number of operands!");
1906 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1907 }
1908
Jim Grosbach0e387b22011-10-17 22:26:03 +00001909 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1910 assert(N == 1 && "Invalid number of operands!");
1911 // The immediate encodes the type of constant as well as the value.
1912 // Mask in that this is an i8 splat.
1913 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1914 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1915 }
1916
Jim Grosbachea461102011-10-17 23:09:09 +00001917 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1918 assert(N == 1 && "Invalid number of operands!");
1919 // The immediate encodes the type of constant as well as the value.
1920 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1921 unsigned Value = CE->getValue();
1922 if (Value >= 256)
1923 Value = (Value >> 8) | 0xa00;
1924 else
1925 Value |= 0x800;
1926 Inst.addOperand(MCOperand::CreateImm(Value));
1927 }
1928
Jim Grosbach6248a542011-10-18 00:22:00 +00001929 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1930 assert(N == 1 && "Invalid number of operands!");
1931 // The immediate encodes the type of constant as well as the value.
1932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1933 unsigned Value = CE->getValue();
1934 if (Value >= 256 && Value <= 0xff00)
1935 Value = (Value >> 8) | 0x200;
1936 else if (Value > 0xffff && Value <= 0xff0000)
1937 Value = (Value >> 16) | 0x400;
1938 else if (Value > 0xffffff)
1939 Value = (Value >> 24) | 0x600;
1940 Inst.addOperand(MCOperand::CreateImm(Value));
1941 }
1942
1943 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1944 assert(N == 1 && "Invalid number of operands!");
1945 // The immediate encodes the type of constant as well as the value.
1946 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1947 unsigned Value = CE->getValue();
1948 if (Value >= 256 && Value <= 0xffff)
1949 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1950 else if (Value > 0xffff && Value <= 0xffffff)
1951 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1952 else if (Value > 0xffffff)
1953 Value = (Value >> 24) | 0x600;
1954 Inst.addOperand(MCOperand::CreateImm(Value));
1955 }
1956
Jim Grosbach9b087852011-12-19 23:51:07 +00001957 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1958 assert(N == 1 && "Invalid number of operands!");
1959 // The immediate encodes the type of constant as well as the value.
1960 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1961 unsigned Value = ~CE->getValue();
1962 if (Value >= 256 && Value <= 0xffff)
1963 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1964 else if (Value > 0xffff && Value <= 0xffffff)
1965 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1966 else if (Value > 0xffffff)
1967 Value = (Value >> 24) | 0x600;
1968 Inst.addOperand(MCOperand::CreateImm(Value));
1969 }
1970
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001971 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1972 assert(N == 1 && "Invalid number of operands!");
1973 // The immediate encodes the type of constant as well as the value.
1974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1975 uint64_t Value = CE->getValue();
1976 unsigned Imm = 0;
1977 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1978 Imm |= (Value & 1) << i;
1979 }
1980 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1981 }
1982
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001983 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001984
Jim Grosbach89df9962011-08-26 21:43:41 +00001985 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001986 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001987 Op->ITMask.Mask = Mask;
1988 Op->StartLoc = S;
1989 Op->EndLoc = S;
1990 return Op;
1991 }
1992
Chris Lattner3a697562010-10-28 17:20:03 +00001993 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001994 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001995 Op->CC.Val = CC;
1996 Op->StartLoc = S;
1997 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001998 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001999 }
2000
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002001 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002002 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002003 Op->Cop.Val = CopVal;
2004 Op->StartLoc = S;
2005 Op->EndLoc = S;
2006 return Op;
2007 }
2008
2009 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002010 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002011 Op->Cop.Val = CopVal;
2012 Op->StartLoc = S;
2013 Op->EndLoc = S;
2014 return Op;
2015 }
2016
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002017 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2018 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2019 Op->Cop.Val = Val;
2020 Op->StartLoc = S;
2021 Op->EndLoc = E;
2022 return Op;
2023 }
2024
Jim Grosbachd67641b2010-12-06 18:21:12 +00002025 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002026 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002027 Op->Reg.RegNum = RegNum;
2028 Op->StartLoc = S;
2029 Op->EndLoc = S;
2030 return Op;
2031 }
2032
Chris Lattner3a697562010-10-28 17:20:03 +00002033 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002034 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002035 Op->Tok.Data = Str.data();
2036 Op->Tok.Length = Str.size();
2037 Op->StartLoc = S;
2038 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002039 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002040 }
2041
Bill Wendling50d0f582010-11-18 23:43:05 +00002042 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002043 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002044 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002045 Op->StartLoc = S;
2046 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002047 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002048 }
2049
Jim Grosbache8606dc2011-07-13 17:50:29 +00002050 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2051 unsigned SrcReg,
2052 unsigned ShiftReg,
2053 unsigned ShiftImm,
2054 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002055 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002056 Op->RegShiftedReg.ShiftTy = ShTy;
2057 Op->RegShiftedReg.SrcReg = SrcReg;
2058 Op->RegShiftedReg.ShiftReg = ShiftReg;
2059 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002060 Op->StartLoc = S;
2061 Op->EndLoc = E;
2062 return Op;
2063 }
2064
Owen Anderson92a20222011-07-21 18:54:16 +00002065 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2066 unsigned SrcReg,
2067 unsigned ShiftImm,
2068 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002069 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002070 Op->RegShiftedImm.ShiftTy = ShTy;
2071 Op->RegShiftedImm.SrcReg = SrcReg;
2072 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002073 Op->StartLoc = S;
2074 Op->EndLoc = E;
2075 return Op;
2076 }
2077
Jim Grosbach580f4a92011-07-25 22:20:28 +00002078 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002079 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002080 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002081 Op->ShifterImm.isASR = isASR;
2082 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002083 Op->StartLoc = S;
2084 Op->EndLoc = E;
2085 return Op;
2086 }
2087
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002088 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002089 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002090 Op->RotImm.Imm = Imm;
2091 Op->StartLoc = S;
2092 Op->EndLoc = E;
2093 return Op;
2094 }
2095
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002096 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2097 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002098 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002099 Op->Bitfield.LSB = LSB;
2100 Op->Bitfield.Width = Width;
2101 Op->StartLoc = S;
2102 Op->EndLoc = E;
2103 return Op;
2104 }
2105
Bill Wendling7729e062010-11-09 22:44:22 +00002106 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002107 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002108 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002109 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002110
Jim Grosbachd300b942011-09-13 22:56:44 +00002111 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002112 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002113 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002114 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002115 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002116
2117 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002118 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002119 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002120 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002121 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002122 Op->StartLoc = StartLoc;
2123 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002124 return Op;
2125 }
2126
Jim Grosbach862019c2011-10-18 23:02:30 +00002127 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002128 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002129 ARMOperand *Op = new ARMOperand(k_VectorList);
2130 Op->VectorList.RegNum = RegNum;
2131 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002132 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002133 Op->StartLoc = S;
2134 Op->EndLoc = E;
2135 return Op;
2136 }
2137
Jim Grosbach98b05a52011-11-30 01:09:44 +00002138 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002139 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002140 SMLoc S, SMLoc E) {
2141 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2142 Op->VectorList.RegNum = RegNum;
2143 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002144 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002145 Op->StartLoc = S;
2146 Op->EndLoc = E;
2147 return Op;
2148 }
2149
Jim Grosbach7636bf62011-12-02 00:35:16 +00002150 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002151 unsigned Index,
2152 bool isDoubleSpaced,
2153 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002154 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2155 Op->VectorList.RegNum = RegNum;
2156 Op->VectorList.Count = Count;
2157 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002158 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002159 Op->StartLoc = S;
2160 Op->EndLoc = E;
2161 return Op;
2162 }
2163
Jim Grosbach460a9052011-10-07 23:56:00 +00002164 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2165 MCContext &Ctx) {
2166 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2167 Op->VectorIndex.Val = Idx;
2168 Op->StartLoc = S;
2169 Op->EndLoc = E;
2170 return Op;
2171 }
2172
Chris Lattner3a697562010-10-28 17:20:03 +00002173 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002174 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002175 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002176 Op->StartLoc = S;
2177 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002178 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002179 }
2180
Jim Grosbach7ce05792011-08-03 23:50:40 +00002181 static ARMOperand *CreateMem(unsigned BaseRegNum,
2182 const MCConstantExpr *OffsetImm,
2183 unsigned OffsetRegNum,
2184 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002185 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002186 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002187 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002188 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002189 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002190 Op->Memory.BaseRegNum = BaseRegNum;
2191 Op->Memory.OffsetImm = OffsetImm;
2192 Op->Memory.OffsetRegNum = OffsetRegNum;
2193 Op->Memory.ShiftType = ShiftType;
2194 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002195 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002196 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002197 Op->StartLoc = S;
2198 Op->EndLoc = E;
2199 return Op;
2200 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002201
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002202 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2203 ARM_AM::ShiftOpc ShiftTy,
2204 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002205 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002206 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002207 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002208 Op->PostIdxReg.isAdd = isAdd;
2209 Op->PostIdxReg.ShiftTy = ShiftTy;
2210 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002211 Op->StartLoc = S;
2212 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002213 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002214 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002215
2216 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002217 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002218 Op->MBOpt.Val = Opt;
2219 Op->StartLoc = S;
2220 Op->EndLoc = S;
2221 return Op;
2222 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002223
2224 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002225 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002226 Op->IFlags.Val = IFlags;
2227 Op->StartLoc = S;
2228 Op->EndLoc = S;
2229 return Op;
2230 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002231
2232 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002233 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002234 Op->MMask.Val = MMask;
2235 Op->StartLoc = S;
2236 Op->EndLoc = S;
2237 return Op;
2238 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002239};
2240
2241} // end anonymous namespace.
2242
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002243void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002244 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002245 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002246 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002247 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002248 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002249 OS << "<ccout " << getReg() << ">";
2250 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002251 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002252 static const char *MaskStr[] = {
2253 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2254 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2255 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002256 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2257 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2258 break;
2259 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002260 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002261 OS << "<coprocessor number: " << getCoproc() << ">";
2262 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002263 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002264 OS << "<coprocessor register: " << getCoproc() << ">";
2265 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002266 case k_CoprocOption:
2267 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2268 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002269 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002270 OS << "<mask: " << getMSRMask() << ">";
2271 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002272 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002273 getImm()->print(OS);
2274 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002275 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002276 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2277 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002278 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002279 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002280 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002281 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002282 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002283 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002284 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2285 << PostIdxReg.RegNum;
2286 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2287 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2288 << PostIdxReg.ShiftImm;
2289 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002290 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002291 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002292 OS << "<ARM_PROC::";
2293 unsigned IFlags = getProcIFlags();
2294 for (int i=2; i >= 0; --i)
2295 if (IFlags & (1 << i))
2296 OS << ARM_PROC::IFlagsToString(1 << i);
2297 OS << ">";
2298 break;
2299 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002300 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002301 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002302 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002303 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002304 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2305 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002306 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002307 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002308 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002309 << RegShiftedReg.SrcReg << " "
2310 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2311 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002312 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002313 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002314 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002315 << RegShiftedImm.SrcReg << " "
2316 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2317 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002318 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002319 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002320 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2321 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002322 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002323 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2324 << ", width: " << Bitfield.Width << ">";
2325 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002326 case k_RegisterList:
2327 case k_DPRRegisterList:
2328 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002329 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002330
Bill Wendling5fa22a12010-11-09 23:28:44 +00002331 const SmallVectorImpl<unsigned> &RegList = getRegList();
2332 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002333 I = RegList.begin(), E = RegList.end(); I != E; ) {
2334 OS << *I;
2335 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002336 }
2337
2338 OS << ">";
2339 break;
2340 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002341 case k_VectorList:
2342 OS << "<vector_list " << VectorList.Count << " * "
2343 << VectorList.RegNum << ">";
2344 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002345 case k_VectorListAllLanes:
2346 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2347 << VectorList.RegNum << ">";
2348 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002349 case k_VectorListIndexed:
2350 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2351 << VectorList.Count << " * " << VectorList.RegNum << ">";
2352 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002353 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002354 OS << "'" << getToken() << "'";
2355 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002356 case k_VectorIndex:
2357 OS << "<vectorindex " << getVectorIndex() << ">";
2358 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002359 }
2360}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002361
2362/// @name Auto-generated Match Functions
2363/// {
2364
2365static unsigned MatchRegisterName(StringRef Name);
2366
2367/// }
2368
Bob Wilson69df7232011-02-03 21:46:10 +00002369bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2370 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002371 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002372 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002373 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002374
2375 return (RegNo == (unsigned)-1);
2376}
2377
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002378/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002379/// and if it is a register name the token is eaten and the register number is
2380/// returned. Otherwise return -1.
2381///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002382int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002383 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002384 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002385
Benjamin Kramer59085362011-11-06 20:37:06 +00002386 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002387 unsigned RegNum = MatchRegisterName(lowerCase);
2388 if (!RegNum) {
2389 RegNum = StringSwitch<unsigned>(lowerCase)
2390 .Case("r13", ARM::SP)
2391 .Case("r14", ARM::LR)
2392 .Case("r15", ARM::PC)
2393 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002394 // Additional register name aliases for 'gas' compatibility.
2395 .Case("a1", ARM::R0)
2396 .Case("a2", ARM::R1)
2397 .Case("a3", ARM::R2)
2398 .Case("a4", ARM::R3)
2399 .Case("v1", ARM::R4)
2400 .Case("v2", ARM::R5)
2401 .Case("v3", ARM::R6)
2402 .Case("v4", ARM::R7)
2403 .Case("v5", ARM::R8)
2404 .Case("v6", ARM::R9)
2405 .Case("v7", ARM::R10)
2406 .Case("v8", ARM::R11)
2407 .Case("sb", ARM::R9)
2408 .Case("sl", ARM::R10)
2409 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002410 .Default(0);
2411 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002412 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002413 // Check for aliases registered via .req. Canonicalize to lower case.
2414 // That's more consistent since register names are case insensitive, and
2415 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2416 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002417 // If no match, return failure.
2418 if (Entry == RegisterReqs.end())
2419 return -1;
2420 Parser.Lex(); // Eat identifier token.
2421 return Entry->getValue();
2422 }
Bob Wilson69df7232011-02-03 21:46:10 +00002423
Chris Lattnere5658fa2010-10-30 04:09:10 +00002424 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002425
Chris Lattnere5658fa2010-10-30 04:09:10 +00002426 return RegNum;
2427}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002428
Jim Grosbach19906722011-07-13 18:49:30 +00002429// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2430// If a recoverable error occurs, return 1. If an irrecoverable error
2431// occurs, return -1. An irrecoverable error is one where tokens have been
2432// consumed in the process of trying to parse the shifter (i.e., when it is
2433// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002434int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002435 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2436 SMLoc S = Parser.getTok().getLoc();
2437 const AsmToken &Tok = Parser.getTok();
2438 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2439
Benjamin Kramer59085362011-11-06 20:37:06 +00002440 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002441 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002442 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002443 .Case("lsl", ARM_AM::lsl)
2444 .Case("lsr", ARM_AM::lsr)
2445 .Case("asr", ARM_AM::asr)
2446 .Case("ror", ARM_AM::ror)
2447 .Case("rrx", ARM_AM::rrx)
2448 .Default(ARM_AM::no_shift);
2449
2450 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002451 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002452
Jim Grosbache8606dc2011-07-13 17:50:29 +00002453 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002454
Jim Grosbache8606dc2011-07-13 17:50:29 +00002455 // The source register for the shift has already been added to the
2456 // operand list, so we need to pop it off and combine it into the shifted
2457 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002458 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002459 if (!PrevOp->isReg())
2460 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2461 int SrcReg = PrevOp->getReg();
2462 int64_t Imm = 0;
2463 int ShiftReg = 0;
2464 if (ShiftTy == ARM_AM::rrx) {
2465 // RRX Doesn't have an explicit shift amount. The encoder expects
2466 // the shift register to be the same as the source register. Seems odd,
2467 // but OK.
2468 ShiftReg = SrcReg;
2469 } else {
2470 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002471 if (Parser.getTok().is(AsmToken::Hash) ||
2472 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002473 Parser.Lex(); // Eat hash.
2474 SMLoc ImmLoc = Parser.getTok().getLoc();
2475 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002476 if (getParser().ParseExpression(ShiftExpr)) {
2477 Error(ImmLoc, "invalid immediate shift value");
2478 return -1;
2479 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002480 // The expression must be evaluatable as an immediate.
2481 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002482 if (!CE) {
2483 Error(ImmLoc, "invalid immediate shift value");
2484 return -1;
2485 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002486 // Range check the immediate.
2487 // lsl, ror: 0 <= imm <= 31
2488 // lsr, asr: 0 <= imm <= 32
2489 Imm = CE->getValue();
2490 if (Imm < 0 ||
2491 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2492 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002493 Error(ImmLoc, "immediate shift value out of range");
2494 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002495 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002496 // shift by zero is a nop. Always send it through as lsl.
2497 // ('as' compatibility)
2498 if (Imm == 0)
2499 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002500 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002501 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002502 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002503 if (ShiftReg == -1) {
2504 Error (L, "expected immediate or register in shift operand");
2505 return -1;
2506 }
2507 } else {
2508 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002509 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002510 return -1;
2511 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002512 }
2513
Owen Anderson92a20222011-07-21 18:54:16 +00002514 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2515 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002516 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002517 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002518 else
2519 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2520 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002521
Jim Grosbach19906722011-07-13 18:49:30 +00002522 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002523}
2524
2525
Bill Wendling50d0f582010-11-18 23:43:05 +00002526/// Try to parse a register name. The token must be an Identifier when called.
2527/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2528/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002529///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002530/// TODO this is likely to change to allow different register types and or to
2531/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002532bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002533tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002534 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002535 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002536 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002537 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002538
Bill Wendling50d0f582010-11-18 23:43:05 +00002539 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002540
Chris Lattnere5658fa2010-10-30 04:09:10 +00002541 const AsmToken &ExclaimTok = Parser.getTok();
2542 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002543 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2544 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002545 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002546 return false;
2547 }
2548
2549 // Also check for an index operand. This is only legal for vector registers,
2550 // but that'll get caught OK in operand matching, so we don't need to
2551 // explicitly filter everything else out here.
2552 if (Parser.getTok().is(AsmToken::LBrac)) {
2553 SMLoc SIdx = Parser.getTok().getLoc();
2554 Parser.Lex(); // Eat left bracket token.
2555
2556 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002557 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002558 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002559 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002560 if (!MCE)
2561 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002562
2563 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002564 if (Parser.getTok().isNot(AsmToken::RBrac))
2565 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002566
2567 Parser.Lex(); // Eat right bracket token.
2568
2569 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2570 SIdx, E,
2571 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002572 }
2573
Bill Wendling50d0f582010-11-18 23:43:05 +00002574 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002575}
2576
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002577/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2578/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2579/// "c5", ...
2580static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002581 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2582 // but efficient.
2583 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002584 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002585 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002586 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002587 return -1;
2588 switch (Name[1]) {
2589 default: return -1;
2590 case '0': return 0;
2591 case '1': return 1;
2592 case '2': return 2;
2593 case '3': return 3;
2594 case '4': return 4;
2595 case '5': return 5;
2596 case '6': return 6;
2597 case '7': return 7;
2598 case '8': return 8;
2599 case '9': return 9;
2600 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002601 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002602 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002603 return -1;
2604 switch (Name[2]) {
2605 default: return -1;
2606 case '0': return 10;
2607 case '1': return 11;
2608 case '2': return 12;
2609 case '3': return 13;
2610 case '4': return 14;
2611 case '5': return 15;
2612 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002613 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002614}
2615
Jim Grosbach89df9962011-08-26 21:43:41 +00002616/// parseITCondCode - Try to parse a condition code for an IT instruction.
2617ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2618parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2619 SMLoc S = Parser.getTok().getLoc();
2620 const AsmToken &Tok = Parser.getTok();
2621 if (!Tok.is(AsmToken::Identifier))
2622 return MatchOperand_NoMatch;
2623 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2624 .Case("eq", ARMCC::EQ)
2625 .Case("ne", ARMCC::NE)
2626 .Case("hs", ARMCC::HS)
2627 .Case("cs", ARMCC::HS)
2628 .Case("lo", ARMCC::LO)
2629 .Case("cc", ARMCC::LO)
2630 .Case("mi", ARMCC::MI)
2631 .Case("pl", ARMCC::PL)
2632 .Case("vs", ARMCC::VS)
2633 .Case("vc", ARMCC::VC)
2634 .Case("hi", ARMCC::HI)
2635 .Case("ls", ARMCC::LS)
2636 .Case("ge", ARMCC::GE)
2637 .Case("lt", ARMCC::LT)
2638 .Case("gt", ARMCC::GT)
2639 .Case("le", ARMCC::LE)
2640 .Case("al", ARMCC::AL)
2641 .Default(~0U);
2642 if (CC == ~0U)
2643 return MatchOperand_NoMatch;
2644 Parser.Lex(); // Eat the token.
2645
2646 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2647
2648 return MatchOperand_Success;
2649}
2650
Jim Grosbach43904292011-07-25 20:14:50 +00002651/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002652/// token must be an Identifier when called, and if it is a coprocessor
2653/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002654ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002655parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002656 SMLoc S = Parser.getTok().getLoc();
2657 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002658 if (Tok.isNot(AsmToken::Identifier))
2659 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002660
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002661 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002662 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002663 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002664
2665 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002666 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002667 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002668}
2669
Jim Grosbach43904292011-07-25 20:14:50 +00002670/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002671/// token must be an Identifier when called, and if it is a coprocessor
2672/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002673ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002674parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002675 SMLoc S = Parser.getTok().getLoc();
2676 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002677 if (Tok.isNot(AsmToken::Identifier))
2678 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002679
2680 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2681 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002682 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002683
2684 Parser.Lex(); // Eat identifier token.
2685 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002686 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002687}
2688
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002689/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2690/// coproc_option : '{' imm0_255 '}'
2691ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2692parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2693 SMLoc S = Parser.getTok().getLoc();
2694
2695 // If this isn't a '{', this isn't a coprocessor immediate operand.
2696 if (Parser.getTok().isNot(AsmToken::LCurly))
2697 return MatchOperand_NoMatch;
2698 Parser.Lex(); // Eat the '{'
2699
2700 const MCExpr *Expr;
2701 SMLoc Loc = Parser.getTok().getLoc();
2702 if (getParser().ParseExpression(Expr)) {
2703 Error(Loc, "illegal expression");
2704 return MatchOperand_ParseFail;
2705 }
2706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2707 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2708 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2709 return MatchOperand_ParseFail;
2710 }
2711 int Val = CE->getValue();
2712
2713 // Check for and consume the closing '}'
2714 if (Parser.getTok().isNot(AsmToken::RCurly))
2715 return MatchOperand_ParseFail;
2716 SMLoc E = Parser.getTok().getLoc();
2717 Parser.Lex(); // Eat the '}'
2718
2719 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2720 return MatchOperand_Success;
2721}
2722
Jim Grosbachd0588e22011-09-14 18:08:35 +00002723// For register list parsing, we need to map from raw GPR register numbering
2724// to the enumeration values. The enumeration values aren't sorted by
2725// register number due to our using "sp", "lr" and "pc" as canonical names.
2726static unsigned getNextRegister(unsigned Reg) {
2727 // If this is a GPR, we need to do it manually, otherwise we can rely
2728 // on the sort ordering of the enumeration since the other reg-classes
2729 // are sane.
2730 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2731 return Reg + 1;
2732 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002733 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002734 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2735 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2736 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2737 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2738 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2739 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2740 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2741 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2742 }
2743}
2744
Jim Grosbachce485e72011-11-11 21:27:40 +00002745// Return the low-subreg of a given Q register.
2746static unsigned getDRegFromQReg(unsigned QReg) {
2747 switch (QReg) {
2748 default: llvm_unreachable("expected a Q register!");
2749 case ARM::Q0: return ARM::D0;
2750 case ARM::Q1: return ARM::D2;
2751 case ARM::Q2: return ARM::D4;
2752 case ARM::Q3: return ARM::D6;
2753 case ARM::Q4: return ARM::D8;
2754 case ARM::Q5: return ARM::D10;
2755 case ARM::Q6: return ARM::D12;
2756 case ARM::Q7: return ARM::D14;
2757 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002758 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002759 case ARM::Q10: return ARM::D20;
2760 case ARM::Q11: return ARM::D22;
2761 case ARM::Q12: return ARM::D24;
2762 case ARM::Q13: return ARM::D26;
2763 case ARM::Q14: return ARM::D28;
2764 case ARM::Q15: return ARM::D30;
2765 }
2766}
2767
Jim Grosbachd0588e22011-09-14 18:08:35 +00002768/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002769bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002770parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002771 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002772 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002773 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002774 Parser.Lex(); // Eat '{' token.
2775 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002776
Jim Grosbachd0588e22011-09-14 18:08:35 +00002777 // Check the first register in the list to see what register class
2778 // this is a list of.
2779 int Reg = tryParseRegister();
2780 if (Reg == -1)
2781 return Error(RegLoc, "register expected");
2782
Jim Grosbachce485e72011-11-11 21:27:40 +00002783 // The reglist instructions have at most 16 registers, so reserve
2784 // space for that many.
2785 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2786
2787 // Allow Q regs and just interpret them as the two D sub-registers.
2788 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2789 Reg = getDRegFromQReg(Reg);
2790 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2791 ++Reg;
2792 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002793 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002794 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2795 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2796 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2797 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2798 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2799 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2800 else
2801 return Error(RegLoc, "invalid register in register list");
2802
Jim Grosbachce485e72011-11-11 21:27:40 +00002803 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002804 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002805
Jim Grosbachd0588e22011-09-14 18:08:35 +00002806 // This starts immediately after the first register token in the list,
2807 // so we can see either a comma or a minus (range separator) as a legal
2808 // next token.
2809 while (Parser.getTok().is(AsmToken::Comma) ||
2810 Parser.getTok().is(AsmToken::Minus)) {
2811 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002812 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002813 SMLoc EndLoc = Parser.getTok().getLoc();
2814 int EndReg = tryParseRegister();
2815 if (EndReg == -1)
2816 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002817 // Allow Q regs and just interpret them as the two D sub-registers.
2818 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2819 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002820 // If the register is the same as the start reg, there's nothing
2821 // more to do.
2822 if (Reg == EndReg)
2823 continue;
2824 // The register must be in the same register class as the first.
2825 if (!RC->contains(EndReg))
2826 return Error(EndLoc, "invalid register in register list");
2827 // Ranges must go from low to high.
2828 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2829 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002830
Jim Grosbachd0588e22011-09-14 18:08:35 +00002831 // Add all the registers in the range to the register list.
2832 while (Reg != EndReg) {
2833 Reg = getNextRegister(Reg);
2834 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2835 }
2836 continue;
2837 }
2838 Parser.Lex(); // Eat the comma.
2839 RegLoc = Parser.getTok().getLoc();
2840 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002841 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002842 Reg = tryParseRegister();
2843 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002844 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002845 // Allow Q regs and just interpret them as the two D sub-registers.
2846 bool isQReg = false;
2847 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2848 Reg = getDRegFromQReg(Reg);
2849 isQReg = true;
2850 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002851 // The register must be in the same register class as the first.
2852 if (!RC->contains(Reg))
2853 return Error(RegLoc, "invalid register in register list");
2854 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002855 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002856 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002857 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2858 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2859 ") in register list");
2860 continue;
2861 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002862 // VFP register lists must also be contiguous.
2863 // It's OK to use the enumeration values directly here rather, as the
2864 // VFP register classes have the enum sorted properly.
2865 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2866 Reg != OldReg + 1)
2867 return Error(RegLoc, "non-contiguous register range");
2868 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002869 if (isQReg)
2870 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002871 }
2872
Jim Grosbachd0588e22011-09-14 18:08:35 +00002873 SMLoc E = Parser.getTok().getLoc();
2874 if (Parser.getTok().isNot(AsmToken::RCurly))
2875 return Error(E, "'}' expected");
2876 Parser.Lex(); // Eat '}' token.
2877
Jim Grosbach27debd62011-12-13 21:48:29 +00002878 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002879 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002880
2881 // The ARM system instruction variants for LDM/STM have a '^' token here.
2882 if (Parser.getTok().is(AsmToken::Caret)) {
2883 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2884 Parser.Lex(); // Eat '^' token.
2885 }
2886
Bill Wendling50d0f582010-11-18 23:43:05 +00002887 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002888}
2889
Jim Grosbach98b05a52011-11-30 01:09:44 +00002890// Helper function to parse the lane index for vector lists.
2891ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002892parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2893 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002894 if (Parser.getTok().is(AsmToken::LBrac)) {
2895 Parser.Lex(); // Eat the '['.
2896 if (Parser.getTok().is(AsmToken::RBrac)) {
2897 // "Dn[]" is the 'all lanes' syntax.
2898 LaneKind = AllLanes;
2899 Parser.Lex(); // Eat the ']'.
2900 return MatchOperand_Success;
2901 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002902 const MCExpr *LaneIndex;
2903 SMLoc Loc = Parser.getTok().getLoc();
2904 if (getParser().ParseExpression(LaneIndex)) {
2905 Error(Loc, "illegal expression");
2906 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002907 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002908 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2909 if (!CE) {
2910 Error(Loc, "lane index must be empty or an integer");
2911 return MatchOperand_ParseFail;
2912 }
2913 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2914 Error(Parser.getTok().getLoc(), "']' expected");
2915 return MatchOperand_ParseFail;
2916 }
2917 Parser.Lex(); // Eat the ']'.
2918 int64_t Val = CE->getValue();
2919
2920 // FIXME: Make this range check context sensitive for .8, .16, .32.
2921 if (Val < 0 || Val > 7) {
2922 Error(Parser.getTok().getLoc(), "lane index out of range");
2923 return MatchOperand_ParseFail;
2924 }
2925 Index = Val;
2926 LaneKind = IndexedLane;
2927 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002928 }
2929 LaneKind = NoLanes;
2930 return MatchOperand_Success;
2931}
2932
Jim Grosbach862019c2011-10-18 23:02:30 +00002933// parse a vector register list
2934ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2935parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002936 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002937 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002938 SMLoc S = Parser.getTok().getLoc();
2939 // As an extension (to match gas), support a plain D register or Q register
2940 // (without encosing curly braces) as a single or double entry list,
2941 // respectively.
2942 if (Parser.getTok().is(AsmToken::Identifier)) {
2943 int Reg = tryParseRegister();
2944 if (Reg == -1)
2945 return MatchOperand_NoMatch;
2946 SMLoc E = Parser.getTok().getLoc();
2947 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002948 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002949 if (Res != MatchOperand_Success)
2950 return Res;
2951 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002952 case NoLanes:
2953 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002954 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002955 break;
2956 case AllLanes:
2957 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002958 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2959 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002960 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002961 case IndexedLane:
2962 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002963 LaneIndex,
2964 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002965 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002966 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002967 return MatchOperand_Success;
2968 }
2969 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2970 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002971 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002972 if (Res != MatchOperand_Success)
2973 return Res;
2974 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002975 case NoLanes:
2976 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00002977 // VLD1 wants a DPair register.
2978 // FIXME: Make the rest of the two-reg instructions want the same
2979 // thing.
2980 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
2981 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
2982
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002983 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002984 break;
2985 case AllLanes:
2986 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002987 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2988 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002989 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002990 case IndexedLane:
2991 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002992 LaneIndex,
2993 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002994 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002995 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002996 return MatchOperand_Success;
2997 }
2998 Error(S, "vector register expected");
2999 return MatchOperand_ParseFail;
3000 }
3001
3002 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003003 return MatchOperand_NoMatch;
3004
Jim Grosbach862019c2011-10-18 23:02:30 +00003005 Parser.Lex(); // Eat '{' token.
3006 SMLoc RegLoc = Parser.getTok().getLoc();
3007
3008 int Reg = tryParseRegister();
3009 if (Reg == -1) {
3010 Error(RegLoc, "register expected");
3011 return MatchOperand_ParseFail;
3012 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003013 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003014 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003015 unsigned FirstReg = Reg;
3016 // The list is of D registers, but we also allow Q regs and just interpret
3017 // them as the two D sub-registers.
3018 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3019 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003020 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3021 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003022 ++Reg;
3023 ++Count;
3024 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003025 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003026 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003027
Jim Grosbache43862b2011-11-15 23:19:15 +00003028 while (Parser.getTok().is(AsmToken::Comma) ||
3029 Parser.getTok().is(AsmToken::Minus)) {
3030 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003031 if (!Spacing)
3032 Spacing = 1; // Register range implies a single spaced list.
3033 else if (Spacing == 2) {
3034 Error(Parser.getTok().getLoc(),
3035 "sequential registers in double spaced list");
3036 return MatchOperand_ParseFail;
3037 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003038 Parser.Lex(); // Eat the minus.
3039 SMLoc EndLoc = Parser.getTok().getLoc();
3040 int EndReg = tryParseRegister();
3041 if (EndReg == -1) {
3042 Error(EndLoc, "register expected");
3043 return MatchOperand_ParseFail;
3044 }
3045 // Allow Q regs and just interpret them as the two D sub-registers.
3046 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3047 EndReg = getDRegFromQReg(EndReg) + 1;
3048 // If the register is the same as the start reg, there's nothing
3049 // more to do.
3050 if (Reg == EndReg)
3051 continue;
3052 // The register must be in the same register class as the first.
3053 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3054 Error(EndLoc, "invalid register in register list");
3055 return MatchOperand_ParseFail;
3056 }
3057 // Ranges must go from low to high.
3058 if (Reg > EndReg) {
3059 Error(EndLoc, "bad range in register list");
3060 return MatchOperand_ParseFail;
3061 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003062 // Parse the lane specifier if present.
3063 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003064 unsigned NextLaneIndex;
3065 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003066 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003067 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003068 Error(EndLoc, "mismatched lane index in register list");
3069 return MatchOperand_ParseFail;
3070 }
3071 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003072
3073 // Add all the registers in the range to the register list.
3074 Count += EndReg - Reg;
3075 Reg = EndReg;
3076 continue;
3077 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003078 Parser.Lex(); // Eat the comma.
3079 RegLoc = Parser.getTok().getLoc();
3080 int OldReg = Reg;
3081 Reg = tryParseRegister();
3082 if (Reg == -1) {
3083 Error(RegLoc, "register expected");
3084 return MatchOperand_ParseFail;
3085 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003086 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003087 // It's OK to use the enumeration values directly here rather, as the
3088 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003089 //
3090 // The list is of D registers, but we also allow Q regs and just interpret
3091 // them as the two D sub-registers.
3092 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003093 if (!Spacing)
3094 Spacing = 1; // Register range implies a single spaced list.
3095 else if (Spacing == 2) {
3096 Error(RegLoc,
3097 "invalid register in double-spaced list (must be 'D' register')");
3098 return MatchOperand_ParseFail;
3099 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003100 Reg = getDRegFromQReg(Reg);
3101 if (Reg != OldReg + 1) {
3102 Error(RegLoc, "non-contiguous register range");
3103 return MatchOperand_ParseFail;
3104 }
3105 ++Reg;
3106 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003107 // Parse the lane specifier if present.
3108 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003109 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003110 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003111 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003112 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003113 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003114 Error(EndLoc, "mismatched lane index in register list");
3115 return MatchOperand_ParseFail;
3116 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003117 continue;
3118 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003119 // Normal D register.
3120 // Figure out the register spacing (single or double) of the list if
3121 // we don't know it already.
3122 if (!Spacing)
3123 Spacing = 1 + (Reg == OldReg + 2);
3124
3125 // Just check that it's contiguous and keep going.
3126 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003127 Error(RegLoc, "non-contiguous register range");
3128 return MatchOperand_ParseFail;
3129 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003130 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003131 // Parse the lane specifier if present.
3132 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003133 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003134 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003135 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003136 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003137 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003138 Error(EndLoc, "mismatched lane index in register list");
3139 return MatchOperand_ParseFail;
3140 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003141 }
3142
3143 SMLoc E = Parser.getTok().getLoc();
3144 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3145 Error(E, "'}' expected");
3146 return MatchOperand_ParseFail;
3147 }
3148 Parser.Lex(); // Eat '}' token.
3149
Jim Grosbach98b05a52011-11-30 01:09:44 +00003150 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003151 case NoLanes:
Jim Grosbach28f08c92012-03-05 19:33:30 +00003152 if (Count == 2 && Spacing == 1)
3153 // VLD1 wants a DPair register.
3154 // FIXME: Make the rest of the two-reg instructions want the same
3155 // thing.
3156 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0,
3157 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3158
3159
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003160 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3161 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003162 break;
3163 case AllLanes:
3164 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003165 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003166 S, E));
3167 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003168 case IndexedLane:
3169 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003170 LaneIndex,
3171 (Spacing == 2),
3172 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003173 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003174 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003175 return MatchOperand_Success;
3176}
3177
Jim Grosbach43904292011-07-25 20:14:50 +00003178/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003179ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003180parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003181 SMLoc S = Parser.getTok().getLoc();
3182 const AsmToken &Tok = Parser.getTok();
3183 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3184 StringRef OptStr = Tok.getString();
3185
3186 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3187 .Case("sy", ARM_MB::SY)
3188 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003189 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003190 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003191 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003192 .Case("ishst", ARM_MB::ISHST)
3193 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003194 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003195 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003196 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003197 .Case("osh", ARM_MB::OSH)
3198 .Case("oshst", ARM_MB::OSHST)
3199 .Default(~0U);
3200
3201 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003202 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003203
3204 Parser.Lex(); // Eat identifier token.
3205 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003206 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003207}
3208
Jim Grosbach43904292011-07-25 20:14:50 +00003209/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003210ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003211parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003212 SMLoc S = Parser.getTok().getLoc();
3213 const AsmToken &Tok = Parser.getTok();
3214 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3215 StringRef IFlagsStr = Tok.getString();
3216
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003217 // An iflags string of "none" is interpreted to mean that none of the AIF
3218 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003219 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003220 if (IFlagsStr != "none") {
3221 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3222 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3223 .Case("a", ARM_PROC::A)
3224 .Case("i", ARM_PROC::I)
3225 .Case("f", ARM_PROC::F)
3226 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003227
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003228 // If some specific iflag is already set, it means that some letter is
3229 // present more than once, this is not acceptable.
3230 if (Flag == ~0U || (IFlags & Flag))
3231 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003232
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003233 IFlags |= Flag;
3234 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003235 }
3236
3237 Parser.Lex(); // Eat identifier token.
3238 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3239 return MatchOperand_Success;
3240}
3241
Jim Grosbach43904292011-07-25 20:14:50 +00003242/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003243ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003244parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003245 SMLoc S = Parser.getTok().getLoc();
3246 const AsmToken &Tok = Parser.getTok();
3247 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3248 StringRef Mask = Tok.getString();
3249
James Molloyacad68d2011-09-28 14:21:38 +00003250 if (isMClass()) {
3251 // See ARMv6-M 10.1.1
3252 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3253 .Case("apsr", 0)
3254 .Case("iapsr", 1)
3255 .Case("eapsr", 2)
3256 .Case("xpsr", 3)
3257 .Case("ipsr", 5)
3258 .Case("epsr", 6)
3259 .Case("iepsr", 7)
3260 .Case("msp", 8)
3261 .Case("psp", 9)
3262 .Case("primask", 16)
3263 .Case("basepri", 17)
3264 .Case("basepri_max", 18)
3265 .Case("faultmask", 19)
3266 .Case("control", 20)
3267 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003268
James Molloyacad68d2011-09-28 14:21:38 +00003269 if (FlagsVal == ~0U)
3270 return MatchOperand_NoMatch;
3271
3272 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3273 // basepri, basepri_max and faultmask only valid for V7m.
3274 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003275
James Molloyacad68d2011-09-28 14:21:38 +00003276 Parser.Lex(); // Eat identifier token.
3277 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3278 return MatchOperand_Success;
3279 }
3280
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003281 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3282 size_t Start = 0, Next = Mask.find('_');
3283 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003284 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003285 if (Next != StringRef::npos)
3286 Flags = Mask.slice(Next+1, Mask.size());
3287
3288 // FlagsVal contains the complete mask:
3289 // 3-0: Mask
3290 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3291 unsigned FlagsVal = 0;
3292
3293 if (SpecReg == "apsr") {
3294 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003295 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003296 .Case("g", 0x4) // same as CPSR_s
3297 .Case("nzcvqg", 0xc) // same as CPSR_fs
3298 .Default(~0U);
3299
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003300 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003301 if (!Flags.empty())
3302 return MatchOperand_NoMatch;
3303 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003304 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003305 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003306 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003307 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3308 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003309 for (int i = 0, e = Flags.size(); i != e; ++i) {
3310 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3311 .Case("c", 1)
3312 .Case("x", 2)
3313 .Case("s", 4)
3314 .Case("f", 8)
3315 .Default(~0U);
3316
3317 // If some specific flag is already set, it means that some letter is
3318 // present more than once, this is not acceptable.
3319 if (FlagsVal == ~0U || (FlagsVal & Flag))
3320 return MatchOperand_NoMatch;
3321 FlagsVal |= Flag;
3322 }
3323 } else // No match for special register.
3324 return MatchOperand_NoMatch;
3325
Owen Anderson7784f1d2011-10-21 18:43:28 +00003326 // Special register without flags is NOT equivalent to "fc" flags.
3327 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3328 // two lines would enable gas compatibility at the expense of breaking
3329 // round-tripping.
3330 //
3331 // if (!FlagsVal)
3332 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003333
3334 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3335 if (SpecReg == "spsr")
3336 FlagsVal |= 16;
3337
3338 Parser.Lex(); // Eat identifier token.
3339 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3340 return MatchOperand_Success;
3341}
3342
Jim Grosbachf6c05252011-07-21 17:23:04 +00003343ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3344parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3345 int Low, int High) {
3346 const AsmToken &Tok = Parser.getTok();
3347 if (Tok.isNot(AsmToken::Identifier)) {
3348 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3349 return MatchOperand_ParseFail;
3350 }
3351 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003352 std::string LowerOp = Op.lower();
3353 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003354 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3355 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3356 return MatchOperand_ParseFail;
3357 }
3358 Parser.Lex(); // Eat shift type token.
3359
3360 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003361 if (Parser.getTok().isNot(AsmToken::Hash) &&
3362 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003363 Error(Parser.getTok().getLoc(), "'#' expected");
3364 return MatchOperand_ParseFail;
3365 }
3366 Parser.Lex(); // Eat hash token.
3367
3368 const MCExpr *ShiftAmount;
3369 SMLoc Loc = Parser.getTok().getLoc();
3370 if (getParser().ParseExpression(ShiftAmount)) {
3371 Error(Loc, "illegal expression");
3372 return MatchOperand_ParseFail;
3373 }
3374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3375 if (!CE) {
3376 Error(Loc, "constant expression expected");
3377 return MatchOperand_ParseFail;
3378 }
3379 int Val = CE->getValue();
3380 if (Val < Low || Val > High) {
3381 Error(Loc, "immediate value out of range");
3382 return MatchOperand_ParseFail;
3383 }
3384
3385 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3386
3387 return MatchOperand_Success;
3388}
3389
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003390ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3391parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3392 const AsmToken &Tok = Parser.getTok();
3393 SMLoc S = Tok.getLoc();
3394 if (Tok.isNot(AsmToken::Identifier)) {
3395 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3396 return MatchOperand_ParseFail;
3397 }
3398 int Val = StringSwitch<int>(Tok.getString())
3399 .Case("be", 1)
3400 .Case("le", 0)
3401 .Default(-1);
3402 Parser.Lex(); // Eat the token.
3403
3404 if (Val == -1) {
3405 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3406 return MatchOperand_ParseFail;
3407 }
3408 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3409 getContext()),
3410 S, Parser.getTok().getLoc()));
3411 return MatchOperand_Success;
3412}
3413
Jim Grosbach580f4a92011-07-25 22:20:28 +00003414/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3415/// instructions. Legal values are:
3416/// lsl #n 'n' in [0,31]
3417/// asr #n 'n' in [1,32]
3418/// n == 32 encoded as n == 0.
3419ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3420parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3421 const AsmToken &Tok = Parser.getTok();
3422 SMLoc S = Tok.getLoc();
3423 if (Tok.isNot(AsmToken::Identifier)) {
3424 Error(S, "shift operator 'asr' or 'lsl' expected");
3425 return MatchOperand_ParseFail;
3426 }
3427 StringRef ShiftName = Tok.getString();
3428 bool isASR;
3429 if (ShiftName == "lsl" || ShiftName == "LSL")
3430 isASR = false;
3431 else if (ShiftName == "asr" || ShiftName == "ASR")
3432 isASR = true;
3433 else {
3434 Error(S, "shift operator 'asr' or 'lsl' expected");
3435 return MatchOperand_ParseFail;
3436 }
3437 Parser.Lex(); // Eat the operator.
3438
3439 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003440 if (Parser.getTok().isNot(AsmToken::Hash) &&
3441 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003442 Error(Parser.getTok().getLoc(), "'#' expected");
3443 return MatchOperand_ParseFail;
3444 }
3445 Parser.Lex(); // Eat hash token.
3446
3447 const MCExpr *ShiftAmount;
3448 SMLoc E = Parser.getTok().getLoc();
3449 if (getParser().ParseExpression(ShiftAmount)) {
3450 Error(E, "malformed shift expression");
3451 return MatchOperand_ParseFail;
3452 }
3453 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3454 if (!CE) {
3455 Error(E, "shift amount must be an immediate");
3456 return MatchOperand_ParseFail;
3457 }
3458
3459 int64_t Val = CE->getValue();
3460 if (isASR) {
3461 // Shift amount must be in [1,32]
3462 if (Val < 1 || Val > 32) {
3463 Error(E, "'asr' shift amount must be in range [1,32]");
3464 return MatchOperand_ParseFail;
3465 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003466 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3467 if (isThumb() && Val == 32) {
3468 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3469 return MatchOperand_ParseFail;
3470 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003471 if (Val == 32) Val = 0;
3472 } else {
3473 // Shift amount must be in [1,32]
3474 if (Val < 0 || Val > 31) {
3475 Error(E, "'lsr' shift amount must be in range [0,31]");
3476 return MatchOperand_ParseFail;
3477 }
3478 }
3479
3480 E = Parser.getTok().getLoc();
3481 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3482
3483 return MatchOperand_Success;
3484}
3485
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003486/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3487/// of instructions. Legal values are:
3488/// ror #n 'n' in {0, 8, 16, 24}
3489ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3490parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3491 const AsmToken &Tok = Parser.getTok();
3492 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003493 if (Tok.isNot(AsmToken::Identifier))
3494 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003495 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003496 if (ShiftName != "ror" && ShiftName != "ROR")
3497 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003498 Parser.Lex(); // Eat the operator.
3499
3500 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003501 if (Parser.getTok().isNot(AsmToken::Hash) &&
3502 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003503 Error(Parser.getTok().getLoc(), "'#' expected");
3504 return MatchOperand_ParseFail;
3505 }
3506 Parser.Lex(); // Eat hash token.
3507
3508 const MCExpr *ShiftAmount;
3509 SMLoc E = Parser.getTok().getLoc();
3510 if (getParser().ParseExpression(ShiftAmount)) {
3511 Error(E, "malformed rotate expression");
3512 return MatchOperand_ParseFail;
3513 }
3514 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3515 if (!CE) {
3516 Error(E, "rotate amount must be an immediate");
3517 return MatchOperand_ParseFail;
3518 }
3519
3520 int64_t Val = CE->getValue();
3521 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3522 // normally, zero is represented in asm by omitting the rotate operand
3523 // entirely.
3524 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3525 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3526 return MatchOperand_ParseFail;
3527 }
3528
3529 E = Parser.getTok().getLoc();
3530 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3531
3532 return MatchOperand_Success;
3533}
3534
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003535ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3536parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3537 SMLoc S = Parser.getTok().getLoc();
3538 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003539 if (Parser.getTok().isNot(AsmToken::Hash) &&
3540 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003541 Error(Parser.getTok().getLoc(), "'#' expected");
3542 return MatchOperand_ParseFail;
3543 }
3544 Parser.Lex(); // Eat hash token.
3545
3546 const MCExpr *LSBExpr;
3547 SMLoc E = Parser.getTok().getLoc();
3548 if (getParser().ParseExpression(LSBExpr)) {
3549 Error(E, "malformed immediate expression");
3550 return MatchOperand_ParseFail;
3551 }
3552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3553 if (!CE) {
3554 Error(E, "'lsb' operand must be an immediate");
3555 return MatchOperand_ParseFail;
3556 }
3557
3558 int64_t LSB = CE->getValue();
3559 // The LSB must be in the range [0,31]
3560 if (LSB < 0 || LSB > 31) {
3561 Error(E, "'lsb' operand must be in the range [0,31]");
3562 return MatchOperand_ParseFail;
3563 }
3564 E = Parser.getTok().getLoc();
3565
3566 // Expect another immediate operand.
3567 if (Parser.getTok().isNot(AsmToken::Comma)) {
3568 Error(Parser.getTok().getLoc(), "too few operands");
3569 return MatchOperand_ParseFail;
3570 }
3571 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003572 if (Parser.getTok().isNot(AsmToken::Hash) &&
3573 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003574 Error(Parser.getTok().getLoc(), "'#' expected");
3575 return MatchOperand_ParseFail;
3576 }
3577 Parser.Lex(); // Eat hash token.
3578
3579 const MCExpr *WidthExpr;
3580 if (getParser().ParseExpression(WidthExpr)) {
3581 Error(E, "malformed immediate expression");
3582 return MatchOperand_ParseFail;
3583 }
3584 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3585 if (!CE) {
3586 Error(E, "'width' operand must be an immediate");
3587 return MatchOperand_ParseFail;
3588 }
3589
3590 int64_t Width = CE->getValue();
3591 // The LSB must be in the range [1,32-lsb]
3592 if (Width < 1 || Width > 32 - LSB) {
3593 Error(E, "'width' operand must be in the range [1,32-lsb]");
3594 return MatchOperand_ParseFail;
3595 }
3596 E = Parser.getTok().getLoc();
3597
3598 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3599
3600 return MatchOperand_Success;
3601}
3602
Jim Grosbach7ce05792011-08-03 23:50:40 +00003603ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3604parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3605 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003606 // postidx_reg := '+' register {, shift}
3607 // | '-' register {, shift}
3608 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003609
3610 // This method must return MatchOperand_NoMatch without consuming any tokens
3611 // in the case where there is no match, as other alternatives take other
3612 // parse methods.
3613 AsmToken Tok = Parser.getTok();
3614 SMLoc S = Tok.getLoc();
3615 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003616 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003617 int Reg = -1;
3618 if (Tok.is(AsmToken::Plus)) {
3619 Parser.Lex(); // Eat the '+' token.
3620 haveEaten = true;
3621 } else if (Tok.is(AsmToken::Minus)) {
3622 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003623 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003624 haveEaten = true;
3625 }
3626 if (Parser.getTok().is(AsmToken::Identifier))
3627 Reg = tryParseRegister();
3628 if (Reg == -1) {
3629 if (!haveEaten)
3630 return MatchOperand_NoMatch;
3631 Error(Parser.getTok().getLoc(), "register expected");
3632 return MatchOperand_ParseFail;
3633 }
3634 SMLoc E = Parser.getTok().getLoc();
3635
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003636 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3637 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003638 if (Parser.getTok().is(AsmToken::Comma)) {
3639 Parser.Lex(); // Eat the ','.
3640 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3641 return MatchOperand_ParseFail;
3642 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003643
3644 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3645 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003646
3647 return MatchOperand_Success;
3648}
3649
Jim Grosbach251bf252011-08-10 21:56:18 +00003650ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3651parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3652 // Check for a post-index addressing register operand. Specifically:
3653 // am3offset := '+' register
3654 // | '-' register
3655 // | register
3656 // | # imm
3657 // | # + imm
3658 // | # - imm
3659
3660 // This method must return MatchOperand_NoMatch without consuming any tokens
3661 // in the case where there is no match, as other alternatives take other
3662 // parse methods.
3663 AsmToken Tok = Parser.getTok();
3664 SMLoc S = Tok.getLoc();
3665
3666 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003667 if (Parser.getTok().is(AsmToken::Hash) ||
3668 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003669 Parser.Lex(); // Eat the '#'.
3670 // Explicitly look for a '-', as we need to encode negative zero
3671 // differently.
3672 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3673 const MCExpr *Offset;
3674 if (getParser().ParseExpression(Offset))
3675 return MatchOperand_ParseFail;
3676 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3677 if (!CE) {
3678 Error(S, "constant expression expected");
3679 return MatchOperand_ParseFail;
3680 }
3681 SMLoc E = Tok.getLoc();
3682 // Negative zero is encoded as the flag value INT32_MIN.
3683 int32_t Val = CE->getValue();
3684 if (isNegative && Val == 0)
3685 Val = INT32_MIN;
3686
3687 Operands.push_back(
3688 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3689
3690 return MatchOperand_Success;
3691 }
3692
3693
3694 bool haveEaten = false;
3695 bool isAdd = true;
3696 int Reg = -1;
3697 if (Tok.is(AsmToken::Plus)) {
3698 Parser.Lex(); // Eat the '+' token.
3699 haveEaten = true;
3700 } else if (Tok.is(AsmToken::Minus)) {
3701 Parser.Lex(); // Eat the '-' token.
3702 isAdd = false;
3703 haveEaten = true;
3704 }
3705 if (Parser.getTok().is(AsmToken::Identifier))
3706 Reg = tryParseRegister();
3707 if (Reg == -1) {
3708 if (!haveEaten)
3709 return MatchOperand_NoMatch;
3710 Error(Parser.getTok().getLoc(), "register expected");
3711 return MatchOperand_ParseFail;
3712 }
3713 SMLoc E = Parser.getTok().getLoc();
3714
3715 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3716 0, S, E));
3717
3718 return MatchOperand_Success;
3719}
3720
Jim Grosbacha77295d2011-09-08 22:07:06 +00003721/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3722/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3723/// when they refer multiple MIOperands inside a single one.
3724bool ARMAsmParser::
3725cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3726 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3727 // Rt, Rt2
3728 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3729 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3730 // Create a writeback register dummy placeholder.
3731 Inst.addOperand(MCOperand::CreateReg(0));
3732 // addr
3733 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3734 // pred
3735 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3736 return true;
3737}
3738
3739/// cvtT2StrdPre - Convert parsed operands to MCInst.
3740/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3741/// when they refer multiple MIOperands inside a single one.
3742bool ARMAsmParser::
3743cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3744 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3745 // Create a writeback register dummy placeholder.
3746 Inst.addOperand(MCOperand::CreateReg(0));
3747 // Rt, Rt2
3748 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3749 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3750 // addr
3751 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3752 // pred
3753 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3754 return true;
3755}
3756
Jim Grosbacheeec0252011-09-08 00:39:19 +00003757/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3758/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3759/// when they refer multiple MIOperands inside a single one.
3760bool ARMAsmParser::
3761cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3762 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3763 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3764
3765 // Create a writeback register dummy placeholder.
3766 Inst.addOperand(MCOperand::CreateImm(0));
3767
3768 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3769 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3770 return true;
3771}
3772
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003773/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3774/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3775/// when they refer multiple MIOperands inside a single one.
3776bool ARMAsmParser::
3777cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3778 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3779 // Create a writeback register dummy placeholder.
3780 Inst.addOperand(MCOperand::CreateImm(0));
3781 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3782 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3783 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3784 return true;
3785}
3786
Jim Grosbach1355cf12011-07-26 17:10:22 +00003787/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003788/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3789/// when they refer multiple MIOperands inside a single one.
3790bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003791cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003792 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3793 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3794
3795 // Create a writeback register dummy placeholder.
3796 Inst.addOperand(MCOperand::CreateImm(0));
3797
Jim Grosbach7ce05792011-08-03 23:50:40 +00003798 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003799 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3800 return true;
3801}
3802
Owen Anderson9ab0f252011-08-26 20:43:14 +00003803/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3804/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3805/// when they refer multiple MIOperands inside a single one.
3806bool ARMAsmParser::
3807cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3808 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3809 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3810
3811 // Create a writeback register dummy placeholder.
3812 Inst.addOperand(MCOperand::CreateImm(0));
3813
3814 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3815 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3816 return true;
3817}
3818
3819
Jim Grosbach548340c2011-08-11 19:22:40 +00003820/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3821/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3822/// when they refer multiple MIOperands inside a single one.
3823bool ARMAsmParser::
3824cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3825 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3826 // Create a writeback register dummy placeholder.
3827 Inst.addOperand(MCOperand::CreateImm(0));
3828 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3829 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3830 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3831 return true;
3832}
3833
Jim Grosbach1355cf12011-07-26 17:10:22 +00003834/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003835/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3836/// when they refer multiple MIOperands inside a single one.
3837bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003838cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003839 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3840 // Create a writeback register dummy placeholder.
3841 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003842 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3843 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3844 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003845 return true;
3846}
3847
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003848/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3849/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3850/// when they refer multiple MIOperands inside a single one.
3851bool ARMAsmParser::
3852cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3853 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3854 // Create a writeback register dummy placeholder.
3855 Inst.addOperand(MCOperand::CreateImm(0));
3856 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3857 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3858 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3859 return true;
3860}
3861
Jim Grosbach7ce05792011-08-03 23:50:40 +00003862/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3863/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3864/// when they refer multiple MIOperands inside a single one.
3865bool ARMAsmParser::
3866cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3867 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3868 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003869 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003870 // Create a writeback register dummy placeholder.
3871 Inst.addOperand(MCOperand::CreateImm(0));
3872 // addr
3873 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3874 // offset
3875 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3876 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003877 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3878 return true;
3879}
3880
Jim Grosbach7ce05792011-08-03 23:50:40 +00003881/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003882/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3883/// when they refer multiple MIOperands inside a single one.
3884bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003885cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3886 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3887 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003888 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003889 // Create a writeback register dummy placeholder.
3890 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003891 // addr
3892 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3893 // offset
3894 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3895 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003896 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3897 return true;
3898}
3899
Jim Grosbach7ce05792011-08-03 23:50:40 +00003900/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003901/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3902/// when they refer multiple MIOperands inside a single one.
3903bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003904cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3905 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003906 // Create a writeback register dummy placeholder.
3907 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003908 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003909 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003910 // addr
3911 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3912 // offset
3913 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3914 // pred
3915 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3916 return true;
3917}
3918
3919/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3920/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3921/// when they refer multiple MIOperands inside a single one.
3922bool ARMAsmParser::
3923cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3924 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3925 // Create a writeback register dummy placeholder.
3926 Inst.addOperand(MCOperand::CreateImm(0));
3927 // Rt
3928 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3929 // addr
3930 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3931 // offset
3932 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3933 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003934 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3935 return true;
3936}
3937
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003938/// cvtLdrdPre - Convert parsed operands to MCInst.
3939/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3940/// when they refer multiple MIOperands inside a single one.
3941bool ARMAsmParser::
3942cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3943 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3944 // Rt, Rt2
3945 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3946 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3947 // Create a writeback register dummy placeholder.
3948 Inst.addOperand(MCOperand::CreateImm(0));
3949 // addr
3950 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3951 // pred
3952 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3953 return true;
3954}
3955
Jim Grosbach14605d12011-08-11 20:28:23 +00003956/// cvtStrdPre - Convert parsed operands to MCInst.
3957/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3958/// when they refer multiple MIOperands inside a single one.
3959bool ARMAsmParser::
3960cvtStrdPre(MCInst &Inst, unsigned Opcode,
3961 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3962 // Create a writeback register dummy placeholder.
3963 Inst.addOperand(MCOperand::CreateImm(0));
3964 // Rt, Rt2
3965 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3966 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3967 // addr
3968 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3969 // pred
3970 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3971 return true;
3972}
3973
Jim Grosbach623a4542011-08-10 22:42:16 +00003974/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3975/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3976/// when they refer multiple MIOperands inside a single one.
3977bool ARMAsmParser::
3978cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3979 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3980 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3981 // Create a writeback register dummy placeholder.
3982 Inst.addOperand(MCOperand::CreateImm(0));
3983 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3984 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3985 return true;
3986}
3987
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003988/// cvtThumbMultiple- Convert parsed operands to MCInst.
3989/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3990/// when they refer multiple MIOperands inside a single one.
3991bool ARMAsmParser::
3992cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3993 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3994 // The second source operand must be the same register as the destination
3995 // operand.
3996 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003997 (((ARMOperand*)Operands[3])->getReg() !=
3998 ((ARMOperand*)Operands[5])->getReg()) &&
3999 (((ARMOperand*)Operands[3])->getReg() !=
4000 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004001 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004002 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004003 return false;
4004 }
4005 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4006 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004007 // If we have a three-operand form, make sure to set Rn to be the operand
4008 // that isn't the same as Rd.
4009 unsigned RegOp = 4;
4010 if (Operands.size() == 6 &&
4011 ((ARMOperand*)Operands[4])->getReg() ==
4012 ((ARMOperand*)Operands[3])->getReg())
4013 RegOp = 5;
4014 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4015 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004016 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4017
4018 return true;
4019}
Jim Grosbach623a4542011-08-10 22:42:16 +00004020
Jim Grosbach12431322011-10-24 22:16:58 +00004021bool ARMAsmParser::
4022cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4023 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4024 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004025 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004026 // Create a writeback register dummy placeholder.
4027 Inst.addOperand(MCOperand::CreateImm(0));
4028 // Vn
4029 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4030 // pred
4031 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4032 return true;
4033}
4034
4035bool ARMAsmParser::
4036cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4037 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4038 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004039 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004040 // Create a writeback register dummy placeholder.
4041 Inst.addOperand(MCOperand::CreateImm(0));
4042 // Vn
4043 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4044 // Vm
4045 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4046 // pred
4047 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4048 return true;
4049}
4050
Jim Grosbach4334e032011-10-31 21:50:31 +00004051bool ARMAsmParser::
4052cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4053 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4054 // Create a writeback register dummy placeholder.
4055 Inst.addOperand(MCOperand::CreateImm(0));
4056 // Vn
4057 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4058 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004059 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004060 // pred
4061 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4062 return true;
4063}
4064
4065bool ARMAsmParser::
4066cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4067 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4068 // Create a writeback register dummy placeholder.
4069 Inst.addOperand(MCOperand::CreateImm(0));
4070 // Vn
4071 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4072 // Vm
4073 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4074 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004075 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004076 // pred
4077 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4078 return true;
4079}
4080
Bill Wendlinge7176102010-11-06 22:36:58 +00004081/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004082/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004083bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004084parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004085 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004086 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004087 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004088 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004089 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004090
Sean Callanan18b83232010-01-19 21:44:56 +00004091 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004092 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004093 if (BaseRegNum == -1)
4094 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004095
Daniel Dunbar05710932011-01-18 05:34:17 +00004096 // The next token must either be a comma or a closing bracket.
4097 const AsmToken &Tok = Parser.getTok();
4098 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004099 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004100
Jim Grosbach7ce05792011-08-03 23:50:40 +00004101 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004102 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004103 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004104
Jim Grosbach7ce05792011-08-03 23:50:40 +00004105 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004106 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004107
Jim Grosbachfb12f352011-09-19 18:42:21 +00004108 // If there's a pre-indexing writeback marker, '!', just add it as a token
4109 // operand. It's rather odd, but syntactically valid.
4110 if (Parser.getTok().is(AsmToken::Exclaim)) {
4111 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4112 Parser.Lex(); // Eat the '!'.
4113 }
4114
Jim Grosbach7ce05792011-08-03 23:50:40 +00004115 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004116 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004117
Jim Grosbach7ce05792011-08-03 23:50:40 +00004118 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4119 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004120
Jim Grosbach57dcb852011-10-11 17:29:55 +00004121 // If we have a ':', it's an alignment specifier.
4122 if (Parser.getTok().is(AsmToken::Colon)) {
4123 Parser.Lex(); // Eat the ':'.
4124 E = Parser.getTok().getLoc();
4125
4126 const MCExpr *Expr;
4127 if (getParser().ParseExpression(Expr))
4128 return true;
4129
4130 // The expression has to be a constant. Memory references with relocations
4131 // don't come through here, as they use the <label> forms of the relevant
4132 // instructions.
4133 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4134 if (!CE)
4135 return Error (E, "constant expression expected");
4136
4137 unsigned Align = 0;
4138 switch (CE->getValue()) {
4139 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004140 return Error(E,
4141 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4142 case 16: Align = 2; break;
4143 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004144 case 64: Align = 8; break;
4145 case 128: Align = 16; break;
4146 case 256: Align = 32; break;
4147 }
4148
4149 // Now we should have the closing ']'
4150 E = Parser.getTok().getLoc();
4151 if (Parser.getTok().isNot(AsmToken::RBrac))
4152 return Error(E, "']' expected");
4153 Parser.Lex(); // Eat right bracket token.
4154
4155 // Don't worry about range checking the value here. That's handled by
4156 // the is*() predicates.
4157 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4158 ARM_AM::no_shift, 0, Align,
4159 false, S, E));
4160
4161 // If there's a pre-indexing writeback marker, '!', just add it as a token
4162 // operand.
4163 if (Parser.getTok().is(AsmToken::Exclaim)) {
4164 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4165 Parser.Lex(); // Eat the '!'.
4166 }
4167
4168 return false;
4169 }
4170
4171 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004172 // offset. Be friendly and also accept a plain integer (without a leading
4173 // hash) for gas compatibility.
4174 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004175 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004176 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004177 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004178 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004179 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004180
Owen Anderson0da10cf2011-08-29 19:36:44 +00004181 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004182 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004183 if (getParser().ParseExpression(Offset))
4184 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004185
4186 // The expression has to be a constant. Memory references with relocations
4187 // don't come through here, as they use the <label> forms of the relevant
4188 // instructions.
4189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4190 if (!CE)
4191 return Error (E, "constant expression expected");
4192
Owen Anderson0da10cf2011-08-29 19:36:44 +00004193 // If the constant was #-0, represent it as INT32_MIN.
4194 int32_t Val = CE->getValue();
4195 if (isNegative && Val == 0)
4196 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4197
Jim Grosbach7ce05792011-08-03 23:50:40 +00004198 // Now we should have the closing ']'
4199 E = Parser.getTok().getLoc();
4200 if (Parser.getTok().isNot(AsmToken::RBrac))
4201 return Error(E, "']' expected");
4202 Parser.Lex(); // Eat right bracket token.
4203
4204 // Don't worry about range checking the value here. That's handled by
4205 // the is*() predicates.
4206 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004207 ARM_AM::no_shift, 0, 0,
4208 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004209
4210 // If there's a pre-indexing writeback marker, '!', just add it as a token
4211 // operand.
4212 if (Parser.getTok().is(AsmToken::Exclaim)) {
4213 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4214 Parser.Lex(); // Eat the '!'.
4215 }
4216
4217 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004218 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004219
4220 // The register offset is optionally preceded by a '+' or '-'
4221 bool isNegative = false;
4222 if (Parser.getTok().is(AsmToken::Minus)) {
4223 isNegative = true;
4224 Parser.Lex(); // Eat the '-'.
4225 } else if (Parser.getTok().is(AsmToken::Plus)) {
4226 // Nothing to do.
4227 Parser.Lex(); // Eat the '+'.
4228 }
4229
4230 E = Parser.getTok().getLoc();
4231 int OffsetRegNum = tryParseRegister();
4232 if (OffsetRegNum == -1)
4233 return Error(E, "register expected");
4234
4235 // If there's a shift operator, handle it.
4236 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004237 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004238 if (Parser.getTok().is(AsmToken::Comma)) {
4239 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004240 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004241 return true;
4242 }
4243
4244 // Now we should have the closing ']'
4245 E = Parser.getTok().getLoc();
4246 if (Parser.getTok().isNot(AsmToken::RBrac))
4247 return Error(E, "']' expected");
4248 Parser.Lex(); // Eat right bracket token.
4249
4250 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004251 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004252 S, E));
4253
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004254 // If there's a pre-indexing writeback marker, '!', just add it as a token
4255 // operand.
4256 if (Parser.getTok().is(AsmToken::Exclaim)) {
4257 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4258 Parser.Lex(); // Eat the '!'.
4259 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004260
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004261 return false;
4262}
4263
Jim Grosbach7ce05792011-08-03 23:50:40 +00004264/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004265/// ( lsl | lsr | asr | ror ) , # shift_amount
4266/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004267/// return true if it parses a shift otherwise it returns false.
4268bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4269 unsigned &Amount) {
4270 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004271 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004272 if (Tok.isNot(AsmToken::Identifier))
4273 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004274 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004275 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4276 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004277 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004278 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004279 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004280 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004281 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004282 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004283 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004284 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004285 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004286 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004287 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004288 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004289
Jim Grosbach7ce05792011-08-03 23:50:40 +00004290 // rrx stands alone.
4291 Amount = 0;
4292 if (St != ARM_AM::rrx) {
4293 Loc = Parser.getTok().getLoc();
4294 // A '#' and a shift amount.
4295 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004296 if (HashTok.isNot(AsmToken::Hash) &&
4297 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004298 return Error(HashTok.getLoc(), "'#' expected");
4299 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004300
Jim Grosbach7ce05792011-08-03 23:50:40 +00004301 const MCExpr *Expr;
4302 if (getParser().ParseExpression(Expr))
4303 return true;
4304 // Range check the immediate.
4305 // lsl, ror: 0 <= imm <= 31
4306 // lsr, asr: 0 <= imm <= 32
4307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4308 if (!CE)
4309 return Error(Loc, "shift amount must be an immediate");
4310 int64_t Imm = CE->getValue();
4311 if (Imm < 0 ||
4312 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4313 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4314 return Error(Loc, "immediate shift value out of range");
4315 Amount = Imm;
4316 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004317
4318 return false;
4319}
4320
Jim Grosbach9d390362011-10-03 23:38:36 +00004321/// parseFPImm - A floating point immediate expression operand.
4322ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4323parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004324 // Anything that can accept a floating point constant as an operand
4325 // needs to go through here, as the regular ParseExpression is
4326 // integer only.
4327 //
4328 // This routine still creates a generic Immediate operand, containing
4329 // a bitcast of the 64-bit floating point value. The various operands
4330 // that accept floats can check whether the value is valid for them
4331 // via the standard is*() predicates.
4332
Jim Grosbach9d390362011-10-03 23:38:36 +00004333 SMLoc S = Parser.getTok().getLoc();
4334
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004335 if (Parser.getTok().isNot(AsmToken::Hash) &&
4336 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004337 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004338
4339 // Disambiguate the VMOV forms that can accept an FP immediate.
4340 // vmov.f32 <sreg>, #imm
4341 // vmov.f64 <dreg>, #imm
4342 // vmov.f32 <dreg>, #imm @ vector f32x2
4343 // vmov.f32 <qreg>, #imm @ vector f32x4
4344 //
4345 // There are also the NEON VMOV instructions which expect an
4346 // integer constant. Make sure we don't try to parse an FPImm
4347 // for these:
4348 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4349 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4350 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4351 TyOp->getToken() != ".f64"))
4352 return MatchOperand_NoMatch;
4353
Jim Grosbach9d390362011-10-03 23:38:36 +00004354 Parser.Lex(); // Eat the '#'.
4355
4356 // Handle negation, as that still comes through as a separate token.
4357 bool isNegative = false;
4358 if (Parser.getTok().is(AsmToken::Minus)) {
4359 isNegative = true;
4360 Parser.Lex();
4361 }
4362 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004363 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004364 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004365 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004366 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4367 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004368 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004369 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004370 Operands.push_back(ARMOperand::CreateImm(
4371 MCConstantExpr::Create(IntVal, getContext()),
4372 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004373 return MatchOperand_Success;
4374 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004375 // Also handle plain integers. Instructions which allow floating point
4376 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004377 if (Tok.is(AsmToken::Integer)) {
4378 int64_t Val = Tok.getIntVal();
4379 Parser.Lex(); // Eat the token.
4380 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004381 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004382 return MatchOperand_ParseFail;
4383 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004384 double RealVal = ARM_AM::getFPImmFloat(Val);
4385 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4386 Operands.push_back(ARMOperand::CreateImm(
4387 MCConstantExpr::Create(Val, getContext()), S,
4388 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004389 return MatchOperand_Success;
4390 }
4391
Jim Grosbachae69f702012-01-19 02:47:30 +00004392 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004393 return MatchOperand_ParseFail;
4394}
Jim Grosbach51222d12012-01-20 18:09:51 +00004395
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004396/// Parse a arm instruction operand. For now this parses the operand regardless
4397/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004398bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004399 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004400 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004401
4402 // Check if the current operand has a custom associated parser, if so, try to
4403 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004404 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4405 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004406 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004407 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4408 // there was a match, but an error occurred, in which case, just return that
4409 // the operand parsing failed.
4410 if (ResTy == MatchOperand_ParseFail)
4411 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004412
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004413 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004414 default:
4415 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004416 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004417 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004418 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004419 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004420 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004421 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004422 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004423 else if (Res == -1) // irrecoverable error
4424 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004425 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004426 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4427 S = Parser.getTok().getLoc();
4428 Parser.Lex();
4429 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4430 return false;
4431 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004432
4433 // Fall though for the Identifier case that is not a register or a
4434 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004435 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004436 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004437 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004438 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004439 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004440 // This was not a register so parse other operands that start with an
4441 // identifier (like labels) as expressions and create them as immediates.
4442 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004443 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004444 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004445 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004446 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004447 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4448 return false;
4449 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004450 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004451 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004452 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004453 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004454 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004455 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004456 // #42 -> immediate.
4457 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004458 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004459 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004460 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004461 const MCExpr *ImmVal;
4462 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004463 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004464 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004465 if (CE) {
4466 int32_t Val = CE->getValue();
4467 if (isNegative && Val == 0)
4468 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004469 }
Sean Callanan76264762010-04-02 22:27:05 +00004470 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004471 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4472 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004473 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004474 case AsmToken::Colon: {
4475 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004476 // FIXME: Check it's an expression prefix,
4477 // e.g. (FOO - :lower16:BAR) isn't legal.
4478 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004479 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004480 return true;
4481
Evan Cheng75972122011-01-13 07:58:56 +00004482 const MCExpr *SubExprVal;
4483 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004484 return true;
4485
Evan Cheng75972122011-01-13 07:58:56 +00004486 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4487 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004488 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004489 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004490 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004491 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004492 }
4493}
4494
Jim Grosbach1355cf12011-07-26 17:10:22 +00004495// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004496// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004497bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004498 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004499
4500 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004501 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004502 Parser.Lex(); // Eat ':'
4503
4504 if (getLexer().isNot(AsmToken::Identifier)) {
4505 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4506 return true;
4507 }
4508
4509 StringRef IDVal = Parser.getTok().getIdentifier();
4510 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004511 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004512 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004513 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004514 } else {
4515 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4516 return true;
4517 }
4518 Parser.Lex();
4519
4520 if (getLexer().isNot(AsmToken::Colon)) {
4521 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4522 return true;
4523 }
4524 Parser.Lex(); // Eat the last ':'
4525 return false;
4526}
4527
Daniel Dunbar352e1482011-01-11 15:59:50 +00004528/// \brief Given a mnemonic, split out possible predication code and carry
4529/// setting letters to form a canonical mnemonic and flags.
4530//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004531// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004532// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004533StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004534 unsigned &PredicationCode,
4535 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004536 unsigned &ProcessorIMod,
4537 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004538 PredicationCode = ARMCC::AL;
4539 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004540 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004541
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004542 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004543 //
4544 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004545 if ((Mnemonic == "movs" && isThumb()) ||
4546 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4547 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4548 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4549 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4550 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4551 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004552 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4553 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004554 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004555
Jim Grosbach3f00e312011-07-11 17:09:57 +00004556 // First, split out any predication code. Ignore mnemonics we know aren't
4557 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004558 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004559 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004560 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004561 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004562 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4563 .Case("eq", ARMCC::EQ)
4564 .Case("ne", ARMCC::NE)
4565 .Case("hs", ARMCC::HS)
4566 .Case("cs", ARMCC::HS)
4567 .Case("lo", ARMCC::LO)
4568 .Case("cc", ARMCC::LO)
4569 .Case("mi", ARMCC::MI)
4570 .Case("pl", ARMCC::PL)
4571 .Case("vs", ARMCC::VS)
4572 .Case("vc", ARMCC::VC)
4573 .Case("hi", ARMCC::HI)
4574 .Case("ls", ARMCC::LS)
4575 .Case("ge", ARMCC::GE)
4576 .Case("lt", ARMCC::LT)
4577 .Case("gt", ARMCC::GT)
4578 .Case("le", ARMCC::LE)
4579 .Case("al", ARMCC::AL)
4580 .Default(~0U);
4581 if (CC != ~0U) {
4582 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4583 PredicationCode = CC;
4584 }
Bill Wendling52925b62010-10-29 23:50:21 +00004585 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004586
Daniel Dunbar352e1482011-01-11 15:59:50 +00004587 // Next, determine if we have a carry setting bit. We explicitly ignore all
4588 // the instructions we know end in 's'.
4589 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004590 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004591 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4592 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4593 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004594 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004595 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004596 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004597 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004598 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004599 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4600 CarrySetting = true;
4601 }
4602
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004603 // The "cps" instruction can have a interrupt mode operand which is glued into
4604 // the mnemonic. Check if this is the case, split it and parse the imod op
4605 if (Mnemonic.startswith("cps")) {
4606 // Split out any imod code.
4607 unsigned IMod =
4608 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4609 .Case("ie", ARM_PROC::IE)
4610 .Case("id", ARM_PROC::ID)
4611 .Default(~0U);
4612 if (IMod != ~0U) {
4613 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4614 ProcessorIMod = IMod;
4615 }
4616 }
4617
Jim Grosbach89df9962011-08-26 21:43:41 +00004618 // The "it" instruction has the condition mask on the end of the mnemonic.
4619 if (Mnemonic.startswith("it")) {
4620 ITMask = Mnemonic.slice(2, Mnemonic.size());
4621 Mnemonic = Mnemonic.slice(0, 2);
4622 }
4623
Daniel Dunbar352e1482011-01-11 15:59:50 +00004624 return Mnemonic;
4625}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004626
4627/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4628/// inclusion of carry set or predication code operands.
4629//
4630// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004631void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004632getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004633 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004634 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4635 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004636 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004637 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004638 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004639 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004640 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004641 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004642 Mnemonic == "mla" || Mnemonic == "smlal" ||
4643 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004644 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004645 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004646 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004647
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004648 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4649 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4650 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4651 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004652 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4653 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004654 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004655 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4656 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4657 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004658 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4659 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004660 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004661 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004662 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004663 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004664
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004665 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004666 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004667 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004668 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004669 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004670}
4671
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004672bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4673 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004674 // FIXME: This is all horribly hacky. We really need a better way to deal
4675 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004676
4677 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4678 // another does not. Specifically, the MOVW instruction does not. So we
4679 // special case it here and remove the defaulted (non-setting) cc_out
4680 // operand if that's the instruction we're trying to match.
4681 //
4682 // We do this as post-processing of the explicit operands rather than just
4683 // conditionally adding the cc_out in the first place because we need
4684 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004685 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004686 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4687 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4688 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4689 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004690
4691 // Register-register 'add' for thumb does not have a cc_out operand
4692 // when there are only two register operands.
4693 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4694 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4695 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4696 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4697 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004698 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004699 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4700 // have to check the immediate range here since Thumb2 has a variant
4701 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004702 if (((isThumb() && Mnemonic == "add") ||
4703 (isThumbTwo() && Mnemonic == "sub")) &&
4704 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004705 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4706 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4707 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004708 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4709 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4710 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004711 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004712 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4713 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004714 // selecting via the generic "add" mnemonic, so to know that we
4715 // should remove the cc_out operand, we have to explicitly check that
4716 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004717 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4718 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004719 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4720 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4721 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4722 // Nest conditions rather than one big 'if' statement for readability.
4723 //
4724 // If either register is a high reg, it's either one of the SP
4725 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004726 // check against T3. If the second register is the PC, this is an
4727 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004728 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4729 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004730 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004731 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4732 return false;
4733 // If both registers are low, we're in an IT block, and the immediate is
4734 // in range, we should use encoding T1 instead, which has a cc_out.
4735 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004736 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004737 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4738 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4739 return false;
4740
4741 // Otherwise, we use encoding T4, which does not have a cc_out
4742 // operand.
4743 return true;
4744 }
4745
Jim Grosbach64944f42011-09-14 21:00:40 +00004746 // The thumb2 multiply instruction doesn't have a CCOut register, so
4747 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4748 // use the 16-bit encoding or not.
4749 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4750 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4751 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4752 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4753 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4754 // If the registers aren't low regs, the destination reg isn't the
4755 // same as one of the source regs, or the cc_out operand is zero
4756 // outside of an IT block, we have to use the 32-bit encoding, so
4757 // remove the cc_out operand.
4758 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4759 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004760 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004761 !inITBlock() ||
4762 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4763 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4764 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4765 static_cast<ARMOperand*>(Operands[4])->getReg())))
4766 return true;
4767
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004768 // Also check the 'mul' syntax variant that doesn't specify an explicit
4769 // destination register.
4770 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4771 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4772 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4773 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4774 // If the registers aren't low regs or the cc_out operand is zero
4775 // outside of an IT block, we have to use the 32-bit encoding, so
4776 // remove the cc_out operand.
4777 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4778 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4779 !inITBlock()))
4780 return true;
4781
Jim Grosbach64944f42011-09-14 21:00:40 +00004782
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004783
Jim Grosbachf69c8042011-08-24 21:42:27 +00004784 // Register-register 'add/sub' for thumb does not have a cc_out operand
4785 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4786 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4787 // right, this will result in better diagnostics (which operand is off)
4788 // anyway.
4789 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4790 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004791 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4792 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4793 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4794 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004795
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004796 return false;
4797}
4798
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004799static bool isDataTypeToken(StringRef Tok) {
4800 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4801 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4802 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4803 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4804 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4805 Tok == ".f" || Tok == ".d";
4806}
4807
4808// FIXME: This bit should probably be handled via an explicit match class
4809// in the .td files that matches the suffix instead of having it be
4810// a literal string token the way it is now.
4811static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4812 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4813}
4814
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004815static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004816/// Parse an arm instruction mnemonic followed by its operands.
4817bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4818 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004819 // Apply mnemonic aliases before doing anything else, as the destination
4820 // mnemnonic may include suffices and we want to handle them normally.
4821 // The generic tblgen'erated code does this later, at the start of
4822 // MatchInstructionImpl(), but that's too late for aliases that include
4823 // any sort of suffix.
4824 unsigned AvailableFeatures = getAvailableFeatures();
4825 applyMnemonicAliases(Name, AvailableFeatures);
4826
Jim Grosbacha39cda72011-12-14 02:16:11 +00004827 // First check for the ARM-specific .req directive.
4828 if (Parser.getTok().is(AsmToken::Identifier) &&
4829 Parser.getTok().getIdentifier() == ".req") {
4830 parseDirectiveReq(Name, NameLoc);
4831 // We always return 'error' for this, as we're done with this
4832 // statement and don't need to match the 'instruction."
4833 return true;
4834 }
4835
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004836 // Create the leading tokens for the mnemonic, split by '.' characters.
4837 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004838 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004839
Daniel Dunbar352e1482011-01-11 15:59:50 +00004840 // Split out the predication code and carry setting flag from the mnemonic.
4841 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004842 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004843 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004844 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004845 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004846 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004847
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004848 // In Thumb1, only the branch (B) instruction can be predicated.
4849 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4850 Parser.EatToEndOfStatement();
4851 return Error(NameLoc, "conditional execution not supported in Thumb1");
4852 }
4853
Jim Grosbachffa32252011-07-19 19:13:28 +00004854 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4855
Jim Grosbach89df9962011-08-26 21:43:41 +00004856 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4857 // is the mask as it will be for the IT encoding if the conditional
4858 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4859 // where the conditional bit0 is zero, the instruction post-processing
4860 // will adjust the mask accordingly.
4861 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004862 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4863 if (ITMask.size() > 3) {
4864 Parser.EatToEndOfStatement();
4865 return Error(Loc, "too many conditions on IT instruction");
4866 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004867 unsigned Mask = 8;
4868 for (unsigned i = ITMask.size(); i != 0; --i) {
4869 char pos = ITMask[i - 1];
4870 if (pos != 't' && pos != 'e') {
4871 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004872 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004873 }
4874 Mask >>= 1;
4875 if (ITMask[i - 1] == 't')
4876 Mask |= 8;
4877 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004878 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004879 }
4880
Jim Grosbachffa32252011-07-19 19:13:28 +00004881 // FIXME: This is all a pretty gross hack. We should automatically handle
4882 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004883
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004884 // Next, add the CCOut and ConditionCode operands, if needed.
4885 //
4886 // For mnemonics which can ever incorporate a carry setting bit or predication
4887 // code, our matching model involves us always generating CCOut and
4888 // ConditionCode operands to match the mnemonic "as written" and then we let
4889 // the matcher deal with finding the right instruction or generating an
4890 // appropriate error.
4891 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004892 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004893
Jim Grosbach33c16a22011-07-14 22:04:21 +00004894 // If we had a carry-set on an instruction that can't do that, issue an
4895 // error.
4896 if (!CanAcceptCarrySet && CarrySetting) {
4897 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004898 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004899 "' can not set flags, but 's' suffix specified");
4900 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004901 // If we had a predication code on an instruction that can't do that, issue an
4902 // error.
4903 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4904 Parser.EatToEndOfStatement();
4905 return Error(NameLoc, "instruction '" + Mnemonic +
4906 "' is not predicable, but condition code specified");
4907 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004908
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004909 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004910 if (CanAcceptCarrySet) {
4911 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004912 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004913 Loc));
4914 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004915
4916 // Add the predication code operand, if necessary.
4917 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004918 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4919 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004920 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004921 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004922 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004923
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004924 // Add the processor imod operand, if necessary.
4925 if (ProcessorIMod) {
4926 Operands.push_back(ARMOperand::CreateImm(
4927 MCConstantExpr::Create(ProcessorIMod, getContext()),
4928 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004929 }
4930
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004931 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004932 while (Next != StringRef::npos) {
4933 Start = Next;
4934 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004935 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004936
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004937 // Some NEON instructions have an optional datatype suffix that is
4938 // completely ignored. Check for that.
4939 if (isDataTypeToken(ExtraToken) &&
4940 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4941 continue;
4942
Jim Grosbach81d2e392011-09-07 16:06:04 +00004943 if (ExtraToken != ".n") {
4944 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4945 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4946 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004947 }
4948
4949 // Read the remaining operands.
4950 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004951 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004952 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004953 Parser.EatToEndOfStatement();
4954 return true;
4955 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004956
4957 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004958 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004959
4960 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004961 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004962 Parser.EatToEndOfStatement();
4963 return true;
4964 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004965 }
4966 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004967
Chris Lattnercbf8a982010-09-11 16:18:25 +00004968 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004969 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004970 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004971 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004972 }
Bill Wendling146018f2010-11-06 21:42:12 +00004973
Chris Lattner34e53142010-09-08 05:10:46 +00004974 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004975
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004976 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4977 // do and don't have a cc_out optional-def operand. With some spot-checks
4978 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004979 // parse and adjust accordingly before actually matching. We shouldn't ever
4980 // try to remove a cc_out operand that was explicitly set on the the
4981 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4982 // table driven matcher doesn't fit well with the ARM instruction set.
4983 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004984 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4985 Operands.erase(Operands.begin() + 1);
4986 delete Op;
4987 }
4988
Jim Grosbachcf121c32011-07-28 21:57:55 +00004989 // ARM mode 'blx' need special handling, as the register operand version
4990 // is predicable, but the label operand version is not. So, we can't rely
4991 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004992 // a k_CondCode operand in the list. If we're trying to match the label
4993 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004994 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4995 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4996 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4997 Operands.erase(Operands.begin() + 1);
4998 delete Op;
4999 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005000
5001 // The vector-compare-to-zero instructions have a literal token "#0" at
5002 // the end that comes to here as an immediate operand. Convert it to a
5003 // token to play nicely with the matcher.
5004 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5005 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5006 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5007 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5008 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5009 if (CE && CE->getValue() == 0) {
5010 Operands.erase(Operands.begin() + 5);
5011 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5012 delete Op;
5013 }
5014 }
Jim Grosbach68259142011-10-03 22:30:24 +00005015 // VCMP{E} does the same thing, but with a different operand count.
5016 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5017 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5018 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5019 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5020 if (CE && CE->getValue() == 0) {
5021 Operands.erase(Operands.begin() + 4);
5022 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5023 delete Op;
5024 }
5025 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005026 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005027 // end. Convert it to a token here. Take care not to convert those
5028 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005029 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005030 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5031 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005032 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5033 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5034 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005035 if (CE && CE->getValue() == 0 &&
5036 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005037 // The cc_out operand matches the IT block.
5038 ((inITBlock() != CarrySetting) &&
5039 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005040 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005041 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005042 Operands.erase(Operands.begin() + 5);
5043 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5044 delete Op;
5045 }
5046 }
5047
Chris Lattner98986712010-01-14 22:21:20 +00005048 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005049}
5050
Jim Grosbach189610f2011-07-26 18:25:39 +00005051// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005052
5053// return 'true' if register list contains non-low GPR registers,
5054// 'false' otherwise. If Reg is in the register list or is HiReg, set
5055// 'containsReg' to true.
5056static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5057 unsigned HiReg, bool &containsReg) {
5058 containsReg = false;
5059 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5060 unsigned OpReg = Inst.getOperand(i).getReg();
5061 if (OpReg == Reg)
5062 containsReg = true;
5063 // Anything other than a low register isn't legal here.
5064 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5065 return true;
5066 }
5067 return false;
5068}
5069
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005070// Check if the specified regisgter is in the register list of the inst,
5071// starting at the indicated operand number.
5072static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5073 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5074 unsigned OpReg = Inst.getOperand(i).getReg();
5075 if (OpReg == Reg)
5076 return true;
5077 }
5078 return false;
5079}
5080
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005081// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5082// the ARMInsts array) instead. Getting that here requires awkward
5083// API changes, though. Better way?
5084namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005085extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005086}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005087static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005088 return ARMInsts[Opcode];
5089}
5090
Jim Grosbach189610f2011-07-26 18:25:39 +00005091// FIXME: We would really like to be able to tablegen'erate this.
5092bool ARMAsmParser::
5093validateInstruction(MCInst &Inst,
5094 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005095 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005096 SMLoc Loc = Operands[0]->getStartLoc();
5097 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005098 // NOTE: BKPT instruction has the interesting property of being
5099 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005100 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005101 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5102 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005103 unsigned bit = 1;
5104 if (ITState.FirstCond)
5105 ITState.FirstCond = false;
5106 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005107 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005108 // The instruction must be predicable.
5109 if (!MCID.isPredicable())
5110 return Error(Loc, "instructions in IT block must be predicable");
5111 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5112 unsigned ITCond = bit ? ITState.Cond :
5113 ARMCC::getOppositeCondition(ITState.Cond);
5114 if (Cond != ITCond) {
5115 // Find the condition code Operand to get its SMLoc information.
5116 SMLoc CondLoc;
5117 for (unsigned i = 1; i < Operands.size(); ++i)
5118 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5119 CondLoc = Operands[i]->getStartLoc();
5120 return Error(CondLoc, "incorrect condition in IT block; got '" +
5121 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5122 "', but expected '" +
5123 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5124 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005125 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005126 } else if (isThumbTwo() && MCID.isPredicable() &&
5127 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005128 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5129 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005130 return Error(Loc, "predicated instructions must be in IT block");
5131
Jim Grosbach189610f2011-07-26 18:25:39 +00005132 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005133 case ARM::LDRD:
5134 case ARM::LDRD_PRE:
5135 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005136 case ARM::LDREXD: {
5137 // Rt2 must be Rt + 1.
5138 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5139 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5140 if (Rt2 != Rt + 1)
5141 return Error(Operands[3]->getStartLoc(),
5142 "destination operands must be sequential");
5143 return false;
5144 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005145 case ARM::STRD: {
5146 // Rt2 must be Rt + 1.
5147 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5148 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5149 if (Rt2 != Rt + 1)
5150 return Error(Operands[3]->getStartLoc(),
5151 "source operands must be sequential");
5152 return false;
5153 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005154 case ARM::STRD_PRE:
5155 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005156 case ARM::STREXD: {
5157 // Rt2 must be Rt + 1.
5158 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5159 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5160 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005161 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005162 "source operands must be sequential");
5163 return false;
5164 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005165 case ARM::SBFX:
5166 case ARM::UBFX: {
5167 // width must be in range [1, 32-lsb]
5168 unsigned lsb = Inst.getOperand(2).getImm();
5169 unsigned widthm1 = Inst.getOperand(3).getImm();
5170 if (widthm1 >= 32 - lsb)
5171 return Error(Operands[5]->getStartLoc(),
5172 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005173 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005174 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005175 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005176 // If we're parsing Thumb2, the .w variant is available and handles
5177 // most cases that are normally illegal for a Thumb1 LDM
5178 // instruction. We'll make the transformation in processInstruction()
5179 // if necessary.
5180 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005181 // Thumb LDM instructions are writeback iff the base register is not
5182 // in the register list.
5183 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005184 bool hasWritebackToken =
5185 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5186 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005187 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005188 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005189 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5190 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005191 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005192 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005193 return Error(Operands[2]->getStartLoc(),
5194 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005195 // If we should not have writeback, there must not be a '!'. This is
5196 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005197 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005198 return Error(Operands[3]->getStartLoc(),
5199 "writeback operator '!' not allowed when base register "
5200 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005201
5202 break;
5203 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005204 case ARM::t2LDMIA_UPD: {
5205 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5206 return Error(Operands[4]->getStartLoc(),
5207 "writeback operator '!' not allowed when base register "
5208 "in register list");
5209 break;
5210 }
Jim Grosbach54026372011-11-10 23:17:11 +00005211 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5212 // so only issue a diagnostic for thumb1. The instructions will be
5213 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005214 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005215 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005216 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5217 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005218 return Error(Operands[2]->getStartLoc(),
5219 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005220 break;
5221 }
5222 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005223 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005224 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5225 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005226 return Error(Operands[2]->getStartLoc(),
5227 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005228 break;
5229 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005230 case ARM::tSTMIA_UPD: {
5231 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005232 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005233 return Error(Operands[4]->getStartLoc(),
5234 "registers must be in range r0-r7");
5235 break;
5236 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005237 }
5238
5239 return false;
5240}
5241
Jim Grosbachd7433e22012-01-23 23:45:44 +00005242static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005243 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005244 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005245 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005246 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5247 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5248 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5249 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5250 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5251 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5252 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5253 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5254 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005255
5256 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005257 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5258 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5259 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5260 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5261 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005262
Jim Grosbach7945ead2012-01-24 00:43:12 +00005263 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5264 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5265 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5266 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5267 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005268
Jim Grosbach7945ead2012-01-24 00:43:12 +00005269 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5270 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5271 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5272 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5273 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005274
Jim Grosbach4adb1822012-01-24 00:07:41 +00005275 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005276 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5277 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5278 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5279 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5280 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5281 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5282 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5283 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5284 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5285 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5286 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5287 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5288 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5289 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5290 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005291
Jim Grosbachd7433e22012-01-23 23:45:44 +00005292 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005293 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5294 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5295 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5296 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5297 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5298 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5299 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5300 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5301 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5302 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5303 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5304 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5305 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5306 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5307 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5308 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5309 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5310 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005311
Jim Grosbach88a54de2012-01-24 18:53:13 +00005312 // VST4LN
5313 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5314 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5315 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5316 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5317 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5318 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5319 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5320 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5321 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5322 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5323 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5324 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5325 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5326 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5327 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5328
Jim Grosbach539aab72012-01-24 00:58:13 +00005329 // VST4
5330 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5331 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5332 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5333 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5334 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5335 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5336 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5337 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5338 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5339 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5340 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5341 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5342 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5343 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5344 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5345 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5346 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5347 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005348 }
5349}
5350
Jim Grosbachd7433e22012-01-23 23:45:44 +00005351static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005352 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005353 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005354 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005355 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5356 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5357 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5358 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5359 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5360 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5361 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5362 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5363 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005364
5365 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005366 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5367 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5368 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5369 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5370 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5371 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5372 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5373 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5374 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5375 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5376 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5377 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5378 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5379 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5380 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005381
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005382 // VLD3DUP
5383 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5384 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5385 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5386 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5387 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5388 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5389 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5390 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5391 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5392 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5393 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5394 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5395 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5396 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5397 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5398 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5399 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5400 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5401
Jim Grosbach3a678af2012-01-23 21:53:26 +00005402 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005403 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5404 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5405 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5406 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5407 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5408 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5409 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5410 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5411 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5412 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5413 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5414 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5415 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5416 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5417 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005418
5419 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005420 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5421 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5422 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5423 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5424 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5425 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5426 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5427 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5428 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5429 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5430 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5431 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5432 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5433 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5434 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5435 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5436 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5437 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005438
Jim Grosbache983a132012-01-24 18:37:25 +00005439 // VLD4LN
5440 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5441 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5442 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5443 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5444 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5445 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5446 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5447 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5448 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5449 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5450 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5451 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5452 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5453 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5454 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5455
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005456 // VLD4DUP
5457 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5458 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5459 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5460 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5461 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5462 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5463 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5464 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5465 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5466 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5467 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5468 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5469 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5470 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5471 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5472 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5473 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5474 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5475
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005476 // VLD4
5477 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5478 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5479 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5480 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5481 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5482 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5483 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5484 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5485 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5486 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5487 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5488 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5489 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5490 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5491 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5492 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5493 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5494 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005495 }
5496}
5497
Jim Grosbach83ec8772011-11-10 23:42:14 +00005498bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005499processInstruction(MCInst &Inst,
5500 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5501 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005502 // Aliases for alternate PC+imm syntax of LDR instructions.
5503 case ARM::t2LDRpcrel:
5504 Inst.setOpcode(ARM::t2LDRpci);
5505 return true;
5506 case ARM::t2LDRBpcrel:
5507 Inst.setOpcode(ARM::t2LDRBpci);
5508 return true;
5509 case ARM::t2LDRHpcrel:
5510 Inst.setOpcode(ARM::t2LDRHpci);
5511 return true;
5512 case ARM::t2LDRSBpcrel:
5513 Inst.setOpcode(ARM::t2LDRSBpci);
5514 return true;
5515 case ARM::t2LDRSHpcrel:
5516 Inst.setOpcode(ARM::t2LDRSHpci);
5517 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005518 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005519 case ARM::VST1LNdWB_register_Asm_8:
5520 case ARM::VST1LNdWB_register_Asm_16:
5521 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005522 MCInst TmpInst;
5523 // Shuffle the operands around so the lane index operand is in the
5524 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005525 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005526 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005527 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5528 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5529 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5530 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5531 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5532 TmpInst.addOperand(Inst.getOperand(1)); // lane
5533 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5534 TmpInst.addOperand(Inst.getOperand(6));
5535 Inst = TmpInst;
5536 return true;
5537 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005538
Jim Grosbach8b31f952012-01-23 19:39:08 +00005539 case ARM::VST2LNdWB_register_Asm_8:
5540 case ARM::VST2LNdWB_register_Asm_16:
5541 case ARM::VST2LNdWB_register_Asm_32:
5542 case ARM::VST2LNqWB_register_Asm_16:
5543 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005544 MCInst TmpInst;
5545 // Shuffle the operands around so the lane index operand is in the
5546 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005547 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005548 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005549 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5550 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5551 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5552 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5553 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005554 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5555 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005556 TmpInst.addOperand(Inst.getOperand(1)); // lane
5557 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5558 TmpInst.addOperand(Inst.getOperand(6));
5559 Inst = TmpInst;
5560 return true;
5561 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005562
5563 case ARM::VST3LNdWB_register_Asm_8:
5564 case ARM::VST3LNdWB_register_Asm_16:
5565 case ARM::VST3LNdWB_register_Asm_32:
5566 case ARM::VST3LNqWB_register_Asm_16:
5567 case ARM::VST3LNqWB_register_Asm_32: {
5568 MCInst TmpInst;
5569 // Shuffle the operands around so the lane index operand is in the
5570 // right place.
5571 unsigned Spacing;
5572 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5573 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5574 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5575 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5576 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5577 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5578 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5579 Spacing));
5580 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5581 Spacing * 2));
5582 TmpInst.addOperand(Inst.getOperand(1)); // lane
5583 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5584 TmpInst.addOperand(Inst.getOperand(6));
5585 Inst = TmpInst;
5586 return true;
5587 }
5588
Jim Grosbach88a54de2012-01-24 18:53:13 +00005589 case ARM::VST4LNdWB_register_Asm_8:
5590 case ARM::VST4LNdWB_register_Asm_16:
5591 case ARM::VST4LNdWB_register_Asm_32:
5592 case ARM::VST4LNqWB_register_Asm_16:
5593 case ARM::VST4LNqWB_register_Asm_32: {
5594 MCInst TmpInst;
5595 // Shuffle the operands around so the lane index operand is in the
5596 // right place.
5597 unsigned Spacing;
5598 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5599 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5600 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5601 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5602 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5603 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5604 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5605 Spacing));
5606 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5607 Spacing * 2));
5608 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5609 Spacing * 3));
5610 TmpInst.addOperand(Inst.getOperand(1)); // lane
5611 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5612 TmpInst.addOperand(Inst.getOperand(6));
5613 Inst = TmpInst;
5614 return true;
5615 }
5616
Jim Grosbach8b31f952012-01-23 19:39:08 +00005617 case ARM::VST1LNdWB_fixed_Asm_8:
5618 case ARM::VST1LNdWB_fixed_Asm_16:
5619 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005620 MCInst TmpInst;
5621 // Shuffle the operands around so the lane index operand is in the
5622 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005623 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005624 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005625 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5626 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5627 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5628 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5629 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5630 TmpInst.addOperand(Inst.getOperand(1)); // lane
5631 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5632 TmpInst.addOperand(Inst.getOperand(5));
5633 Inst = TmpInst;
5634 return true;
5635 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005636
Jim Grosbach8b31f952012-01-23 19:39:08 +00005637 case ARM::VST2LNdWB_fixed_Asm_8:
5638 case ARM::VST2LNdWB_fixed_Asm_16:
5639 case ARM::VST2LNdWB_fixed_Asm_32:
5640 case ARM::VST2LNqWB_fixed_Asm_16:
5641 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005642 MCInst TmpInst;
5643 // Shuffle the operands around so the lane index operand is in the
5644 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005645 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005646 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005647 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5648 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5649 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5650 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5651 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005652 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5653 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005654 TmpInst.addOperand(Inst.getOperand(1)); // lane
5655 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5656 TmpInst.addOperand(Inst.getOperand(5));
5657 Inst = TmpInst;
5658 return true;
5659 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005660
5661 case ARM::VST3LNdWB_fixed_Asm_8:
5662 case ARM::VST3LNdWB_fixed_Asm_16:
5663 case ARM::VST3LNdWB_fixed_Asm_32:
5664 case ARM::VST3LNqWB_fixed_Asm_16:
5665 case ARM::VST3LNqWB_fixed_Asm_32: {
5666 MCInst TmpInst;
5667 // Shuffle the operands around so the lane index operand is in the
5668 // right place.
5669 unsigned Spacing;
5670 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5671 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5672 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5673 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5674 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5675 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5676 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5677 Spacing));
5678 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5679 Spacing * 2));
5680 TmpInst.addOperand(Inst.getOperand(1)); // lane
5681 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5682 TmpInst.addOperand(Inst.getOperand(5));
5683 Inst = TmpInst;
5684 return true;
5685 }
5686
Jim Grosbach88a54de2012-01-24 18:53:13 +00005687 case ARM::VST4LNdWB_fixed_Asm_8:
5688 case ARM::VST4LNdWB_fixed_Asm_16:
5689 case ARM::VST4LNdWB_fixed_Asm_32:
5690 case ARM::VST4LNqWB_fixed_Asm_16:
5691 case ARM::VST4LNqWB_fixed_Asm_32: {
5692 MCInst TmpInst;
5693 // Shuffle the operands around so the lane index operand is in the
5694 // right place.
5695 unsigned Spacing;
5696 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5697 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5698 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5699 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5700 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5701 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5702 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5703 Spacing));
5704 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5705 Spacing * 2));
5706 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5707 Spacing * 3));
5708 TmpInst.addOperand(Inst.getOperand(1)); // lane
5709 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5710 TmpInst.addOperand(Inst.getOperand(5));
5711 Inst = TmpInst;
5712 return true;
5713 }
5714
Jim Grosbach8b31f952012-01-23 19:39:08 +00005715 case ARM::VST1LNdAsm_8:
5716 case ARM::VST1LNdAsm_16:
5717 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005718 MCInst TmpInst;
5719 // Shuffle the operands around so the lane index operand is in the
5720 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005721 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005722 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005723 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5724 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5725 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5726 TmpInst.addOperand(Inst.getOperand(1)); // lane
5727 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5728 TmpInst.addOperand(Inst.getOperand(5));
5729 Inst = TmpInst;
5730 return true;
5731 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005732
Jim Grosbach8b31f952012-01-23 19:39:08 +00005733 case ARM::VST2LNdAsm_8:
5734 case ARM::VST2LNdAsm_16:
5735 case ARM::VST2LNdAsm_32:
5736 case ARM::VST2LNqAsm_16:
5737 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005738 MCInst TmpInst;
5739 // Shuffle the operands around so the lane index operand is in the
5740 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005741 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005742 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005743 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5744 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5745 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005746 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5747 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005748 TmpInst.addOperand(Inst.getOperand(1)); // lane
5749 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5750 TmpInst.addOperand(Inst.getOperand(5));
5751 Inst = TmpInst;
5752 return true;
5753 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005754
5755 case ARM::VST3LNdAsm_8:
5756 case ARM::VST3LNdAsm_16:
5757 case ARM::VST3LNdAsm_32:
5758 case ARM::VST3LNqAsm_16:
5759 case ARM::VST3LNqAsm_32: {
5760 MCInst TmpInst;
5761 // Shuffle the operands around so the lane index operand is in the
5762 // right place.
5763 unsigned Spacing;
5764 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5765 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5766 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5767 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5768 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5769 Spacing));
5770 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5771 Spacing * 2));
5772 TmpInst.addOperand(Inst.getOperand(1)); // lane
5773 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5774 TmpInst.addOperand(Inst.getOperand(5));
5775 Inst = TmpInst;
5776 return true;
5777 }
5778
Jim Grosbach88a54de2012-01-24 18:53:13 +00005779 case ARM::VST4LNdAsm_8:
5780 case ARM::VST4LNdAsm_16:
5781 case ARM::VST4LNdAsm_32:
5782 case ARM::VST4LNqAsm_16:
5783 case ARM::VST4LNqAsm_32: {
5784 MCInst TmpInst;
5785 // Shuffle the operands around so the lane index operand is in the
5786 // right place.
5787 unsigned Spacing;
5788 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5789 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5790 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5791 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5792 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5793 Spacing));
5794 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5795 Spacing * 2));
5796 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5797 Spacing * 3));
5798 TmpInst.addOperand(Inst.getOperand(1)); // lane
5799 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5800 TmpInst.addOperand(Inst.getOperand(5));
5801 Inst = TmpInst;
5802 return true;
5803 }
5804
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005805 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005806 case ARM::VLD1LNdWB_register_Asm_8:
5807 case ARM::VLD1LNdWB_register_Asm_16:
5808 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005809 MCInst TmpInst;
5810 // Shuffle the operands around so the lane index operand is in the
5811 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005812 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005813 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005814 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5815 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5816 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5817 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5818 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5819 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5820 TmpInst.addOperand(Inst.getOperand(1)); // lane
5821 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5822 TmpInst.addOperand(Inst.getOperand(6));
5823 Inst = TmpInst;
5824 return true;
5825 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005826
Jim Grosbach8b31f952012-01-23 19:39:08 +00005827 case ARM::VLD2LNdWB_register_Asm_8:
5828 case ARM::VLD2LNdWB_register_Asm_16:
5829 case ARM::VLD2LNdWB_register_Asm_32:
5830 case ARM::VLD2LNqWB_register_Asm_16:
5831 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005832 MCInst TmpInst;
5833 // Shuffle the operands around so the lane index operand is in the
5834 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005835 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005836 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005837 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005838 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5839 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005840 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5841 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5842 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5843 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5844 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005845 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5846 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005847 TmpInst.addOperand(Inst.getOperand(1)); // lane
5848 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5849 TmpInst.addOperand(Inst.getOperand(6));
5850 Inst = TmpInst;
5851 return true;
5852 }
5853
Jim Grosbach3a678af2012-01-23 21:53:26 +00005854 case ARM::VLD3LNdWB_register_Asm_8:
5855 case ARM::VLD3LNdWB_register_Asm_16:
5856 case ARM::VLD3LNdWB_register_Asm_32:
5857 case ARM::VLD3LNqWB_register_Asm_16:
5858 case ARM::VLD3LNqWB_register_Asm_32: {
5859 MCInst TmpInst;
5860 // Shuffle the operands around so the lane index operand is in the
5861 // right place.
5862 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005863 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005864 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5865 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5866 Spacing));
5867 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005868 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005869 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5870 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5871 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5872 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5873 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5874 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5875 Spacing));
5876 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005877 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005878 TmpInst.addOperand(Inst.getOperand(1)); // lane
5879 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5880 TmpInst.addOperand(Inst.getOperand(6));
5881 Inst = TmpInst;
5882 return true;
5883 }
5884
Jim Grosbache983a132012-01-24 18:37:25 +00005885 case ARM::VLD4LNdWB_register_Asm_8:
5886 case ARM::VLD4LNdWB_register_Asm_16:
5887 case ARM::VLD4LNdWB_register_Asm_32:
5888 case ARM::VLD4LNqWB_register_Asm_16:
5889 case ARM::VLD4LNqWB_register_Asm_32: {
5890 MCInst TmpInst;
5891 // Shuffle the operands around so the lane index operand is in the
5892 // right place.
5893 unsigned Spacing;
5894 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5895 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5896 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5897 Spacing));
5898 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5899 Spacing * 2));
5900 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5901 Spacing * 3));
5902 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5903 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5904 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5905 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5906 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5907 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5908 Spacing));
5909 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5910 Spacing * 2));
5911 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5912 Spacing * 3));
5913 TmpInst.addOperand(Inst.getOperand(1)); // lane
5914 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5915 TmpInst.addOperand(Inst.getOperand(6));
5916 Inst = TmpInst;
5917 return true;
5918 }
5919
Jim Grosbach8b31f952012-01-23 19:39:08 +00005920 case ARM::VLD1LNdWB_fixed_Asm_8:
5921 case ARM::VLD1LNdWB_fixed_Asm_16:
5922 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005923 MCInst TmpInst;
5924 // Shuffle the operands around so the lane index operand is in the
5925 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005926 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005927 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005928 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5929 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5930 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5931 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5932 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5933 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5934 TmpInst.addOperand(Inst.getOperand(1)); // lane
5935 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5936 TmpInst.addOperand(Inst.getOperand(5));
5937 Inst = TmpInst;
5938 return true;
5939 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005940
Jim Grosbach8b31f952012-01-23 19:39:08 +00005941 case ARM::VLD2LNdWB_fixed_Asm_8:
5942 case ARM::VLD2LNdWB_fixed_Asm_16:
5943 case ARM::VLD2LNdWB_fixed_Asm_32:
5944 case ARM::VLD2LNqWB_fixed_Asm_16:
5945 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005946 MCInst TmpInst;
5947 // Shuffle the operands around so the lane index operand is in the
5948 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005949 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005950 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005951 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005952 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5953 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005954 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5955 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5956 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5957 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5958 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005959 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5960 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005961 TmpInst.addOperand(Inst.getOperand(1)); // lane
5962 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5963 TmpInst.addOperand(Inst.getOperand(5));
5964 Inst = TmpInst;
5965 return true;
5966 }
5967
Jim Grosbach3a678af2012-01-23 21:53:26 +00005968 case ARM::VLD3LNdWB_fixed_Asm_8:
5969 case ARM::VLD3LNdWB_fixed_Asm_16:
5970 case ARM::VLD3LNdWB_fixed_Asm_32:
5971 case ARM::VLD3LNqWB_fixed_Asm_16:
5972 case ARM::VLD3LNqWB_fixed_Asm_32: {
5973 MCInst TmpInst;
5974 // Shuffle the operands around so the lane index operand is in the
5975 // right place.
5976 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005977 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005978 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5979 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5980 Spacing));
5981 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005982 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005983 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5984 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5985 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5986 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5987 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5988 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5989 Spacing));
5990 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005991 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005992 TmpInst.addOperand(Inst.getOperand(1)); // lane
5993 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5994 TmpInst.addOperand(Inst.getOperand(5));
5995 Inst = TmpInst;
5996 return true;
5997 }
5998
Jim Grosbache983a132012-01-24 18:37:25 +00005999 case ARM::VLD4LNdWB_fixed_Asm_8:
6000 case ARM::VLD4LNdWB_fixed_Asm_16:
6001 case ARM::VLD4LNdWB_fixed_Asm_32:
6002 case ARM::VLD4LNqWB_fixed_Asm_16:
6003 case ARM::VLD4LNqWB_fixed_Asm_32: {
6004 MCInst TmpInst;
6005 // Shuffle the operands around so the lane index operand is in the
6006 // right place.
6007 unsigned Spacing;
6008 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6009 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6010 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6011 Spacing));
6012 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6013 Spacing * 2));
6014 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6015 Spacing * 3));
6016 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6017 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6018 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6019 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6020 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6021 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6022 Spacing));
6023 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6024 Spacing * 2));
6025 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6026 Spacing * 3));
6027 TmpInst.addOperand(Inst.getOperand(1)); // lane
6028 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6029 TmpInst.addOperand(Inst.getOperand(5));
6030 Inst = TmpInst;
6031 return true;
6032 }
6033
Jim Grosbach8b31f952012-01-23 19:39:08 +00006034 case ARM::VLD1LNdAsm_8:
6035 case ARM::VLD1LNdAsm_16:
6036 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006037 MCInst TmpInst;
6038 // Shuffle the operands around so the lane index operand is in the
6039 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006040 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006041 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006042 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6043 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6044 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6045 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6046 TmpInst.addOperand(Inst.getOperand(1)); // lane
6047 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6048 TmpInst.addOperand(Inst.getOperand(5));
6049 Inst = TmpInst;
6050 return true;
6051 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006052
Jim Grosbach8b31f952012-01-23 19:39:08 +00006053 case ARM::VLD2LNdAsm_8:
6054 case ARM::VLD2LNdAsm_16:
6055 case ARM::VLD2LNdAsm_32:
6056 case ARM::VLD2LNqAsm_16:
6057 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006058 MCInst TmpInst;
6059 // Shuffle the operands around so the lane index operand is in the
6060 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006061 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006062 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006063 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006064 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6065 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006066 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6067 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6068 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== 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(1)); // lane
6072 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6073 TmpInst.addOperand(Inst.getOperand(5));
6074 Inst = TmpInst;
6075 return true;
6076 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006077
6078 case ARM::VLD3LNdAsm_8:
6079 case ARM::VLD3LNdAsm_16:
6080 case ARM::VLD3LNdAsm_32:
6081 case ARM::VLD3LNqAsm_16:
6082 case ARM::VLD3LNqAsm_32: {
6083 MCInst TmpInst;
6084 // Shuffle the operands around so the lane index operand is in the
6085 // right place.
6086 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006087 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006088 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6089 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6090 Spacing));
6091 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006092 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006093 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6094 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6095 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6096 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6097 Spacing));
6098 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006099 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006100 TmpInst.addOperand(Inst.getOperand(1)); // lane
6101 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6102 TmpInst.addOperand(Inst.getOperand(5));
6103 Inst = TmpInst;
6104 return true;
6105 }
6106
Jim Grosbache983a132012-01-24 18:37:25 +00006107 case ARM::VLD4LNdAsm_8:
6108 case ARM::VLD4LNdAsm_16:
6109 case ARM::VLD4LNdAsm_32:
6110 case ARM::VLD4LNqAsm_16:
6111 case ARM::VLD4LNqAsm_32: {
6112 MCInst TmpInst;
6113 // Shuffle the operands around so the lane index operand is in the
6114 // right place.
6115 unsigned Spacing;
6116 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6117 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6118 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6119 Spacing));
6120 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6121 Spacing * 2));
6122 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6123 Spacing * 3));
6124 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6125 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6126 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6127 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6128 Spacing));
6129 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6130 Spacing * 2));
6131 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6132 Spacing * 3));
6133 TmpInst.addOperand(Inst.getOperand(1)); // lane
6134 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6135 TmpInst.addOperand(Inst.getOperand(5));
6136 Inst = TmpInst;
6137 return true;
6138 }
6139
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006140 // VLD3DUP single 3-element structure to all lanes instructions.
6141 case ARM::VLD3DUPdAsm_8:
6142 case ARM::VLD3DUPdAsm_16:
6143 case ARM::VLD3DUPdAsm_32:
6144 case ARM::VLD3DUPqAsm_8:
6145 case ARM::VLD3DUPqAsm_16:
6146 case ARM::VLD3DUPqAsm_32: {
6147 MCInst TmpInst;
6148 unsigned Spacing;
6149 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6150 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6151 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6152 Spacing));
6153 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6154 Spacing * 2));
6155 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6156 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6157 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6158 TmpInst.addOperand(Inst.getOperand(4));
6159 Inst = TmpInst;
6160 return true;
6161 }
6162
6163 case ARM::VLD3DUPdWB_fixed_Asm_8:
6164 case ARM::VLD3DUPdWB_fixed_Asm_16:
6165 case ARM::VLD3DUPdWB_fixed_Asm_32:
6166 case ARM::VLD3DUPqWB_fixed_Asm_8:
6167 case ARM::VLD3DUPqWB_fixed_Asm_16:
6168 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6169 MCInst TmpInst;
6170 unsigned Spacing;
6171 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6172 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6173 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6174 Spacing));
6175 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6176 Spacing * 2));
6177 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6178 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6179 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6180 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6181 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6182 TmpInst.addOperand(Inst.getOperand(4));
6183 Inst = TmpInst;
6184 return true;
6185 }
6186
6187 case ARM::VLD3DUPdWB_register_Asm_8:
6188 case ARM::VLD3DUPdWB_register_Asm_16:
6189 case ARM::VLD3DUPdWB_register_Asm_32:
6190 case ARM::VLD3DUPqWB_register_Asm_8:
6191 case ARM::VLD3DUPqWB_register_Asm_16:
6192 case ARM::VLD3DUPqWB_register_Asm_32: {
6193 MCInst TmpInst;
6194 unsigned Spacing;
6195 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6196 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6197 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6198 Spacing));
6199 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6200 Spacing * 2));
6201 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6202 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6203 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6204 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6205 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6206 TmpInst.addOperand(Inst.getOperand(5));
6207 Inst = TmpInst;
6208 return true;
6209 }
6210
Jim Grosbachc387fc62012-01-23 23:20:46 +00006211 // VLD3 multiple 3-element structure instructions.
6212 case ARM::VLD3dAsm_8:
6213 case ARM::VLD3dAsm_16:
6214 case ARM::VLD3dAsm_32:
6215 case ARM::VLD3qAsm_8:
6216 case ARM::VLD3qAsm_16:
6217 case ARM::VLD3qAsm_32: {
6218 MCInst TmpInst;
6219 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006220 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006221 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6222 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6223 Spacing));
6224 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6225 Spacing * 2));
6226 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6227 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6228 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6229 TmpInst.addOperand(Inst.getOperand(4));
6230 Inst = TmpInst;
6231 return true;
6232 }
6233
6234 case ARM::VLD3dWB_fixed_Asm_8:
6235 case ARM::VLD3dWB_fixed_Asm_16:
6236 case ARM::VLD3dWB_fixed_Asm_32:
6237 case ARM::VLD3qWB_fixed_Asm_8:
6238 case ARM::VLD3qWB_fixed_Asm_16:
6239 case ARM::VLD3qWB_fixed_Asm_32: {
6240 MCInst TmpInst;
6241 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006242 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006243 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6244 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6245 Spacing));
6246 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6247 Spacing * 2));
6248 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6249 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6250 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6251 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6252 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6253 TmpInst.addOperand(Inst.getOperand(4));
6254 Inst = TmpInst;
6255 return true;
6256 }
6257
6258 case ARM::VLD3dWB_register_Asm_8:
6259 case ARM::VLD3dWB_register_Asm_16:
6260 case ARM::VLD3dWB_register_Asm_32:
6261 case ARM::VLD3qWB_register_Asm_8:
6262 case ARM::VLD3qWB_register_Asm_16:
6263 case ARM::VLD3qWB_register_Asm_32: {
6264 MCInst TmpInst;
6265 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006266 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006267 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6268 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6269 Spacing));
6270 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6271 Spacing * 2));
6272 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6273 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6274 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6275 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6276 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6277 TmpInst.addOperand(Inst.getOperand(5));
6278 Inst = TmpInst;
6279 return true;
6280 }
6281
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006282 // VLD4DUP single 3-element structure to all lanes instructions.
6283 case ARM::VLD4DUPdAsm_8:
6284 case ARM::VLD4DUPdAsm_16:
6285 case ARM::VLD4DUPdAsm_32:
6286 case ARM::VLD4DUPqAsm_8:
6287 case ARM::VLD4DUPqAsm_16:
6288 case ARM::VLD4DUPqAsm_32: {
6289 MCInst TmpInst;
6290 unsigned Spacing;
6291 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6292 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6293 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6294 Spacing));
6295 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6296 Spacing * 2));
6297 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6298 Spacing * 3));
6299 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6300 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6301 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6302 TmpInst.addOperand(Inst.getOperand(4));
6303 Inst = TmpInst;
6304 return true;
6305 }
6306
6307 case ARM::VLD4DUPdWB_fixed_Asm_8:
6308 case ARM::VLD4DUPdWB_fixed_Asm_16:
6309 case ARM::VLD4DUPdWB_fixed_Asm_32:
6310 case ARM::VLD4DUPqWB_fixed_Asm_8:
6311 case ARM::VLD4DUPqWB_fixed_Asm_16:
6312 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6313 MCInst TmpInst;
6314 unsigned Spacing;
6315 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6316 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6317 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6318 Spacing));
6319 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6320 Spacing * 2));
6321 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6322 Spacing * 3));
6323 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6324 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6325 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6326 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6327 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6328 TmpInst.addOperand(Inst.getOperand(4));
6329 Inst = TmpInst;
6330 return true;
6331 }
6332
6333 case ARM::VLD4DUPdWB_register_Asm_8:
6334 case ARM::VLD4DUPdWB_register_Asm_16:
6335 case ARM::VLD4DUPdWB_register_Asm_32:
6336 case ARM::VLD4DUPqWB_register_Asm_8:
6337 case ARM::VLD4DUPqWB_register_Asm_16:
6338 case ARM::VLD4DUPqWB_register_Asm_32: {
6339 MCInst TmpInst;
6340 unsigned Spacing;
6341 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6342 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6343 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6344 Spacing));
6345 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6346 Spacing * 2));
6347 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6348 Spacing * 3));
6349 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6350 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6351 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6352 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6353 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6354 TmpInst.addOperand(Inst.getOperand(5));
6355 Inst = TmpInst;
6356 return true;
6357 }
6358
6359 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006360 case ARM::VLD4dAsm_8:
6361 case ARM::VLD4dAsm_16:
6362 case ARM::VLD4dAsm_32:
6363 case ARM::VLD4qAsm_8:
6364 case ARM::VLD4qAsm_16:
6365 case ARM::VLD4qAsm_32: {
6366 MCInst TmpInst;
6367 unsigned Spacing;
6368 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6369 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6370 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6371 Spacing));
6372 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6373 Spacing * 2));
6374 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6375 Spacing * 3));
6376 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6377 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6378 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6379 TmpInst.addOperand(Inst.getOperand(4));
6380 Inst = TmpInst;
6381 return true;
6382 }
6383
6384 case ARM::VLD4dWB_fixed_Asm_8:
6385 case ARM::VLD4dWB_fixed_Asm_16:
6386 case ARM::VLD4dWB_fixed_Asm_32:
6387 case ARM::VLD4qWB_fixed_Asm_8:
6388 case ARM::VLD4qWB_fixed_Asm_16:
6389 case ARM::VLD4qWB_fixed_Asm_32: {
6390 MCInst TmpInst;
6391 unsigned Spacing;
6392 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6393 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6394 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6395 Spacing));
6396 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6397 Spacing * 2));
6398 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6399 Spacing * 3));
6400 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6401 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6402 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6403 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6404 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6405 TmpInst.addOperand(Inst.getOperand(4));
6406 Inst = TmpInst;
6407 return true;
6408 }
6409
6410 case ARM::VLD4dWB_register_Asm_8:
6411 case ARM::VLD4dWB_register_Asm_16:
6412 case ARM::VLD4dWB_register_Asm_32:
6413 case ARM::VLD4qWB_register_Asm_8:
6414 case ARM::VLD4qWB_register_Asm_16:
6415 case ARM::VLD4qWB_register_Asm_32: {
6416 MCInst TmpInst;
6417 unsigned Spacing;
6418 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6419 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6420 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6421 Spacing));
6422 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6423 Spacing * 2));
6424 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6425 Spacing * 3));
6426 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6427 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6428 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6429 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6430 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6431 TmpInst.addOperand(Inst.getOperand(5));
6432 Inst = TmpInst;
6433 return true;
6434 }
6435
Jim Grosbachd7433e22012-01-23 23:45:44 +00006436 // VST3 multiple 3-element structure instructions.
6437 case ARM::VST3dAsm_8:
6438 case ARM::VST3dAsm_16:
6439 case ARM::VST3dAsm_32:
6440 case ARM::VST3qAsm_8:
6441 case ARM::VST3qAsm_16:
6442 case ARM::VST3qAsm_32: {
6443 MCInst TmpInst;
6444 unsigned Spacing;
6445 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6446 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6447 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6448 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6449 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6450 Spacing));
6451 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6452 Spacing * 2));
6453 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6454 TmpInst.addOperand(Inst.getOperand(4));
6455 Inst = TmpInst;
6456 return true;
6457 }
6458
6459 case ARM::VST3dWB_fixed_Asm_8:
6460 case ARM::VST3dWB_fixed_Asm_16:
6461 case ARM::VST3dWB_fixed_Asm_32:
6462 case ARM::VST3qWB_fixed_Asm_8:
6463 case ARM::VST3qWB_fixed_Asm_16:
6464 case ARM::VST3qWB_fixed_Asm_32: {
6465 MCInst TmpInst;
6466 unsigned Spacing;
6467 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6468 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6469 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6470 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6471 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6472 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6473 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6474 Spacing));
6475 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6476 Spacing * 2));
6477 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6478 TmpInst.addOperand(Inst.getOperand(4));
6479 Inst = TmpInst;
6480 return true;
6481 }
6482
6483 case ARM::VST3dWB_register_Asm_8:
6484 case ARM::VST3dWB_register_Asm_16:
6485 case ARM::VST3dWB_register_Asm_32:
6486 case ARM::VST3qWB_register_Asm_8:
6487 case ARM::VST3qWB_register_Asm_16:
6488 case ARM::VST3qWB_register_Asm_32: {
6489 MCInst TmpInst;
6490 unsigned Spacing;
6491 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6492 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6493 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6494 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6495 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6496 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6497 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6498 Spacing));
6499 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6500 Spacing * 2));
6501 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6502 TmpInst.addOperand(Inst.getOperand(5));
6503 Inst = TmpInst;
6504 return true;
6505 }
6506
Jim Grosbach539aab72012-01-24 00:58:13 +00006507 // VST4 multiple 3-element structure instructions.
6508 case ARM::VST4dAsm_8:
6509 case ARM::VST4dAsm_16:
6510 case ARM::VST4dAsm_32:
6511 case ARM::VST4qAsm_8:
6512 case ARM::VST4qAsm_16:
6513 case ARM::VST4qAsm_32: {
6514 MCInst TmpInst;
6515 unsigned Spacing;
6516 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6517 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6518 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6519 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6520 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6521 Spacing));
6522 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6523 Spacing * 2));
6524 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6525 Spacing * 3));
6526 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6527 TmpInst.addOperand(Inst.getOperand(4));
6528 Inst = TmpInst;
6529 return true;
6530 }
6531
6532 case ARM::VST4dWB_fixed_Asm_8:
6533 case ARM::VST4dWB_fixed_Asm_16:
6534 case ARM::VST4dWB_fixed_Asm_32:
6535 case ARM::VST4qWB_fixed_Asm_8:
6536 case ARM::VST4qWB_fixed_Asm_16:
6537 case ARM::VST4qWB_fixed_Asm_32: {
6538 MCInst TmpInst;
6539 unsigned Spacing;
6540 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6541 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6542 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6543 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6544 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6545 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6546 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6547 Spacing));
6548 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6549 Spacing * 2));
6550 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6551 Spacing * 3));
6552 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6553 TmpInst.addOperand(Inst.getOperand(4));
6554 Inst = TmpInst;
6555 return true;
6556 }
6557
6558 case ARM::VST4dWB_register_Asm_8:
6559 case ARM::VST4dWB_register_Asm_16:
6560 case ARM::VST4dWB_register_Asm_32:
6561 case ARM::VST4qWB_register_Asm_8:
6562 case ARM::VST4qWB_register_Asm_16:
6563 case ARM::VST4qWB_register_Asm_32: {
6564 MCInst TmpInst;
6565 unsigned Spacing;
6566 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6567 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6568 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6569 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6570 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6571 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6572 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6573 Spacing));
6574 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6575 Spacing * 2));
6576 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6577 Spacing * 3));
6578 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6579 TmpInst.addOperand(Inst.getOperand(5));
6580 Inst = TmpInst;
6581 return true;
6582 }
6583
Jim Grosbach863d2af2011-12-13 22:45:11 +00006584 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006585 case ARM::t2MOVsr:
6586 case ARM::t2MOVSsr: {
6587 // Which instruction to expand to depends on the CCOut operand and
6588 // whether we're in an IT block if the register operands are low
6589 // registers.
6590 bool isNarrow = false;
6591 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6592 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6593 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6594 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6595 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6596 isNarrow = true;
6597 MCInst TmpInst;
6598 unsigned newOpc;
6599 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6600 default: llvm_unreachable("unexpected opcode!");
6601 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6602 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6603 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6604 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6605 }
6606 TmpInst.setOpcode(newOpc);
6607 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6608 if (isNarrow)
6609 TmpInst.addOperand(MCOperand::CreateReg(
6610 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6611 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6612 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6613 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6614 TmpInst.addOperand(Inst.getOperand(5));
6615 if (!isNarrow)
6616 TmpInst.addOperand(MCOperand::CreateReg(
6617 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6618 Inst = TmpInst;
6619 return true;
6620 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006621 case ARM::t2MOVsi:
6622 case ARM::t2MOVSsi: {
6623 // Which instruction to expand to depends on the CCOut operand and
6624 // whether we're in an IT block if the register operands are low
6625 // registers.
6626 bool isNarrow = false;
6627 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6628 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6629 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6630 isNarrow = true;
6631 MCInst TmpInst;
6632 unsigned newOpc;
6633 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6634 default: llvm_unreachable("unexpected opcode!");
6635 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6636 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6637 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6638 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006639 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006640 }
6641 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6642 if (Ammount == 32) Ammount = 0;
6643 TmpInst.setOpcode(newOpc);
6644 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6645 if (isNarrow)
6646 TmpInst.addOperand(MCOperand::CreateReg(
6647 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6648 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006649 if (newOpc != ARM::t2RRX)
6650 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006651 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6652 TmpInst.addOperand(Inst.getOperand(4));
6653 if (!isNarrow)
6654 TmpInst.addOperand(MCOperand::CreateReg(
6655 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6656 Inst = TmpInst;
6657 return true;
6658 }
6659 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006660 case ARM::ASRr:
6661 case ARM::LSRr:
6662 case ARM::LSLr:
6663 case ARM::RORr: {
6664 ARM_AM::ShiftOpc ShiftTy;
6665 switch(Inst.getOpcode()) {
6666 default: llvm_unreachable("unexpected opcode!");
6667 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6668 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6669 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6670 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6671 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006672 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6673 MCInst TmpInst;
6674 TmpInst.setOpcode(ARM::MOVsr);
6675 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6676 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6677 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6678 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6679 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6680 TmpInst.addOperand(Inst.getOperand(4));
6681 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6682 Inst = TmpInst;
6683 return true;
6684 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006685 case ARM::ASRi:
6686 case ARM::LSRi:
6687 case ARM::LSLi:
6688 case ARM::RORi: {
6689 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006690 switch(Inst.getOpcode()) {
6691 default: llvm_unreachable("unexpected opcode!");
6692 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6693 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6694 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6695 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6696 }
6697 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006698 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006699 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6700 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006701 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006702 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006703 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6704 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006705 if (Opc == ARM::MOVsi)
6706 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006707 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6708 TmpInst.addOperand(Inst.getOperand(4));
6709 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6710 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006711 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006712 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006713 case ARM::RRXi: {
6714 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6715 MCInst TmpInst;
6716 TmpInst.setOpcode(ARM::MOVsi);
6717 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6718 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6719 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6720 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6721 TmpInst.addOperand(Inst.getOperand(3));
6722 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6723 Inst = TmpInst;
6724 return true;
6725 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006726 case ARM::t2LDMIA_UPD: {
6727 // If this is a load of a single register, then we should use
6728 // a post-indexed LDR instruction instead, per the ARM ARM.
6729 if (Inst.getNumOperands() != 5)
6730 return false;
6731 MCInst TmpInst;
6732 TmpInst.setOpcode(ARM::t2LDR_POST);
6733 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6734 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6735 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6736 TmpInst.addOperand(MCOperand::CreateImm(4));
6737 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6738 TmpInst.addOperand(Inst.getOperand(3));
6739 Inst = TmpInst;
6740 return true;
6741 }
6742 case ARM::t2STMDB_UPD: {
6743 // If this is a store of a single register, then we should use
6744 // a pre-indexed STR instruction instead, per the ARM ARM.
6745 if (Inst.getNumOperands() != 5)
6746 return false;
6747 MCInst TmpInst;
6748 TmpInst.setOpcode(ARM::t2STR_PRE);
6749 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6750 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6751 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6752 TmpInst.addOperand(MCOperand::CreateImm(-4));
6753 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6754 TmpInst.addOperand(Inst.getOperand(3));
6755 Inst = TmpInst;
6756 return true;
6757 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006758 case ARM::LDMIA_UPD:
6759 // If this is a load of a single register via a 'pop', then we should use
6760 // a post-indexed LDR instruction instead, per the ARM ARM.
6761 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6762 Inst.getNumOperands() == 5) {
6763 MCInst TmpInst;
6764 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6765 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6766 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6767 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6768 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6769 TmpInst.addOperand(MCOperand::CreateImm(4));
6770 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6771 TmpInst.addOperand(Inst.getOperand(3));
6772 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006773 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006774 }
6775 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006776 case ARM::STMDB_UPD:
6777 // If this is a store of a single register via a 'push', then we should use
6778 // a pre-indexed STR instruction instead, per the ARM ARM.
6779 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6780 Inst.getNumOperands() == 5) {
6781 MCInst TmpInst;
6782 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6783 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6784 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6785 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6786 TmpInst.addOperand(MCOperand::CreateImm(-4));
6787 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6788 TmpInst.addOperand(Inst.getOperand(3));
6789 Inst = TmpInst;
6790 }
6791 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006792 case ARM::t2ADDri12:
6793 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6794 // mnemonic was used (not "addw"), encoding T3 is preferred.
6795 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6796 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6797 break;
6798 Inst.setOpcode(ARM::t2ADDri);
6799 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6800 break;
6801 case ARM::t2SUBri12:
6802 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6803 // mnemonic was used (not "subw"), encoding T3 is preferred.
6804 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6805 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6806 break;
6807 Inst.setOpcode(ARM::t2SUBri);
6808 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6809 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006810 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006811 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6812 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6813 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6814 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006815 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006816 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006817 return true;
6818 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006819 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006820 case ARM::tSUBi8:
6821 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6822 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6823 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6824 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006825 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006826 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006827 return true;
6828 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006829 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006830 case ARM::t2ADDrr: {
6831 // If the destination and first source operand are the same, and
6832 // there's no setting of the flags, use encoding T2 instead of T3.
6833 // Note that this is only for ADD, not SUB. This mirrors the system
6834 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6835 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6836 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006837 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6838 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006839 break;
6840 MCInst TmpInst;
6841 TmpInst.setOpcode(ARM::tADDhirr);
6842 TmpInst.addOperand(Inst.getOperand(0));
6843 TmpInst.addOperand(Inst.getOperand(0));
6844 TmpInst.addOperand(Inst.getOperand(2));
6845 TmpInst.addOperand(Inst.getOperand(3));
6846 TmpInst.addOperand(Inst.getOperand(4));
6847 Inst = TmpInst;
6848 return true;
6849 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006850 case ARM::tB:
6851 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006852 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006853 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006854 return true;
6855 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006856 break;
6857 case ARM::t2B:
6858 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006859 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006860 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006861 return true;
6862 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006863 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006864 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006865 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006866 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006867 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006868 return true;
6869 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006870 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006871 case ARM::tBcc:
6872 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006873 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006874 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006875 return true;
6876 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006877 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006878 case ARM::tLDMIA: {
6879 // If the register list contains any high registers, or if the writeback
6880 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6881 // instead if we're in Thumb2. Otherwise, this should have generated
6882 // an error in validateInstruction().
6883 unsigned Rn = Inst.getOperand(0).getReg();
6884 bool hasWritebackToken =
6885 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6886 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6887 bool listContainsBase;
6888 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6889 (!listContainsBase && !hasWritebackToken) ||
6890 (listContainsBase && hasWritebackToken)) {
6891 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6892 assert (isThumbTwo());
6893 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6894 // If we're switching to the updating version, we need to insert
6895 // the writeback tied operand.
6896 if (hasWritebackToken)
6897 Inst.insert(Inst.begin(),
6898 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006899 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006900 }
6901 break;
6902 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006903 case ARM::tSTMIA_UPD: {
6904 // If the register list contains any high registers, we need to use
6905 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6906 // should have generated an error in validateInstruction().
6907 unsigned Rn = Inst.getOperand(0).getReg();
6908 bool listContainsBase;
6909 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6910 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6911 assert (isThumbTwo());
6912 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006913 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006914 }
6915 break;
6916 }
Jim Grosbach54026372011-11-10 23:17:11 +00006917 case ARM::tPOP: {
6918 bool listContainsBase;
6919 // If the register list contains any high registers, we need to use
6920 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6921 // should have generated an error in validateInstruction().
6922 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006923 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006924 assert (isThumbTwo());
6925 Inst.setOpcode(ARM::t2LDMIA_UPD);
6926 // Add the base register and writeback operands.
6927 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6928 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006929 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006930 }
6931 case ARM::tPUSH: {
6932 bool listContainsBase;
6933 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006934 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006935 assert (isThumbTwo());
6936 Inst.setOpcode(ARM::t2STMDB_UPD);
6937 // Add the base register and writeback operands.
6938 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6939 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006940 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006941 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006942 case ARM::t2MOVi: {
6943 // If we can use the 16-bit encoding and the user didn't explicitly
6944 // request the 32-bit variant, transform it here.
6945 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6946 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006947 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6948 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6949 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006950 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6951 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6952 // The operands aren't in the same order for tMOVi8...
6953 MCInst TmpInst;
6954 TmpInst.setOpcode(ARM::tMOVi8);
6955 TmpInst.addOperand(Inst.getOperand(0));
6956 TmpInst.addOperand(Inst.getOperand(4));
6957 TmpInst.addOperand(Inst.getOperand(1));
6958 TmpInst.addOperand(Inst.getOperand(2));
6959 TmpInst.addOperand(Inst.getOperand(3));
6960 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006961 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006962 }
6963 break;
6964 }
6965 case ARM::t2MOVr: {
6966 // If we can use the 16-bit encoding and the user didn't explicitly
6967 // request the 32-bit variant, transform it here.
6968 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6969 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6970 Inst.getOperand(2).getImm() == ARMCC::AL &&
6971 Inst.getOperand(4).getReg() == ARM::CPSR &&
6972 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6973 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6974 // The operands aren't the same for tMOV[S]r... (no cc_out)
6975 MCInst TmpInst;
6976 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6977 TmpInst.addOperand(Inst.getOperand(0));
6978 TmpInst.addOperand(Inst.getOperand(1));
6979 TmpInst.addOperand(Inst.getOperand(2));
6980 TmpInst.addOperand(Inst.getOperand(3));
6981 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006982 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006983 }
6984 break;
6985 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006986 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006987 case ARM::t2SXTB:
6988 case ARM::t2UXTH:
6989 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006990 // If we can use the 16-bit encoding and the user didn't explicitly
6991 // request the 32-bit variant, transform it here.
6992 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6993 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6994 Inst.getOperand(2).getImm() == 0 &&
6995 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6996 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006997 unsigned NewOpc;
6998 switch (Inst.getOpcode()) {
6999 default: llvm_unreachable("Illegal opcode!");
7000 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7001 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7002 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7003 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7004 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007005 // The operands aren't the same for thumb1 (no rotate operand).
7006 MCInst TmpInst;
7007 TmpInst.setOpcode(NewOpc);
7008 TmpInst.addOperand(Inst.getOperand(0));
7009 TmpInst.addOperand(Inst.getOperand(1));
7010 TmpInst.addOperand(Inst.getOperand(3));
7011 TmpInst.addOperand(Inst.getOperand(4));
7012 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007013 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007014 }
7015 break;
7016 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007017 case ARM::MOVsi: {
7018 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7019 if (SOpc == ARM_AM::rrx) return false;
7020 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7021 // Shifting by zero is accepted as a vanilla 'MOVr'
7022 MCInst TmpInst;
7023 TmpInst.setOpcode(ARM::MOVr);
7024 TmpInst.addOperand(Inst.getOperand(0));
7025 TmpInst.addOperand(Inst.getOperand(1));
7026 TmpInst.addOperand(Inst.getOperand(3));
7027 TmpInst.addOperand(Inst.getOperand(4));
7028 TmpInst.addOperand(Inst.getOperand(5));
7029 Inst = TmpInst;
7030 return true;
7031 }
7032 return false;
7033 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007034 case ARM::ANDrsi:
7035 case ARM::ORRrsi:
7036 case ARM::EORrsi:
7037 case ARM::BICrsi:
7038 case ARM::SUBrsi:
7039 case ARM::ADDrsi: {
7040 unsigned newOpc;
7041 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7042 if (SOpc == ARM_AM::rrx) return false;
7043 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007044 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007045 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7046 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7047 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7048 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7049 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7050 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7051 }
7052 // If the shift is by zero, use the non-shifted instruction definition.
7053 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7054 MCInst TmpInst;
7055 TmpInst.setOpcode(newOpc);
7056 TmpInst.addOperand(Inst.getOperand(0));
7057 TmpInst.addOperand(Inst.getOperand(1));
7058 TmpInst.addOperand(Inst.getOperand(2));
7059 TmpInst.addOperand(Inst.getOperand(4));
7060 TmpInst.addOperand(Inst.getOperand(5));
7061 TmpInst.addOperand(Inst.getOperand(6));
7062 Inst = TmpInst;
7063 return true;
7064 }
7065 return false;
7066 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007067 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007068 case ARM::t2IT: {
7069 // The mask bits for all but the first condition are represented as
7070 // the low bit of the condition code value implies 't'. We currently
7071 // always have 1 implies 't', so XOR toggle the bits if the low bit
7072 // of the condition code is zero. The encoding also expects the low
7073 // bit of the condition to be encoded as bit 4 of the mask operand,
7074 // so mask that in if needed
7075 MCOperand &MO = Inst.getOperand(1);
7076 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007077 unsigned OrigMask = Mask;
7078 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007079 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007080 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7081 for (unsigned i = 3; i != TZ; --i)
7082 Mask ^= 1 << i;
7083 } else
7084 Mask |= 0x10;
7085 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007086
7087 // Set up the IT block state according to the IT instruction we just
7088 // matched.
7089 assert(!inITBlock() && "nested IT blocks?!");
7090 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7091 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7092 ITState.CurPosition = 0;
7093 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007094 break;
7095 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007096 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007097 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007098}
7099
Jim Grosbach47a0d522011-08-16 20:45:50 +00007100unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7101 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7102 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007103 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007104 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007105 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7106 assert(MCID.hasOptionalDef() &&
7107 "optionally flag setting instruction missing optional def operand");
7108 assert(MCID.NumOperands == Inst.getNumOperands() &&
7109 "operand count mismatch!");
7110 // Find the optional-def operand (cc_out).
7111 unsigned OpNo;
7112 for (OpNo = 0;
7113 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7114 ++OpNo)
7115 ;
7116 // If we're parsing Thumb1, reject it completely.
7117 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7118 return Match_MnemonicFail;
7119 // If we're parsing Thumb2, which form is legal depends on whether we're
7120 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007121 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7122 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007123 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007124 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7125 inITBlock())
7126 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007127 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007128 // Some high-register supporting Thumb1 encodings only allow both registers
7129 // to be from r0-r7 when in Thumb2.
7130 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7131 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7132 isARMLowRegister(Inst.getOperand(2).getReg()))
7133 return Match_RequiresThumb2;
7134 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007135 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007136 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7137 isARMLowRegister(Inst.getOperand(1).getReg()))
7138 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007139 return Match_Success;
7140}
7141
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007142bool ARMAsmParser::
7143MatchAndEmitInstruction(SMLoc IDLoc,
7144 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7145 MCStreamer &Out) {
7146 MCInst Inst;
7147 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007148 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007149 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007150 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007151 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007152 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007153 // Context sensitive operand constraints aren't handled by the matcher,
7154 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007155 if (validateInstruction(Inst, Operands)) {
7156 // Still progress the IT block, otherwise one wrong condition causes
7157 // nasty cascading errors.
7158 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007159 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007160 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007161
Jim Grosbachf8fce712011-08-11 17:35:48 +00007162 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007163 // encoding is selected. Loop on it while changes happen so the
7164 // individual transformations can chain off each other. E.g.,
7165 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7166 while (processInstruction(Inst, Operands))
7167 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007168
Jim Grosbacha1109882011-09-02 23:22:08 +00007169 // Only move forward at the very end so that everything in validate
7170 // and process gets a consistent answer about whether we're in an IT
7171 // block.
7172 forwardITPosition();
7173
Jim Grosbach74423e32012-01-25 19:52:01 +00007174 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7175 // doesn't actually encode.
7176 if (Inst.getOpcode() == ARM::ITasm)
7177 return false;
7178
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007179 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007180 Out.EmitInstruction(Inst);
7181 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007182 case Match_MissingFeature:
7183 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
7184 return true;
7185 case Match_InvalidOperand: {
7186 SMLoc ErrorLoc = IDLoc;
7187 if (ErrorInfo != ~0U) {
7188 if (ErrorInfo >= Operands.size())
7189 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007190
Chris Lattnere73d4f82010-10-28 21:41:58 +00007191 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7192 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7193 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007194
Chris Lattnere73d4f82010-10-28 21:41:58 +00007195 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007196 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007197 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00007198 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00007199 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007200 // The converter function will have already emited a diagnostic.
7201 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007202 case Match_RequiresNotITBlock:
7203 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007204 case Match_RequiresITBlock:
7205 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007206 case Match_RequiresV6:
7207 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7208 case Match_RequiresThumb2:
7209 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00007210 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007211
Eric Christopherc223e2b2010-10-29 09:26:59 +00007212 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007213}
7214
Jim Grosbach1355cf12011-07-26 17:10:22 +00007215/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007216bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7217 StringRef IDVal = DirectiveID.getIdentifier();
7218 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007219 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007220 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007221 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007222 else if (IDVal == ".arm")
7223 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007224 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007225 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007226 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007227 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007228 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007229 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007230 else if (IDVal == ".unreq")
7231 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007232 else if (IDVal == ".arch")
7233 return parseDirectiveArch(DirectiveID.getLoc());
7234 else if (IDVal == ".eabi_attribute")
7235 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007236 return true;
7237}
7238
Jim Grosbach1355cf12011-07-26 17:10:22 +00007239/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007240/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007241bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007242 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7243 for (;;) {
7244 const MCExpr *Value;
7245 if (getParser().ParseExpression(Value))
7246 return true;
7247
Chris Lattneraaec2052010-01-19 19:46:13 +00007248 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007249
7250 if (getLexer().is(AsmToken::EndOfStatement))
7251 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007252
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007253 // FIXME: Improve diagnostic.
7254 if (getLexer().isNot(AsmToken::Comma))
7255 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007256 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007257 }
7258 }
7259
Sean Callananb9a25b72010-01-19 20:27:46 +00007260 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007261 return false;
7262}
7263
Jim Grosbach1355cf12011-07-26 17:10:22 +00007264/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007265/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007266bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007267 if (getLexer().isNot(AsmToken::EndOfStatement))
7268 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007269 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007270
Jim Grosbach9a70df92011-12-07 18:04:19 +00007271 if (!isThumb())
7272 SwitchMode();
7273 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7274 return false;
7275}
7276
7277/// parseDirectiveARM
7278/// ::= .arm
7279bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7280 if (getLexer().isNot(AsmToken::EndOfStatement))
7281 return Error(L, "unexpected token in directive");
7282 Parser.Lex();
7283
7284 if (isThumb())
7285 SwitchMode();
7286 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007287 return false;
7288}
7289
Jim Grosbach1355cf12011-07-26 17:10:22 +00007290/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007291/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007292bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007293 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7294 bool isMachO = MAI.hasSubsectionsViaSymbols();
7295 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007296 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007297
Jim Grosbachde4d8392011-12-21 22:30:16 +00007298 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007299 // ELF doesn't
7300 if (isMachO) {
7301 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007302 if (Tok.isNot(AsmToken::EndOfStatement)) {
7303 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7304 return Error(L, "unexpected token in .thumb_func directive");
7305 Name = Tok.getIdentifier();
7306 Parser.Lex(); // Consume the identifier token.
7307 needFuncName = false;
7308 }
Rafael Espindola64695402011-05-16 16:17:21 +00007309 }
7310
Jim Grosbachde4d8392011-12-21 22:30:16 +00007311 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007312 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007313
7314 // Eat the end of statement and any blank lines that follow.
7315 while (getLexer().is(AsmToken::EndOfStatement))
7316 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007317
Rafael Espindola64695402011-05-16 16:17:21 +00007318 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007319 // We really should be checking the next symbol definition even if there's
7320 // stuff in between.
7321 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007322 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007323 }
7324
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007325 // Mark symbol as a thumb symbol.
7326 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7327 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007328 return false;
7329}
7330
Jim Grosbach1355cf12011-07-26 17:10:22 +00007331/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007332/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007333bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007334 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007335 if (Tok.isNot(AsmToken::Identifier))
7336 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007337 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007338 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007339 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007340 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007341 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007342 else
7343 return Error(L, "unrecognized syntax mode in .syntax directive");
7344
7345 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007346 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007347 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007348
7349 // TODO tell the MC streamer the mode
7350 // getParser().getStreamer().Emit???();
7351 return false;
7352}
7353
Jim Grosbach1355cf12011-07-26 17:10:22 +00007354/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007355/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007356bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007357 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007358 if (Tok.isNot(AsmToken::Integer))
7359 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007360 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007361 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007362 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007363 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007364 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007365 else
7366 return Error(L, "invalid operand to .code directive");
7367
7368 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007369 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007370 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007371
Evan Cheng32869202011-07-08 22:36:29 +00007372 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007373 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007374 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007375 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007376 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007377 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007378 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007379 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007380 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007381
Kevin Enderby515d5092009-10-15 20:48:48 +00007382 return false;
7383}
7384
Jim Grosbacha39cda72011-12-14 02:16:11 +00007385/// parseDirectiveReq
7386/// ::= name .req registername
7387bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7388 Parser.Lex(); // Eat the '.req' token.
7389 unsigned Reg;
7390 SMLoc SRegLoc, ERegLoc;
7391 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7392 Parser.EatToEndOfStatement();
7393 return Error(SRegLoc, "register name expected");
7394 }
7395
7396 // Shouldn't be anything else.
7397 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7398 Parser.EatToEndOfStatement();
7399 return Error(Parser.getTok().getLoc(),
7400 "unexpected input in .req directive.");
7401 }
7402
7403 Parser.Lex(); // Consume the EndOfStatement
7404
7405 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7406 return Error(SRegLoc, "redefinition of '" + Name +
7407 "' does not match original.");
7408
7409 return false;
7410}
7411
7412/// parseDirectiveUneq
7413/// ::= .unreq registername
7414bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7415 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7416 Parser.EatToEndOfStatement();
7417 return Error(L, "unexpected input in .unreq directive.");
7418 }
7419 RegisterReqs.erase(Parser.getTok().getIdentifier());
7420 Parser.Lex(); // Eat the identifier.
7421 return false;
7422}
7423
Jason W Kimd7c9e082011-12-20 17:38:12 +00007424/// parseDirectiveArch
7425/// ::= .arch token
7426bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7427 return true;
7428}
7429
7430/// parseDirectiveEabiAttr
7431/// ::= .eabi_attribute int, int
7432bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7433 return true;
7434}
7435
Sean Callanan90b70972010-04-07 20:29:34 +00007436extern "C" void LLVMInitializeARMAsmLexer();
7437
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007438/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007439extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007440 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7441 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007442 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007443}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007444
Chris Lattner0692ee62010-09-06 19:11:01 +00007445#define GET_REGISTER_MATCHER
7446#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007447#include "ARMGenAsmMatcher.inc"