blob: c8e733df2d2f17443fe8ec627fb2c62a1b8322b5 [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;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan76264762010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbach862019c2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendling8155e5b2010-11-06 22:19:43 +0000344 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000351
Jim Grosbach9d390362011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000400
Bill Wendling146018f2010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan76264762010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000425 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan76264762010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000479
Sean Callanan76264762010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Daniel Dunbar8462b302010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503 }
504
Bill Wendling5fa22a12010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000509 }
510
Kevin Enderbycfe07242009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000512 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbach9d390362011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbach460a9052011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000550 bool isFBits16() const {
551 if (!isImm()) return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return Value >= 0 && Value <= 16;
556 }
557 bool isFBits32() const {
558 if (!isImm()) return false;
559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return Value >= 1 && Value <= 32;
563 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000564 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
570 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000571 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000572 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
577 }
578 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
584 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000585 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 256;
591 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000592 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000593 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
595 if (!CE) return false;
596 int64_t Value = CE->getValue();
597 return Value >= 0 && Value < 2;
598 }
599 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 4;
605 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000606 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000607 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 8;
612 }
613 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 16;
619 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000620 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 32;
626 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000627 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value >= 0 && Value < 64;
633 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000634 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000635 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000636 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
637 if (!CE) return false;
638 int64_t Value = CE->getValue();
639 return Value == 8;
640 }
641 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000642 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value == 16;
647 }
648 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value == 32;
654 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000655 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000656 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 8;
661 }
662 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000663 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000664 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665 if (!CE) return false;
666 int64_t Value = CE->getValue();
667 return Value > 0 && Value <= 16;
668 }
669 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000670 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value <= 32;
675 }
676 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value <= 64;
682 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000683 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000684 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
686 if (!CE) return false;
687 int64_t Value = CE->getValue();
688 return Value > 0 && Value < 8;
689 }
690 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000691 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000692 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693 if (!CE) return false;
694 int64_t Value = CE->getValue();
695 return Value > 0 && Value < 16;
696 }
697 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 32;
703 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000704 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 17;
710 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000711 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 33;
717 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000718 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 33;
724 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000725 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 if (!CE) return false;
729 int64_t Value = CE->getValue();
730 return Value >= 0 && Value < 65536;
731 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000732 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000733 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000734 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
735 // If it's not a constant expression, it'll generate a fixup and be
736 // handled later.
737 if (!CE) return true;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value < 65536;
740 }
Jim Grosbached838482011-07-26 16:24:27 +0000741 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value >= 0 && Value <= 0xffffff;
747 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000748 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value > 0 && Value < 33;
754 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000755 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value >= 0 && Value < 32;
761 }
762 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return Value > 0 && Value <= 32;
768 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000769 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return ARM_AM::getSOImmVal(Value) != -1;
775 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000776 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779 if (!CE) return false;
780 int64_t Value = CE->getValue();
781 return ARM_AM::getSOImmVal(~Value) != -1;
782 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000783 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getSOImmVal(-Value) != -1;
789 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000790 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getT2SOImmVal(Value) != -1;
796 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000797 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800 if (!CE) return false;
801 int64_t Value = CE->getValue();
802 return ARM_AM::getT2SOImmVal(~Value) != -1;
803 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000804 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return ARM_AM::getT2SOImmVal(-Value) != -1;
810 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000811 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000812 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000813 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
814 if (!CE) return false;
815 int64_t Value = CE->getValue();
816 return Value == 1 || Value == 0;
817 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000818 bool isReg() const { return Kind == k_Register; }
819 bool isRegList() const { return Kind == k_RegisterList; }
820 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
821 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
822 bool isToken() const { return Kind == k_Token; }
823 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
824 bool isMemory() const { return Kind == k_Memory; }
825 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
826 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
827 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
828 bool isRotImm() const { return Kind == k_RotateImmediate; }
829 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
830 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000831 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000832 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000833 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000835 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000836 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000837 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000838 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
839 (alignOK || Memory.Alignment == 0);
840 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000841 bool isMemPCRelImm12() const {
842 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
843 return false;
844 // Base register must be PC.
845 if (Memory.BaseRegNum != ARM::PC)
846 return false;
847 // Immediate offset in range [-4095, 4095].
848 if (!Memory.OffsetImm) return true;
849 int64_t Val = Memory.OffsetImm->getValue();
850 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
851 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000852 bool isAlignedMemory() const {
853 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000854 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000857 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000858 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000860 if (!Memory.OffsetImm) return true;
861 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000862 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000863 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000864 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000865 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000866 // Immediate offset in range [-4095, 4095].
867 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
868 if (!CE) return false;
869 int64_t Val = CE->getValue();
870 return Val > -4096 && Val < 4096;
871 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000872 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000873 // If we have an immediate that's not a constant, treat it as a label
874 // reference needing a fixup. If it is a constant, it's something else
875 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000876 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000877 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000878 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000879 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000880 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000881 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000882 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000884 if (!Memory.OffsetImm) return true;
885 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000886 return Val > -256 && Val < 256;
887 }
888 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000889 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000890 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000891 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000892 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
893 // Immediate offset in range [-255, 255].
894 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
895 if (!CE) return false;
896 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000897 // Special case, #-0 is INT32_MIN.
898 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000899 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000900 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000901 // If we have an immediate that's not a constant, treat it as a label
902 // reference needing a fixup. If it is a constant, it's something else
903 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000904 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000905 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000906 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000907 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000908 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000909 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000910 if (!Memory.OffsetImm) return true;
911 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000912 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000913 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000914 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000915 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000916 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000917 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000918 return false;
919 return true;
920 }
921 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000923 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
924 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000925 return false;
926 return true;
927 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000928 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000929 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000930 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000931 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000932 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000933 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
935 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000936 return false;
937 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000938 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000939 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000940 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000941 return false;
942 return true;
943 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000944 bool isMemThumbRR() const {
945 // Thumb reg+reg addressing is simple. Just two registers, a base and
946 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000949 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000950 return isARMLowRegister(Memory.BaseRegNum) &&
951 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000952 }
953 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000954 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000955 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000956 return false;
957 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000958 if (!Memory.OffsetImm) return true;
959 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000960 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
961 }
Jim Grosbach38466302011-08-19 18:55:51 +0000962 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000963 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000964 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000965 return false;
966 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000967 if (!Memory.OffsetImm) return true;
968 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000969 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
970 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000972 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000973 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000974 return false;
975 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (!Memory.OffsetImm) return true;
977 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000978 return Val >= 0 && Val <= 31;
979 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000981 if (!isMemory() || Memory.OffsetRegNum != 0 ||
982 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000983 return false;
984 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000985 if (!Memory.OffsetImm) return true;
986 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000987 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000988 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000989 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000990 // If we have an immediate that's not a constant, treat it as a label
991 // reference needing a fixup. If it is a constant, it's something else
992 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000993 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000994 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000995 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000996 return false;
997 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000998 if (!Memory.OffsetImm) return true;
999 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001000 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1001 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001002 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001003 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001004 return false;
1005 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001006 if (!Memory.OffsetImm) return true;
1007 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001008 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1009 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001010 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001011 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001013 // Base reg of PC isn't allowed for these encodings.
1014 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001015 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001018 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001019 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001020 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001021 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001022 return false;
1023 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001024 if (!Memory.OffsetImm) return true;
1025 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001026 return Val >= 0 && Val < 256;
1027 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001028 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001029 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001031 // Base reg of PC isn't allowed for these encodings.
1032 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001033 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001034 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001036 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 }
1038 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001040 return false;
1041 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001042 if (!Memory.OffsetImm) return true;
1043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001044 return (Val >= 0 && Val < 4096);
1045 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001046 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001047 // If we have an immediate that's not a constant, treat it as a label
1048 // reference needing a fixup. If it is a constant, it's something else
1049 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001050 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001051 return true;
1052
Jim Grosbach57dcb852011-10-11 17:29:55 +00001053 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001054 return false;
1055 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001056 if (!Memory.OffsetImm) return true;
1057 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001058 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 }
1060 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001061 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001062 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1063 if (!CE) return false;
1064 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001065 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001066 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001067 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001068 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001069 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1070 if (!CE) return false;
1071 int64_t Val = CE->getValue();
1072 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1073 (Val == INT32_MIN);
1074 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001075
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001076 bool isMSRMask() const { return Kind == k_MSRMask; }
1077 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001078
Jim Grosbach0e387b22011-10-17 22:26:03 +00001079 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001080 bool isSingleSpacedVectorList() const {
1081 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1082 }
1083 bool isDoubleSpacedVectorList() const {
1084 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1085 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001086 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001087 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001088 return VectorList.Count == 1;
1089 }
1090
Jim Grosbach280dfad2011-10-21 18:54:25 +00001091 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001092 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001093 return VectorList.Count == 2;
1094 }
1095
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001096 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001098 return VectorList.Count == 3;
1099 }
1100
Jim Grosbachb6310312011-10-21 20:35:01 +00001101 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001103 return VectorList.Count == 4;
1104 }
1105
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001106 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001107 if (!isDoubleSpacedVectorList()) return false;
1108 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001109 }
1110
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001111 bool isSingleSpacedVectorAllLanes() const {
1112 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1113 }
1114 bool isDoubleSpacedVectorAllLanes() const {
1115 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1116 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001117 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001118 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001119 return VectorList.Count == 1;
1120 }
1121
Jim Grosbach13af2222011-11-30 18:21:25 +00001122 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001123 if (!isSingleSpacedVectorAllLanes()) return false;
1124 return VectorList.Count == 2;
1125 }
1126
1127 bool isVecListTwoQAllLanes() const {
1128 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001129 return VectorList.Count == 2;
1130 }
1131
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001132 bool isSingleSpacedVectorIndexed() const {
1133 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1134 }
1135 bool isDoubleSpacedVectorIndexed() const {
1136 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1137 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001138 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001139 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001140 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1141 }
1142
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001143 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001144 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001145 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1146 }
1147
1148 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001149 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001150 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1151 }
1152
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001153 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001154 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001155 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1156 }
1157
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001158 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001159 if (!isSingleSpacedVectorIndexed()) return false;
1160 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1161 }
1162
1163 bool isVecListTwoQWordIndexed() const {
1164 if (!isDoubleSpacedVectorIndexed()) return false;
1165 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1166 }
1167
1168 bool isVecListTwoQHWordIndexed() const {
1169 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001170 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1171 }
1172
1173 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001174 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001175 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1176 }
1177
Jim Grosbach460a9052011-10-07 23:56:00 +00001178 bool isVectorIndex8() const {
1179 if (Kind != k_VectorIndex) return false;
1180 return VectorIndex.Val < 8;
1181 }
1182 bool isVectorIndex16() const {
1183 if (Kind != k_VectorIndex) return false;
1184 return VectorIndex.Val < 4;
1185 }
1186 bool isVectorIndex32() const {
1187 if (Kind != k_VectorIndex) return false;
1188 return VectorIndex.Val < 2;
1189 }
1190
Jim Grosbach0e387b22011-10-17 22:26:03 +00001191 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001192 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001193 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1194 // Must be a constant.
1195 if (!CE) return false;
1196 int64_t Value = CE->getValue();
1197 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1198 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001199 return Value >= 0 && Value < 256;
1200 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001201
Jim Grosbachea461102011-10-17 23:09:09 +00001202 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001203 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1205 // Must be a constant.
1206 if (!CE) return false;
1207 int64_t Value = CE->getValue();
1208 // i16 value in the range [0,255] or [0x0100, 0xff00]
1209 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1210 }
1211
Jim Grosbach6248a542011-10-18 00:22:00 +00001212 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001213 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 // Must be a constant.
1216 if (!CE) return false;
1217 int64_t Value = CE->getValue();
1218 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1219 return (Value >= 0 && Value < 256) ||
1220 (Value >= 0x0100 && Value <= 0xff00) ||
1221 (Value >= 0x010000 && Value <= 0xff0000) ||
1222 (Value >= 0x01000000 && Value <= 0xff000000);
1223 }
1224
1225 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001226 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001227 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1228 // Must be a constant.
1229 if (!CE) return false;
1230 int64_t Value = CE->getValue();
1231 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1232 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1233 return (Value >= 0 && Value < 256) ||
1234 (Value >= 0x0100 && Value <= 0xff00) ||
1235 (Value >= 0x010000 && Value <= 0xff0000) ||
1236 (Value >= 0x01000000 && Value <= 0xff000000) ||
1237 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1238 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1239 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001240 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001241 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001242 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1243 // Must be a constant.
1244 if (!CE) return false;
1245 int64_t Value = ~CE->getValue();
1246 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1247 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1248 return (Value >= 0 && Value < 256) ||
1249 (Value >= 0x0100 && Value <= 0xff00) ||
1250 (Value >= 0x010000 && Value <= 0xff0000) ||
1251 (Value >= 0x01000000 && Value <= 0xff000000) ||
1252 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1253 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1254 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001255
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001256 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001257 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001258 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1259 // Must be a constant.
1260 if (!CE) return false;
1261 uint64_t Value = CE->getValue();
1262 // i64 value with each byte being either 0 or 0xff.
1263 for (unsigned i = 0; i < 8; ++i)
1264 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1265 return true;
1266 }
1267
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001268 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001269 // Add as immediates when possible. Null MCExpr = 0.
1270 if (Expr == 0)
1271 Inst.addOperand(MCOperand::CreateImm(0));
1272 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001273 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1274 else
1275 Inst.addOperand(MCOperand::CreateExpr(Expr));
1276 }
1277
Daniel Dunbar8462b302010-08-11 06:36:53 +00001278 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001279 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001280 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001281 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1282 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001283 }
1284
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001285 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
1287 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1288 }
1289
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001290 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1293 }
1294
1295 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
1297 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1298 }
1299
Jim Grosbach89df9962011-08-26 21:43:41 +00001300 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1301 assert(N == 1 && "Invalid number of operands!");
1302 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1303 }
1304
1305 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1306 assert(N == 1 && "Invalid number of operands!");
1307 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1308 }
1309
Jim Grosbachd67641b2010-12-06 18:21:12 +00001310 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
1312 Inst.addOperand(MCOperand::CreateReg(getReg()));
1313 }
1314
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001315 void addRegOperands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
1317 Inst.addOperand(MCOperand::CreateReg(getReg()));
1318 }
1319
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001320 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001321 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001322 assert(isRegShiftedReg() &&
1323 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001324 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1325 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001326 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001327 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001328 }
1329
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001330 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001331 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001332 assert(isRegShiftedImm() &&
1333 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001334 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001335 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001336 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001337 }
1338
Jim Grosbach580f4a92011-07-25 22:20:28 +00001339 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001340 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001341 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1342 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001343 }
1344
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001345 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001346 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001347 const SmallVectorImpl<unsigned> &RegList = getRegList();
1348 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001349 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1350 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001351 }
1352
Bill Wendling0f630752010-11-17 04:32:08 +00001353 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1354 addRegListOperands(Inst, N);
1355 }
1356
1357 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1358 addRegListOperands(Inst, N);
1359 }
1360
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001361 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1362 assert(N == 1 && "Invalid number of operands!");
1363 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1364 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1365 }
1366
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001367 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1368 assert(N == 1 && "Invalid number of operands!");
1369 // Munge the lsb/width into a bitfield mask.
1370 unsigned lsb = Bitfield.LSB;
1371 unsigned width = Bitfield.Width;
1372 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1373 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1374 (32 - (lsb + width)));
1375 Inst.addOperand(MCOperand::CreateImm(Mask));
1376 }
1377
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001378 void addImmOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 1 && "Invalid number of operands!");
1380 addExpr(Inst, getImm());
1381 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001382
Jim Grosbach4050bc42011-12-22 22:19:05 +00001383 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1386 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1387 }
1388
1389 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1392 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1393 }
1394
Jim Grosbach9d390362011-10-03 23:38:36 +00001395 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1398 }
1399
Jim Grosbacha77295d2011-09-08 22:07:06 +00001400 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1401 assert(N == 1 && "Invalid number of operands!");
1402 // FIXME: We really want to scale the value here, but the LDRD/STRD
1403 // instruction don't encode operands that way yet.
1404 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1405 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1406 }
1407
Jim Grosbach72f39f82011-08-24 21:22:15 +00001408 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1409 assert(N == 1 && "Invalid number of operands!");
1410 // The immediate is scaled by four in the encoding and is stored
1411 // in the MCInst as such. Lop off the low two bits here.
1412 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1413 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1414 }
1415
1416 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1417 assert(N == 1 && "Invalid number of operands!");
1418 // The immediate is scaled by four in the encoding and is stored
1419 // in the MCInst as such. Lop off the low two bits here.
1420 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1421 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1422 }
1423
Jim Grosbachf4943352011-07-25 23:09:14 +00001424 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 // The constant encodes as the immediate-1, and we store in the instruction
1427 // the bits as encoded, so subtract off one here.
1428 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1429 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1430 }
1431
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001432 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1433 assert(N == 1 && "Invalid number of operands!");
1434 // The constant encodes as the immediate-1, and we store in the instruction
1435 // the bits as encoded, so subtract off one here.
1436 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1437 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1438 }
1439
Jim Grosbach70939ee2011-08-17 21:51:27 +00001440 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 // The constant encodes as the immediate, except for 32, which encodes as
1443 // zero.
1444 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1445 unsigned Imm = CE->getValue();
1446 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1447 }
1448
Jim Grosbachf6c05252011-07-21 17:23:04 +00001449 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1452 // the instruction as well.
1453 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1454 int Val = CE->getValue();
1455 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1456 }
1457
Jim Grosbach89a63372011-10-28 22:36:30 +00001458 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1459 assert(N == 1 && "Invalid number of operands!");
1460 // The operand is actually a t2_so_imm, but we have its bitwise
1461 // negation in the assembly source, so twiddle it here.
1462 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1463 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1464 }
1465
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001466 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
1468 // The operand is actually a t2_so_imm, but we have its
1469 // negation in the assembly source, so twiddle it here.
1470 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1471 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1472 }
1473
Jim Grosbache70ec842011-10-28 22:50:54 +00001474 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1475 assert(N == 1 && "Invalid number of operands!");
1476 // The operand is actually a so_imm, but we have its bitwise
1477 // negation in the assembly source, so twiddle it here.
1478 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1479 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1480 }
1481
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001482 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 // The operand is actually a so_imm, but we have its
1485 // negation in the assembly source, so twiddle it here.
1486 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1487 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1488 }
1489
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001490 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1493 }
1494
Jim Grosbach7ce05792011-08-03 23:50:40 +00001495 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001497 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001498 }
1499
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001500 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1501 assert(N == 1 && "Invalid number of operands!");
1502 int32_t Imm = Memory.OffsetImm->getValue();
1503 // FIXME: Handle #-0
1504 if (Imm == INT32_MIN) Imm = 0;
1505 Inst.addOperand(MCOperand::CreateImm(Imm));
1506 }
1507
Jim Grosbach57dcb852011-10-11 17:29:55 +00001508 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1509 assert(N == 2 && "Invalid number of operands!");
1510 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1511 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1512 }
1513
Jim Grosbach7ce05792011-08-03 23:50:40 +00001514 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001516 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1517 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001518 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1519 // Special case for #-0
1520 if (Val == INT32_MIN) Val = 0;
1521 if (Val < 0) Val = -Val;
1522 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1523 } else {
1524 // For register offset, we encode the shift type and negation flag
1525 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001526 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1527 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001528 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001529 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1530 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001531 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001532 }
1533
Jim Grosbach039c2e12011-08-04 23:01:30 +00001534 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1537 assert(CE && "non-constant AM2OffsetImm operand!");
1538 int32_t Val = CE->getValue();
1539 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1540 // Special case for #-0
1541 if (Val == INT32_MIN) Val = 0;
1542 if (Val < 0) Val = -Val;
1543 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1544 Inst.addOperand(MCOperand::CreateReg(0));
1545 Inst.addOperand(MCOperand::CreateImm(Val));
1546 }
1547
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001548 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1549 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001550 // If we have an immediate that's not a constant, treat it as a label
1551 // reference needing a fixup. If it is a constant, it's something else
1552 // and we reject it.
1553 if (isImm()) {
1554 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1555 Inst.addOperand(MCOperand::CreateReg(0));
1556 Inst.addOperand(MCOperand::CreateImm(0));
1557 return;
1558 }
1559
Jim Grosbache53c87b2011-10-11 15:59:20 +00001560 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1561 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001562 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1563 // Special case for #-0
1564 if (Val == INT32_MIN) Val = 0;
1565 if (Val < 0) Val = -Val;
1566 Val = ARM_AM::getAM3Opc(AddSub, Val);
1567 } else {
1568 // For register offset, we encode the shift type and negation flag
1569 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001570 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001571 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001572 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1573 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001574 Inst.addOperand(MCOperand::CreateImm(Val));
1575 }
1576
1577 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001579 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001580 int32_t Val =
1581 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1582 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1583 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001584 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001585 }
1586
1587 // Constant offset.
1588 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1589 int32_t Val = CE->getValue();
1590 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1591 // Special case for #-0
1592 if (Val == INT32_MIN) Val = 0;
1593 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001594 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001595 Inst.addOperand(MCOperand::CreateReg(0));
1596 Inst.addOperand(MCOperand::CreateImm(Val));
1597 }
1598
Jim Grosbach7ce05792011-08-03 23:50:40 +00001599 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1600 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001601 // If we have an immediate that's not a constant, treat it as a label
1602 // reference needing a fixup. If it is a constant, it's something else
1603 // and we reject it.
1604 if (isImm()) {
1605 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1606 Inst.addOperand(MCOperand::CreateImm(0));
1607 return;
1608 }
1609
Jim Grosbach7ce05792011-08-03 23:50:40 +00001610 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001611 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001612 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1613 // Special case for #-0
1614 if (Val == INT32_MIN) Val = 0;
1615 if (Val < 0) Val = -Val;
1616 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001617 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001618 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001619 }
1620
Jim Grosbacha77295d2011-09-08 22:07:06 +00001621 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001623 // If we have an immediate that's not a constant, treat it as a label
1624 // reference needing a fixup. If it is a constant, it's something else
1625 // and we reject it.
1626 if (isImm()) {
1627 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1628 Inst.addOperand(MCOperand::CreateImm(0));
1629 return;
1630 }
1631
Jim Grosbache53c87b2011-10-11 15:59:20 +00001632 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1633 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001634 Inst.addOperand(MCOperand::CreateImm(Val));
1635 }
1636
Jim Grosbachb6aed502011-09-09 18:37:27 +00001637 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1638 assert(N == 2 && "Invalid number of operands!");
1639 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001640 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1641 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001642 Inst.addOperand(MCOperand::CreateImm(Val));
1643 }
1644
Jim Grosbach7ce05792011-08-03 23:50:40 +00001645 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1646 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001647 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1648 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001649 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001650 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001651
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001652 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1653 addMemImm8OffsetOperands(Inst, N);
1654 }
1655
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001656 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001657 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001658 }
1659
1660 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1661 assert(N == 2 && "Invalid number of operands!");
1662 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001663 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001664 addExpr(Inst, getImm());
1665 Inst.addOperand(MCOperand::CreateImm(0));
1666 return;
1667 }
1668
1669 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001670 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1671 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001672 Inst.addOperand(MCOperand::CreateImm(Val));
1673 }
1674
Jim Grosbach7ce05792011-08-03 23:50:40 +00001675 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1676 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001677 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001678 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001679 addExpr(Inst, getImm());
1680 Inst.addOperand(MCOperand::CreateImm(0));
1681 return;
1682 }
1683
1684 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001685 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1686 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001687 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001688 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001689
Jim Grosbach7f739be2011-09-19 22:21:13 +00001690 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1691 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001692 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1693 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001694 }
1695
1696 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1697 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001698 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1699 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001700 }
1701
Jim Grosbach7ce05792011-08-03 23:50:40 +00001702 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1703 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001704 unsigned Val =
1705 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1706 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001707 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1708 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001709 Inst.addOperand(MCOperand::CreateImm(Val));
1710 }
1711
Jim Grosbachab899c12011-09-07 23:10:15 +00001712 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1713 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001714 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1715 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1716 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001717 }
1718
Jim Grosbach7ce05792011-08-03 23:50:40 +00001719 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1720 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001721 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1722 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001723 }
1724
Jim Grosbach60f91a32011-08-19 17:55:24 +00001725 void addMemThumbRIs4Operands(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() / 4) : 0;
1728 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001729 Inst.addOperand(MCOperand::CreateImm(Val));
1730 }
1731
Jim Grosbach38466302011-08-19 18:55:51 +00001732 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1733 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001734 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1735 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001736 Inst.addOperand(MCOperand::CreateImm(Val));
1737 }
1738
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001739 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1740 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001741 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1742 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001743 Inst.addOperand(MCOperand::CreateImm(Val));
1744 }
1745
Jim Grosbachecd85892011-08-19 18:13:48 +00001746 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1747 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001748 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1749 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001750 Inst.addOperand(MCOperand::CreateImm(Val));
1751 }
1752
Jim Grosbach7ce05792011-08-03 23:50:40 +00001753 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1754 assert(N == 1 && "Invalid number of operands!");
1755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1756 assert(CE && "non-constant post-idx-imm8 operand!");
1757 int Imm = CE->getValue();
1758 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001759 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001760 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1761 Inst.addOperand(MCOperand::CreateImm(Imm));
1762 }
1763
Jim Grosbach2bd01182011-10-11 21:55:36 +00001764 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1765 assert(N == 1 && "Invalid number of operands!");
1766 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1767 assert(CE && "non-constant post-idx-imm8s4 operand!");
1768 int Imm = CE->getValue();
1769 bool isAdd = Imm >= 0;
1770 if (Imm == INT32_MIN) Imm = 0;
1771 // Immediate is scaled by 4.
1772 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1773 Inst.addOperand(MCOperand::CreateImm(Imm));
1774 }
1775
Jim Grosbach7ce05792011-08-03 23:50:40 +00001776 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
1778 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001779 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1780 }
1781
1782 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1783 assert(N == 2 && "Invalid number of operands!");
1784 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1785 // The sign, shift type, and shift amount are encoded in a single operand
1786 // using the AM2 encoding helpers.
1787 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1788 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1789 PostIdxReg.ShiftTy);
1790 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001791 }
1792
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001793 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1794 assert(N == 1 && "Invalid number of operands!");
1795 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1796 }
1797
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001798 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1799 assert(N == 1 && "Invalid number of operands!");
1800 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1801 }
1802
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001803 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001804 assert(N == 1 && "Invalid number of operands!");
1805 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1806 }
1807
Jim Grosbach7636bf62011-12-02 00:35:16 +00001808 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1809 assert(N == 2 && "Invalid number of operands!");
1810 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1811 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1812 }
1813
Jim Grosbach460a9052011-10-07 23:56:00 +00001814 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1815 assert(N == 1 && "Invalid number of operands!");
1816 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1817 }
1818
1819 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1820 assert(N == 1 && "Invalid number of operands!");
1821 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1822 }
1823
1824 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1825 assert(N == 1 && "Invalid number of operands!");
1826 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1827 }
1828
Jim Grosbach0e387b22011-10-17 22:26:03 +00001829 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1830 assert(N == 1 && "Invalid number of operands!");
1831 // The immediate encodes the type of constant as well as the value.
1832 // Mask in that this is an i8 splat.
1833 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1834 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1835 }
1836
Jim Grosbachea461102011-10-17 23:09:09 +00001837 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1838 assert(N == 1 && "Invalid number of operands!");
1839 // The immediate encodes the type of constant as well as the value.
1840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1841 unsigned Value = CE->getValue();
1842 if (Value >= 256)
1843 Value = (Value >> 8) | 0xa00;
1844 else
1845 Value |= 0x800;
1846 Inst.addOperand(MCOperand::CreateImm(Value));
1847 }
1848
Jim Grosbach6248a542011-10-18 00:22:00 +00001849 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1850 assert(N == 1 && "Invalid number of operands!");
1851 // The immediate encodes the type of constant as well as the value.
1852 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1853 unsigned Value = CE->getValue();
1854 if (Value >= 256 && Value <= 0xff00)
1855 Value = (Value >> 8) | 0x200;
1856 else if (Value > 0xffff && Value <= 0xff0000)
1857 Value = (Value >> 16) | 0x400;
1858 else if (Value > 0xffffff)
1859 Value = (Value >> 24) | 0x600;
1860 Inst.addOperand(MCOperand::CreateImm(Value));
1861 }
1862
1863 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1864 assert(N == 1 && "Invalid number of operands!");
1865 // The immediate encodes the type of constant as well as the value.
1866 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1867 unsigned Value = CE->getValue();
1868 if (Value >= 256 && Value <= 0xffff)
1869 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1870 else if (Value > 0xffff && Value <= 0xffffff)
1871 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1872 else if (Value > 0xffffff)
1873 Value = (Value >> 24) | 0x600;
1874 Inst.addOperand(MCOperand::CreateImm(Value));
1875 }
1876
Jim Grosbach9b087852011-12-19 23:51:07 +00001877 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1878 assert(N == 1 && "Invalid number of operands!");
1879 // The immediate encodes the type of constant as well as the value.
1880 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1881 unsigned Value = ~CE->getValue();
1882 if (Value >= 256 && Value <= 0xffff)
1883 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1884 else if (Value > 0xffff && Value <= 0xffffff)
1885 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1886 else if (Value > 0xffffff)
1887 Value = (Value >> 24) | 0x600;
1888 Inst.addOperand(MCOperand::CreateImm(Value));
1889 }
1890
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001891 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1892 assert(N == 1 && "Invalid number of operands!");
1893 // The immediate encodes the type of constant as well as the value.
1894 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1895 uint64_t Value = CE->getValue();
1896 unsigned Imm = 0;
1897 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1898 Imm |= (Value & 1) << i;
1899 }
1900 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1901 }
1902
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001903 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001904
Jim Grosbach89df9962011-08-26 21:43:41 +00001905 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001906 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001907 Op->ITMask.Mask = Mask;
1908 Op->StartLoc = S;
1909 Op->EndLoc = S;
1910 return Op;
1911 }
1912
Chris Lattner3a697562010-10-28 17:20:03 +00001913 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001914 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001915 Op->CC.Val = CC;
1916 Op->StartLoc = S;
1917 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001918 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001919 }
1920
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001921 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001922 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001923 Op->Cop.Val = CopVal;
1924 Op->StartLoc = S;
1925 Op->EndLoc = S;
1926 return Op;
1927 }
1928
1929 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001930 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001931 Op->Cop.Val = CopVal;
1932 Op->StartLoc = S;
1933 Op->EndLoc = S;
1934 return Op;
1935 }
1936
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001937 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1938 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1939 Op->Cop.Val = Val;
1940 Op->StartLoc = S;
1941 Op->EndLoc = E;
1942 return Op;
1943 }
1944
Jim Grosbachd67641b2010-12-06 18:21:12 +00001945 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001946 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001947 Op->Reg.RegNum = RegNum;
1948 Op->StartLoc = S;
1949 Op->EndLoc = S;
1950 return Op;
1951 }
1952
Chris Lattner3a697562010-10-28 17:20:03 +00001953 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001954 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001955 Op->Tok.Data = Str.data();
1956 Op->Tok.Length = Str.size();
1957 Op->StartLoc = S;
1958 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001959 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001960 }
1961
Bill Wendling50d0f582010-11-18 23:43:05 +00001962 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001963 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001964 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001965 Op->StartLoc = S;
1966 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001967 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001968 }
1969
Jim Grosbache8606dc2011-07-13 17:50:29 +00001970 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1971 unsigned SrcReg,
1972 unsigned ShiftReg,
1973 unsigned ShiftImm,
1974 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001975 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001976 Op->RegShiftedReg.ShiftTy = ShTy;
1977 Op->RegShiftedReg.SrcReg = SrcReg;
1978 Op->RegShiftedReg.ShiftReg = ShiftReg;
1979 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001980 Op->StartLoc = S;
1981 Op->EndLoc = E;
1982 return Op;
1983 }
1984
Owen Anderson92a20222011-07-21 18:54:16 +00001985 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1986 unsigned SrcReg,
1987 unsigned ShiftImm,
1988 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001989 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001990 Op->RegShiftedImm.ShiftTy = ShTy;
1991 Op->RegShiftedImm.SrcReg = SrcReg;
1992 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001993 Op->StartLoc = S;
1994 Op->EndLoc = E;
1995 return Op;
1996 }
1997
Jim Grosbach580f4a92011-07-25 22:20:28 +00001998 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001999 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002000 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002001 Op->ShifterImm.isASR = isASR;
2002 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002003 Op->StartLoc = S;
2004 Op->EndLoc = E;
2005 return Op;
2006 }
2007
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002008 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002009 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002010 Op->RotImm.Imm = Imm;
2011 Op->StartLoc = S;
2012 Op->EndLoc = E;
2013 return Op;
2014 }
2015
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002016 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2017 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002018 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002019 Op->Bitfield.LSB = LSB;
2020 Op->Bitfield.Width = Width;
2021 Op->StartLoc = S;
2022 Op->EndLoc = E;
2023 return Op;
2024 }
2025
Bill Wendling7729e062010-11-09 22:44:22 +00002026 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002027 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002028 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002029 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002030
Jim Grosbachd300b942011-09-13 22:56:44 +00002031 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002032 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002033 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002034 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002035 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002036
2037 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002038 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002039 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002040 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002041 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002042 Op->StartLoc = StartLoc;
2043 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002044 return Op;
2045 }
2046
Jim Grosbach862019c2011-10-18 23:02:30 +00002047 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002048 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002049 ARMOperand *Op = new ARMOperand(k_VectorList);
2050 Op->VectorList.RegNum = RegNum;
2051 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002052 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002053 Op->StartLoc = S;
2054 Op->EndLoc = E;
2055 return Op;
2056 }
2057
Jim Grosbach98b05a52011-11-30 01:09:44 +00002058 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002059 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002060 SMLoc S, SMLoc E) {
2061 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2062 Op->VectorList.RegNum = RegNum;
2063 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002064 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002065 Op->StartLoc = S;
2066 Op->EndLoc = E;
2067 return Op;
2068 }
2069
Jim Grosbach7636bf62011-12-02 00:35:16 +00002070 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002071 unsigned Index,
2072 bool isDoubleSpaced,
2073 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002074 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2075 Op->VectorList.RegNum = RegNum;
2076 Op->VectorList.Count = Count;
2077 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002078 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002079 Op->StartLoc = S;
2080 Op->EndLoc = E;
2081 return Op;
2082 }
2083
Jim Grosbach460a9052011-10-07 23:56:00 +00002084 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2085 MCContext &Ctx) {
2086 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2087 Op->VectorIndex.Val = Idx;
2088 Op->StartLoc = S;
2089 Op->EndLoc = E;
2090 return Op;
2091 }
2092
Chris Lattner3a697562010-10-28 17:20:03 +00002093 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002094 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002095 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002096 Op->StartLoc = S;
2097 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002098 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002099 }
2100
Jim Grosbach9d390362011-10-03 23:38:36 +00002101 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002102 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002103 Op->FPImm.Val = Val;
2104 Op->StartLoc = S;
2105 Op->EndLoc = S;
2106 return Op;
2107 }
2108
Jim Grosbach7ce05792011-08-03 23:50:40 +00002109 static ARMOperand *CreateMem(unsigned BaseRegNum,
2110 const MCConstantExpr *OffsetImm,
2111 unsigned OffsetRegNum,
2112 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002113 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002114 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002115 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002116 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002117 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002118 Op->Memory.BaseRegNum = BaseRegNum;
2119 Op->Memory.OffsetImm = OffsetImm;
2120 Op->Memory.OffsetRegNum = OffsetRegNum;
2121 Op->Memory.ShiftType = ShiftType;
2122 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002123 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002124 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002125 Op->StartLoc = S;
2126 Op->EndLoc = E;
2127 return Op;
2128 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002129
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002130 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2131 ARM_AM::ShiftOpc ShiftTy,
2132 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002133 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002134 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002135 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002136 Op->PostIdxReg.isAdd = isAdd;
2137 Op->PostIdxReg.ShiftTy = ShiftTy;
2138 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002139 Op->StartLoc = S;
2140 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002141 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002142 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002143
2144 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002145 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002146 Op->MBOpt.Val = Opt;
2147 Op->StartLoc = S;
2148 Op->EndLoc = S;
2149 return Op;
2150 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002151
2152 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002153 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002154 Op->IFlags.Val = IFlags;
2155 Op->StartLoc = S;
2156 Op->EndLoc = S;
2157 return Op;
2158 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002159
2160 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002161 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002162 Op->MMask.Val = MMask;
2163 Op->StartLoc = S;
2164 Op->EndLoc = S;
2165 return Op;
2166 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002167};
2168
2169} // end anonymous namespace.
2170
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002171void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002172 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002173 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002174 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2175 << ") >";
2176 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002177 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002178 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002179 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002180 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002181 OS << "<ccout " << getReg() << ">";
2182 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002183 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002184 static const char *MaskStr[] = {
2185 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2186 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2187 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002188 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2189 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2190 break;
2191 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002192 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002193 OS << "<coprocessor number: " << getCoproc() << ">";
2194 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002195 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002196 OS << "<coprocessor register: " << getCoproc() << ">";
2197 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002198 case k_CoprocOption:
2199 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2200 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002201 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002202 OS << "<mask: " << getMSRMask() << ">";
2203 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002204 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002205 getImm()->print(OS);
2206 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002207 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002208 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2209 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002210 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002211 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002212 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002213 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002214 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002215 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002216 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2217 << PostIdxReg.RegNum;
2218 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2219 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2220 << PostIdxReg.ShiftImm;
2221 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002222 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002223 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002224 OS << "<ARM_PROC::";
2225 unsigned IFlags = getProcIFlags();
2226 for (int i=2; i >= 0; --i)
2227 if (IFlags & (1 << i))
2228 OS << ARM_PROC::IFlagsToString(1 << i);
2229 OS << ">";
2230 break;
2231 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002232 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002233 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002234 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002235 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002236 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2237 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002238 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002239 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002240 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002241 << RegShiftedReg.SrcReg << " "
2242 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2243 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002244 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002245 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002246 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002247 << RegShiftedImm.SrcReg << " "
2248 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2249 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002250 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002251 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002252 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2253 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002254 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002255 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2256 << ", width: " << Bitfield.Width << ">";
2257 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002258 case k_RegisterList:
2259 case k_DPRRegisterList:
2260 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002261 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002262
Bill Wendling5fa22a12010-11-09 23:28:44 +00002263 const SmallVectorImpl<unsigned> &RegList = getRegList();
2264 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002265 I = RegList.begin(), E = RegList.end(); I != E; ) {
2266 OS << *I;
2267 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002268 }
2269
2270 OS << ">";
2271 break;
2272 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002273 case k_VectorList:
2274 OS << "<vector_list " << VectorList.Count << " * "
2275 << VectorList.RegNum << ">";
2276 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002277 case k_VectorListAllLanes:
2278 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2279 << VectorList.RegNum << ">";
2280 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002281 case k_VectorListIndexed:
2282 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2283 << VectorList.Count << " * " << VectorList.RegNum << ">";
2284 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002285 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002286 OS << "'" << getToken() << "'";
2287 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002288 case k_VectorIndex:
2289 OS << "<vectorindex " << getVectorIndex() << ">";
2290 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002291 }
2292}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002293
2294/// @name Auto-generated Match Functions
2295/// {
2296
2297static unsigned MatchRegisterName(StringRef Name);
2298
2299/// }
2300
Bob Wilson69df7232011-02-03 21:46:10 +00002301bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2302 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002303 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002304 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002305 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002306
2307 return (RegNo == (unsigned)-1);
2308}
2309
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002310/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002311/// and if it is a register name the token is eaten and the register number is
2312/// returned. Otherwise return -1.
2313///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002314int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002315 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002316 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002317
Benjamin Kramer59085362011-11-06 20:37:06 +00002318 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002319 unsigned RegNum = MatchRegisterName(lowerCase);
2320 if (!RegNum) {
2321 RegNum = StringSwitch<unsigned>(lowerCase)
2322 .Case("r13", ARM::SP)
2323 .Case("r14", ARM::LR)
2324 .Case("r15", ARM::PC)
2325 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002326 // Additional register name aliases for 'gas' compatibility.
2327 .Case("a1", ARM::R0)
2328 .Case("a2", ARM::R1)
2329 .Case("a3", ARM::R2)
2330 .Case("a4", ARM::R3)
2331 .Case("v1", ARM::R4)
2332 .Case("v2", ARM::R5)
2333 .Case("v3", ARM::R6)
2334 .Case("v4", ARM::R7)
2335 .Case("v5", ARM::R8)
2336 .Case("v6", ARM::R9)
2337 .Case("v7", ARM::R10)
2338 .Case("v8", ARM::R11)
2339 .Case("sb", ARM::R9)
2340 .Case("sl", ARM::R10)
2341 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002342 .Default(0);
2343 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002344 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002345 // Check for aliases registered via .req. Canonicalize to lower case.
2346 // That's more consistent since register names are case insensitive, and
2347 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2348 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002349 // If no match, return failure.
2350 if (Entry == RegisterReqs.end())
2351 return -1;
2352 Parser.Lex(); // Eat identifier token.
2353 return Entry->getValue();
2354 }
Bob Wilson69df7232011-02-03 21:46:10 +00002355
Chris Lattnere5658fa2010-10-30 04:09:10 +00002356 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002357
Chris Lattnere5658fa2010-10-30 04:09:10 +00002358 return RegNum;
2359}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002360
Jim Grosbach19906722011-07-13 18:49:30 +00002361// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2362// If a recoverable error occurs, return 1. If an irrecoverable error
2363// occurs, return -1. An irrecoverable error is one where tokens have been
2364// consumed in the process of trying to parse the shifter (i.e., when it is
2365// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002366int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002367 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2368 SMLoc S = Parser.getTok().getLoc();
2369 const AsmToken &Tok = Parser.getTok();
2370 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2371
Benjamin Kramer59085362011-11-06 20:37:06 +00002372 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002373 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002374 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002375 .Case("lsl", ARM_AM::lsl)
2376 .Case("lsr", ARM_AM::lsr)
2377 .Case("asr", ARM_AM::asr)
2378 .Case("ror", ARM_AM::ror)
2379 .Case("rrx", ARM_AM::rrx)
2380 .Default(ARM_AM::no_shift);
2381
2382 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002383 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002384
Jim Grosbache8606dc2011-07-13 17:50:29 +00002385 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002386
Jim Grosbache8606dc2011-07-13 17:50:29 +00002387 // The source register for the shift has already been added to the
2388 // operand list, so we need to pop it off and combine it into the shifted
2389 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002390 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002391 if (!PrevOp->isReg())
2392 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2393 int SrcReg = PrevOp->getReg();
2394 int64_t Imm = 0;
2395 int ShiftReg = 0;
2396 if (ShiftTy == ARM_AM::rrx) {
2397 // RRX Doesn't have an explicit shift amount. The encoder expects
2398 // the shift register to be the same as the source register. Seems odd,
2399 // but OK.
2400 ShiftReg = SrcReg;
2401 } else {
2402 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002403 if (Parser.getTok().is(AsmToken::Hash) ||
2404 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002405 Parser.Lex(); // Eat hash.
2406 SMLoc ImmLoc = Parser.getTok().getLoc();
2407 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002408 if (getParser().ParseExpression(ShiftExpr)) {
2409 Error(ImmLoc, "invalid immediate shift value");
2410 return -1;
2411 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002412 // The expression must be evaluatable as an immediate.
2413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002414 if (!CE) {
2415 Error(ImmLoc, "invalid immediate shift value");
2416 return -1;
2417 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002418 // Range check the immediate.
2419 // lsl, ror: 0 <= imm <= 31
2420 // lsr, asr: 0 <= imm <= 32
2421 Imm = CE->getValue();
2422 if (Imm < 0 ||
2423 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2424 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002425 Error(ImmLoc, "immediate shift value out of range");
2426 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002427 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002428 // shift by zero is a nop. Always send it through as lsl.
2429 // ('as' compatibility)
2430 if (Imm == 0)
2431 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002432 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002433 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002434 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002435 if (ShiftReg == -1) {
2436 Error (L, "expected immediate or register in shift operand");
2437 return -1;
2438 }
2439 } else {
2440 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002441 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002442 return -1;
2443 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002444 }
2445
Owen Anderson92a20222011-07-21 18:54:16 +00002446 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2447 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002448 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002449 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002450 else
2451 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2452 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002453
Jim Grosbach19906722011-07-13 18:49:30 +00002454 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002455}
2456
2457
Bill Wendling50d0f582010-11-18 23:43:05 +00002458/// Try to parse a register name. The token must be an Identifier when called.
2459/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2460/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002461///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002462/// TODO this is likely to change to allow different register types and or to
2463/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002464bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002465tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002466 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002467 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002468 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002469 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002470
Bill Wendling50d0f582010-11-18 23:43:05 +00002471 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002472
Chris Lattnere5658fa2010-10-30 04:09:10 +00002473 const AsmToken &ExclaimTok = Parser.getTok();
2474 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002475 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2476 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002477 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002478 return false;
2479 }
2480
2481 // Also check for an index operand. This is only legal for vector registers,
2482 // but that'll get caught OK in operand matching, so we don't need to
2483 // explicitly filter everything else out here.
2484 if (Parser.getTok().is(AsmToken::LBrac)) {
2485 SMLoc SIdx = Parser.getTok().getLoc();
2486 Parser.Lex(); // Eat left bracket token.
2487
2488 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002489 if (getParser().ParseExpression(ImmVal))
2490 return MatchOperand_ParseFail;
2491 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2492 if (!MCE) {
2493 TokError("immediate value expected for vector index");
2494 return MatchOperand_ParseFail;
2495 }
2496
2497 SMLoc E = Parser.getTok().getLoc();
2498 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2499 Error(E, "']' expected");
2500 return MatchOperand_ParseFail;
2501 }
2502
2503 Parser.Lex(); // Eat right bracket token.
2504
2505 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2506 SIdx, E,
2507 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002508 }
2509
Bill Wendling50d0f582010-11-18 23:43:05 +00002510 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002511}
2512
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002513/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2514/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2515/// "c5", ...
2516static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002517 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2518 // but efficient.
2519 switch (Name.size()) {
2520 default: break;
2521 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002522 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002523 return -1;
2524 switch (Name[1]) {
2525 default: return -1;
2526 case '0': return 0;
2527 case '1': return 1;
2528 case '2': return 2;
2529 case '3': return 3;
2530 case '4': return 4;
2531 case '5': return 5;
2532 case '6': return 6;
2533 case '7': return 7;
2534 case '8': return 8;
2535 case '9': return 9;
2536 }
2537 break;
2538 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002539 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002540 return -1;
2541 switch (Name[2]) {
2542 default: return -1;
2543 case '0': return 10;
2544 case '1': return 11;
2545 case '2': return 12;
2546 case '3': return 13;
2547 case '4': return 14;
2548 case '5': return 15;
2549 }
2550 break;
2551 }
2552
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002553 return -1;
2554}
2555
Jim Grosbach89df9962011-08-26 21:43:41 +00002556/// parseITCondCode - Try to parse a condition code for an IT instruction.
2557ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2558parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2559 SMLoc S = Parser.getTok().getLoc();
2560 const AsmToken &Tok = Parser.getTok();
2561 if (!Tok.is(AsmToken::Identifier))
2562 return MatchOperand_NoMatch;
2563 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2564 .Case("eq", ARMCC::EQ)
2565 .Case("ne", ARMCC::NE)
2566 .Case("hs", ARMCC::HS)
2567 .Case("cs", ARMCC::HS)
2568 .Case("lo", ARMCC::LO)
2569 .Case("cc", ARMCC::LO)
2570 .Case("mi", ARMCC::MI)
2571 .Case("pl", ARMCC::PL)
2572 .Case("vs", ARMCC::VS)
2573 .Case("vc", ARMCC::VC)
2574 .Case("hi", ARMCC::HI)
2575 .Case("ls", ARMCC::LS)
2576 .Case("ge", ARMCC::GE)
2577 .Case("lt", ARMCC::LT)
2578 .Case("gt", ARMCC::GT)
2579 .Case("le", ARMCC::LE)
2580 .Case("al", ARMCC::AL)
2581 .Default(~0U);
2582 if (CC == ~0U)
2583 return MatchOperand_NoMatch;
2584 Parser.Lex(); // Eat the token.
2585
2586 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2587
2588 return MatchOperand_Success;
2589}
2590
Jim Grosbach43904292011-07-25 20:14:50 +00002591/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002592/// token must be an Identifier when called, and if it is a coprocessor
2593/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002594ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002595parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002596 SMLoc S = Parser.getTok().getLoc();
2597 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002598 if (Tok.isNot(AsmToken::Identifier))
2599 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002600
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002601 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002602 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002603 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002604
2605 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002606 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002607 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002608}
2609
Jim Grosbach43904292011-07-25 20:14:50 +00002610/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002611/// token must be an Identifier when called, and if it is a coprocessor
2612/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002613ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002614parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002615 SMLoc S = Parser.getTok().getLoc();
2616 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002617 if (Tok.isNot(AsmToken::Identifier))
2618 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002619
2620 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2621 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002622 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002623
2624 Parser.Lex(); // Eat identifier token.
2625 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002626 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002627}
2628
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002629/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2630/// coproc_option : '{' imm0_255 '}'
2631ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2632parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2633 SMLoc S = Parser.getTok().getLoc();
2634
2635 // If this isn't a '{', this isn't a coprocessor immediate operand.
2636 if (Parser.getTok().isNot(AsmToken::LCurly))
2637 return MatchOperand_NoMatch;
2638 Parser.Lex(); // Eat the '{'
2639
2640 const MCExpr *Expr;
2641 SMLoc Loc = Parser.getTok().getLoc();
2642 if (getParser().ParseExpression(Expr)) {
2643 Error(Loc, "illegal expression");
2644 return MatchOperand_ParseFail;
2645 }
2646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2647 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2648 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2649 return MatchOperand_ParseFail;
2650 }
2651 int Val = CE->getValue();
2652
2653 // Check for and consume the closing '}'
2654 if (Parser.getTok().isNot(AsmToken::RCurly))
2655 return MatchOperand_ParseFail;
2656 SMLoc E = Parser.getTok().getLoc();
2657 Parser.Lex(); // Eat the '}'
2658
2659 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2660 return MatchOperand_Success;
2661}
2662
Jim Grosbachd0588e22011-09-14 18:08:35 +00002663// For register list parsing, we need to map from raw GPR register numbering
2664// to the enumeration values. The enumeration values aren't sorted by
2665// register number due to our using "sp", "lr" and "pc" as canonical names.
2666static unsigned getNextRegister(unsigned Reg) {
2667 // If this is a GPR, we need to do it manually, otherwise we can rely
2668 // on the sort ordering of the enumeration since the other reg-classes
2669 // are sane.
2670 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2671 return Reg + 1;
2672 switch(Reg) {
2673 default: assert(0 && "Invalid GPR number!");
2674 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2675 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2676 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2677 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2678 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2679 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2680 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2681 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2682 }
2683}
2684
Jim Grosbachce485e72011-11-11 21:27:40 +00002685// Return the low-subreg of a given Q register.
2686static unsigned getDRegFromQReg(unsigned QReg) {
2687 switch (QReg) {
2688 default: llvm_unreachable("expected a Q register!");
2689 case ARM::Q0: return ARM::D0;
2690 case ARM::Q1: return ARM::D2;
2691 case ARM::Q2: return ARM::D4;
2692 case ARM::Q3: return ARM::D6;
2693 case ARM::Q4: return ARM::D8;
2694 case ARM::Q5: return ARM::D10;
2695 case ARM::Q6: return ARM::D12;
2696 case ARM::Q7: return ARM::D14;
2697 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002698 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002699 case ARM::Q10: return ARM::D20;
2700 case ARM::Q11: return ARM::D22;
2701 case ARM::Q12: return ARM::D24;
2702 case ARM::Q13: return ARM::D26;
2703 case ARM::Q14: return ARM::D28;
2704 case ARM::Q15: return ARM::D30;
2705 }
2706}
2707
Jim Grosbachd0588e22011-09-14 18:08:35 +00002708/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002709bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002710parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002711 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002712 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002713 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002714 Parser.Lex(); // Eat '{' token.
2715 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002716
Jim Grosbachd0588e22011-09-14 18:08:35 +00002717 // Check the first register in the list to see what register class
2718 // this is a list of.
2719 int Reg = tryParseRegister();
2720 if (Reg == -1)
2721 return Error(RegLoc, "register expected");
2722
Jim Grosbachce485e72011-11-11 21:27:40 +00002723 // The reglist instructions have at most 16 registers, so reserve
2724 // space for that many.
2725 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2726
2727 // Allow Q regs and just interpret them as the two D sub-registers.
2728 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2729 Reg = getDRegFromQReg(Reg);
2730 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2731 ++Reg;
2732 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002733 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002734 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2735 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2736 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2737 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2738 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2739 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2740 else
2741 return Error(RegLoc, "invalid register in register list");
2742
Jim Grosbachce485e72011-11-11 21:27:40 +00002743 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002744 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002745
Jim Grosbachd0588e22011-09-14 18:08:35 +00002746 // This starts immediately after the first register token in the list,
2747 // so we can see either a comma or a minus (range separator) as a legal
2748 // next token.
2749 while (Parser.getTok().is(AsmToken::Comma) ||
2750 Parser.getTok().is(AsmToken::Minus)) {
2751 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002752 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002753 SMLoc EndLoc = Parser.getTok().getLoc();
2754 int EndReg = tryParseRegister();
2755 if (EndReg == -1)
2756 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002757 // Allow Q regs and just interpret them as the two D sub-registers.
2758 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2759 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002760 // If the register is the same as the start reg, there's nothing
2761 // more to do.
2762 if (Reg == EndReg)
2763 continue;
2764 // The register must be in the same register class as the first.
2765 if (!RC->contains(EndReg))
2766 return Error(EndLoc, "invalid register in register list");
2767 // Ranges must go from low to high.
2768 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2769 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002770
Jim Grosbachd0588e22011-09-14 18:08:35 +00002771 // Add all the registers in the range to the register list.
2772 while (Reg != EndReg) {
2773 Reg = getNextRegister(Reg);
2774 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2775 }
2776 continue;
2777 }
2778 Parser.Lex(); // Eat the comma.
2779 RegLoc = Parser.getTok().getLoc();
2780 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002781 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002782 Reg = tryParseRegister();
2783 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002784 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002785 // Allow Q regs and just interpret them as the two D sub-registers.
2786 bool isQReg = false;
2787 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2788 Reg = getDRegFromQReg(Reg);
2789 isQReg = true;
2790 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002791 // The register must be in the same register class as the first.
2792 if (!RC->contains(Reg))
2793 return Error(RegLoc, "invalid register in register list");
2794 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002795 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002796 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002797 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2798 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2799 ") in register list");
2800 continue;
2801 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002802 // VFP register lists must also be contiguous.
2803 // It's OK to use the enumeration values directly here rather, as the
2804 // VFP register classes have the enum sorted properly.
2805 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2806 Reg != OldReg + 1)
2807 return Error(RegLoc, "non-contiguous register range");
2808 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002809 if (isQReg)
2810 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002811 }
2812
Jim Grosbachd0588e22011-09-14 18:08:35 +00002813 SMLoc E = Parser.getTok().getLoc();
2814 if (Parser.getTok().isNot(AsmToken::RCurly))
2815 return Error(E, "'}' expected");
2816 Parser.Lex(); // Eat '}' token.
2817
Jim Grosbach27debd62011-12-13 21:48:29 +00002818 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002819 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002820
2821 // The ARM system instruction variants for LDM/STM have a '^' token here.
2822 if (Parser.getTok().is(AsmToken::Caret)) {
2823 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2824 Parser.Lex(); // Eat '^' token.
2825 }
2826
Bill Wendling50d0f582010-11-18 23:43:05 +00002827 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002828}
2829
Jim Grosbach98b05a52011-11-30 01:09:44 +00002830// Helper function to parse the lane index for vector lists.
2831ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002832parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2833 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002834 if (Parser.getTok().is(AsmToken::LBrac)) {
2835 Parser.Lex(); // Eat the '['.
2836 if (Parser.getTok().is(AsmToken::RBrac)) {
2837 // "Dn[]" is the 'all lanes' syntax.
2838 LaneKind = AllLanes;
2839 Parser.Lex(); // Eat the ']'.
2840 return MatchOperand_Success;
2841 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002842 const MCExpr *LaneIndex;
2843 SMLoc Loc = Parser.getTok().getLoc();
2844 if (getParser().ParseExpression(LaneIndex)) {
2845 Error(Loc, "illegal expression");
2846 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002847 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2849 if (!CE) {
2850 Error(Loc, "lane index must be empty or an integer");
2851 return MatchOperand_ParseFail;
2852 }
2853 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2854 Error(Parser.getTok().getLoc(), "']' expected");
2855 return MatchOperand_ParseFail;
2856 }
2857 Parser.Lex(); // Eat the ']'.
2858 int64_t Val = CE->getValue();
2859
2860 // FIXME: Make this range check context sensitive for .8, .16, .32.
2861 if (Val < 0 || Val > 7) {
2862 Error(Parser.getTok().getLoc(), "lane index out of range");
2863 return MatchOperand_ParseFail;
2864 }
2865 Index = Val;
2866 LaneKind = IndexedLane;
2867 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002868 }
2869 LaneKind = NoLanes;
2870 return MatchOperand_Success;
2871}
2872
Jim Grosbach862019c2011-10-18 23:02:30 +00002873// parse a vector register list
2874ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2875parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002876 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002877 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002878 SMLoc S = Parser.getTok().getLoc();
2879 // As an extension (to match gas), support a plain D register or Q register
2880 // (without encosing curly braces) as a single or double entry list,
2881 // respectively.
2882 if (Parser.getTok().is(AsmToken::Identifier)) {
2883 int Reg = tryParseRegister();
2884 if (Reg == -1)
2885 return MatchOperand_NoMatch;
2886 SMLoc E = Parser.getTok().getLoc();
2887 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002888 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002889 if (Res != MatchOperand_Success)
2890 return Res;
2891 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002892 case NoLanes:
2893 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002894 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002895 break;
2896 case AllLanes:
2897 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002898 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2899 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002900 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002901 case IndexedLane:
2902 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002903 LaneIndex,
2904 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002905 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002906 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002907 return MatchOperand_Success;
2908 }
2909 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2910 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002911 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002912 if (Res != MatchOperand_Success)
2913 return Res;
2914 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002915 case NoLanes:
2916 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002917 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002918 break;
2919 case AllLanes:
2920 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002921 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2922 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002923 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002924 case IndexedLane:
2925 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002926 LaneIndex,
2927 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002928 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002929 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002930 return MatchOperand_Success;
2931 }
2932 Error(S, "vector register expected");
2933 return MatchOperand_ParseFail;
2934 }
2935
2936 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002937 return MatchOperand_NoMatch;
2938
Jim Grosbach862019c2011-10-18 23:02:30 +00002939 Parser.Lex(); // Eat '{' token.
2940 SMLoc RegLoc = Parser.getTok().getLoc();
2941
2942 int Reg = tryParseRegister();
2943 if (Reg == -1) {
2944 Error(RegLoc, "register expected");
2945 return MatchOperand_ParseFail;
2946 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002947 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002948 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002949 unsigned FirstReg = Reg;
2950 // The list is of D registers, but we also allow Q regs and just interpret
2951 // them as the two D sub-registers.
2952 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2953 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002954 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2955 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002956 ++Reg;
2957 ++Count;
2958 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002959 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002960 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002961
Jim Grosbache43862b2011-11-15 23:19:15 +00002962 while (Parser.getTok().is(AsmToken::Comma) ||
2963 Parser.getTok().is(AsmToken::Minus)) {
2964 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002965 if (!Spacing)
2966 Spacing = 1; // Register range implies a single spaced list.
2967 else if (Spacing == 2) {
2968 Error(Parser.getTok().getLoc(),
2969 "sequential registers in double spaced list");
2970 return MatchOperand_ParseFail;
2971 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002972 Parser.Lex(); // Eat the minus.
2973 SMLoc EndLoc = Parser.getTok().getLoc();
2974 int EndReg = tryParseRegister();
2975 if (EndReg == -1) {
2976 Error(EndLoc, "register expected");
2977 return MatchOperand_ParseFail;
2978 }
2979 // Allow Q regs and just interpret them as the two D sub-registers.
2980 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2981 EndReg = getDRegFromQReg(EndReg) + 1;
2982 // If the register is the same as the start reg, there's nothing
2983 // more to do.
2984 if (Reg == EndReg)
2985 continue;
2986 // The register must be in the same register class as the first.
2987 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2988 Error(EndLoc, "invalid register in register list");
2989 return MatchOperand_ParseFail;
2990 }
2991 // Ranges must go from low to high.
2992 if (Reg > EndReg) {
2993 Error(EndLoc, "bad range in register list");
2994 return MatchOperand_ParseFail;
2995 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002996 // Parse the lane specifier if present.
2997 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002998 unsigned NextLaneIndex;
2999 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003000 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003001 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003002 Error(EndLoc, "mismatched lane index in register list");
3003 return MatchOperand_ParseFail;
3004 }
3005 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003006
3007 // Add all the registers in the range to the register list.
3008 Count += EndReg - Reg;
3009 Reg = EndReg;
3010 continue;
3011 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003012 Parser.Lex(); // Eat the comma.
3013 RegLoc = Parser.getTok().getLoc();
3014 int OldReg = Reg;
3015 Reg = tryParseRegister();
3016 if (Reg == -1) {
3017 Error(RegLoc, "register expected");
3018 return MatchOperand_ParseFail;
3019 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003020 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003021 // It's OK to use the enumeration values directly here rather, as the
3022 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003023 //
3024 // The list is of D registers, but we also allow Q regs and just interpret
3025 // them as the two D sub-registers.
3026 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003027 if (!Spacing)
3028 Spacing = 1; // Register range implies a single spaced list.
3029 else if (Spacing == 2) {
3030 Error(RegLoc,
3031 "invalid register in double-spaced list (must be 'D' register')");
3032 return MatchOperand_ParseFail;
3033 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003034 Reg = getDRegFromQReg(Reg);
3035 if (Reg != OldReg + 1) {
3036 Error(RegLoc, "non-contiguous register range");
3037 return MatchOperand_ParseFail;
3038 }
3039 ++Reg;
3040 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003041 // Parse the lane specifier if present.
3042 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003043 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003044 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003045 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003046 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003047 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003048 Error(EndLoc, "mismatched lane index in register list");
3049 return MatchOperand_ParseFail;
3050 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003051 continue;
3052 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003053 // Normal D register.
3054 // Figure out the register spacing (single or double) of the list if
3055 // we don't know it already.
3056 if (!Spacing)
3057 Spacing = 1 + (Reg == OldReg + 2);
3058
3059 // Just check that it's contiguous and keep going.
3060 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003061 Error(RegLoc, "non-contiguous register range");
3062 return MatchOperand_ParseFail;
3063 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003064 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003065 // Parse the lane specifier if present.
3066 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003067 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003068 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003069 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003070 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003071 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003072 Error(EndLoc, "mismatched lane index in register list");
3073 return MatchOperand_ParseFail;
3074 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003075 }
3076
3077 SMLoc E = Parser.getTok().getLoc();
3078 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3079 Error(E, "'}' expected");
3080 return MatchOperand_ParseFail;
3081 }
3082 Parser.Lex(); // Eat '}' token.
3083
Jim Grosbach98b05a52011-11-30 01:09:44 +00003084 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003085 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003086 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3087 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003088 break;
3089 case AllLanes:
3090 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003091 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003092 S, E));
3093 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003094 case IndexedLane:
3095 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003096 LaneIndex,
3097 (Spacing == 2),
3098 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003099 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003100 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003101 return MatchOperand_Success;
3102}
3103
Jim Grosbach43904292011-07-25 20:14:50 +00003104/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003105ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003106parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003107 SMLoc S = Parser.getTok().getLoc();
3108 const AsmToken &Tok = Parser.getTok();
3109 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3110 StringRef OptStr = Tok.getString();
3111
3112 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3113 .Case("sy", ARM_MB::SY)
3114 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003115 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003116 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003117 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003118 .Case("ishst", ARM_MB::ISHST)
3119 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003120 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003121 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003122 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003123 .Case("osh", ARM_MB::OSH)
3124 .Case("oshst", ARM_MB::OSHST)
3125 .Default(~0U);
3126
3127 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003128 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003129
3130 Parser.Lex(); // Eat identifier token.
3131 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003132 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003133}
3134
Jim Grosbach43904292011-07-25 20:14:50 +00003135/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003136ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003137parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003138 SMLoc S = Parser.getTok().getLoc();
3139 const AsmToken &Tok = Parser.getTok();
3140 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3141 StringRef IFlagsStr = Tok.getString();
3142
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003143 // An iflags string of "none" is interpreted to mean that none of the AIF
3144 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003145 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003146 if (IFlagsStr != "none") {
3147 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3148 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3149 .Case("a", ARM_PROC::A)
3150 .Case("i", ARM_PROC::I)
3151 .Case("f", ARM_PROC::F)
3152 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003153
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003154 // If some specific iflag is already set, it means that some letter is
3155 // present more than once, this is not acceptable.
3156 if (Flag == ~0U || (IFlags & Flag))
3157 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003158
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003159 IFlags |= Flag;
3160 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003161 }
3162
3163 Parser.Lex(); // Eat identifier token.
3164 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3165 return MatchOperand_Success;
3166}
3167
Jim Grosbach43904292011-07-25 20:14:50 +00003168/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003169ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003170parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003171 SMLoc S = Parser.getTok().getLoc();
3172 const AsmToken &Tok = Parser.getTok();
3173 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3174 StringRef Mask = Tok.getString();
3175
James Molloyacad68d2011-09-28 14:21:38 +00003176 if (isMClass()) {
3177 // See ARMv6-M 10.1.1
3178 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3179 .Case("apsr", 0)
3180 .Case("iapsr", 1)
3181 .Case("eapsr", 2)
3182 .Case("xpsr", 3)
3183 .Case("ipsr", 5)
3184 .Case("epsr", 6)
3185 .Case("iepsr", 7)
3186 .Case("msp", 8)
3187 .Case("psp", 9)
3188 .Case("primask", 16)
3189 .Case("basepri", 17)
3190 .Case("basepri_max", 18)
3191 .Case("faultmask", 19)
3192 .Case("control", 20)
3193 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003194
James Molloyacad68d2011-09-28 14:21:38 +00003195 if (FlagsVal == ~0U)
3196 return MatchOperand_NoMatch;
3197
3198 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3199 // basepri, basepri_max and faultmask only valid for V7m.
3200 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003201
James Molloyacad68d2011-09-28 14:21:38 +00003202 Parser.Lex(); // Eat identifier token.
3203 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3204 return MatchOperand_Success;
3205 }
3206
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003207 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3208 size_t Start = 0, Next = Mask.find('_');
3209 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003210 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003211 if (Next != StringRef::npos)
3212 Flags = Mask.slice(Next+1, Mask.size());
3213
3214 // FlagsVal contains the complete mask:
3215 // 3-0: Mask
3216 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3217 unsigned FlagsVal = 0;
3218
3219 if (SpecReg == "apsr") {
3220 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003221 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003222 .Case("g", 0x4) // same as CPSR_s
3223 .Case("nzcvqg", 0xc) // same as CPSR_fs
3224 .Default(~0U);
3225
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003226 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003227 if (!Flags.empty())
3228 return MatchOperand_NoMatch;
3229 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003230 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003231 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003232 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003233 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3234 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003235 for (int i = 0, e = Flags.size(); i != e; ++i) {
3236 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3237 .Case("c", 1)
3238 .Case("x", 2)
3239 .Case("s", 4)
3240 .Case("f", 8)
3241 .Default(~0U);
3242
3243 // If some specific flag is already set, it means that some letter is
3244 // present more than once, this is not acceptable.
3245 if (FlagsVal == ~0U || (FlagsVal & Flag))
3246 return MatchOperand_NoMatch;
3247 FlagsVal |= Flag;
3248 }
3249 } else // No match for special register.
3250 return MatchOperand_NoMatch;
3251
Owen Anderson7784f1d2011-10-21 18:43:28 +00003252 // Special register without flags is NOT equivalent to "fc" flags.
3253 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3254 // two lines would enable gas compatibility at the expense of breaking
3255 // round-tripping.
3256 //
3257 // if (!FlagsVal)
3258 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003259
3260 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3261 if (SpecReg == "spsr")
3262 FlagsVal |= 16;
3263
3264 Parser.Lex(); // Eat identifier token.
3265 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3266 return MatchOperand_Success;
3267}
3268
Jim Grosbachf6c05252011-07-21 17:23:04 +00003269ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3270parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3271 int Low, int High) {
3272 const AsmToken &Tok = Parser.getTok();
3273 if (Tok.isNot(AsmToken::Identifier)) {
3274 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3275 return MatchOperand_ParseFail;
3276 }
3277 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003278 std::string LowerOp = Op.lower();
3279 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003280 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3281 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3282 return MatchOperand_ParseFail;
3283 }
3284 Parser.Lex(); // Eat shift type token.
3285
3286 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003287 if (Parser.getTok().isNot(AsmToken::Hash) &&
3288 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003289 Error(Parser.getTok().getLoc(), "'#' expected");
3290 return MatchOperand_ParseFail;
3291 }
3292 Parser.Lex(); // Eat hash token.
3293
3294 const MCExpr *ShiftAmount;
3295 SMLoc Loc = Parser.getTok().getLoc();
3296 if (getParser().ParseExpression(ShiftAmount)) {
3297 Error(Loc, "illegal expression");
3298 return MatchOperand_ParseFail;
3299 }
3300 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3301 if (!CE) {
3302 Error(Loc, "constant expression expected");
3303 return MatchOperand_ParseFail;
3304 }
3305 int Val = CE->getValue();
3306 if (Val < Low || Val > High) {
3307 Error(Loc, "immediate value out of range");
3308 return MatchOperand_ParseFail;
3309 }
3310
3311 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3312
3313 return MatchOperand_Success;
3314}
3315
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003316ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3317parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3318 const AsmToken &Tok = Parser.getTok();
3319 SMLoc S = Tok.getLoc();
3320 if (Tok.isNot(AsmToken::Identifier)) {
3321 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3322 return MatchOperand_ParseFail;
3323 }
3324 int Val = StringSwitch<int>(Tok.getString())
3325 .Case("be", 1)
3326 .Case("le", 0)
3327 .Default(-1);
3328 Parser.Lex(); // Eat the token.
3329
3330 if (Val == -1) {
3331 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3332 return MatchOperand_ParseFail;
3333 }
3334 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3335 getContext()),
3336 S, Parser.getTok().getLoc()));
3337 return MatchOperand_Success;
3338}
3339
Jim Grosbach580f4a92011-07-25 22:20:28 +00003340/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3341/// instructions. Legal values are:
3342/// lsl #n 'n' in [0,31]
3343/// asr #n 'n' in [1,32]
3344/// n == 32 encoded as n == 0.
3345ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3346parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3347 const AsmToken &Tok = Parser.getTok();
3348 SMLoc S = Tok.getLoc();
3349 if (Tok.isNot(AsmToken::Identifier)) {
3350 Error(S, "shift operator 'asr' or 'lsl' expected");
3351 return MatchOperand_ParseFail;
3352 }
3353 StringRef ShiftName = Tok.getString();
3354 bool isASR;
3355 if (ShiftName == "lsl" || ShiftName == "LSL")
3356 isASR = false;
3357 else if (ShiftName == "asr" || ShiftName == "ASR")
3358 isASR = true;
3359 else {
3360 Error(S, "shift operator 'asr' or 'lsl' expected");
3361 return MatchOperand_ParseFail;
3362 }
3363 Parser.Lex(); // Eat the operator.
3364
3365 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003366 if (Parser.getTok().isNot(AsmToken::Hash) &&
3367 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003368 Error(Parser.getTok().getLoc(), "'#' expected");
3369 return MatchOperand_ParseFail;
3370 }
3371 Parser.Lex(); // Eat hash token.
3372
3373 const MCExpr *ShiftAmount;
3374 SMLoc E = Parser.getTok().getLoc();
3375 if (getParser().ParseExpression(ShiftAmount)) {
3376 Error(E, "malformed shift expression");
3377 return MatchOperand_ParseFail;
3378 }
3379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3380 if (!CE) {
3381 Error(E, "shift amount must be an immediate");
3382 return MatchOperand_ParseFail;
3383 }
3384
3385 int64_t Val = CE->getValue();
3386 if (isASR) {
3387 // Shift amount must be in [1,32]
3388 if (Val < 1 || Val > 32) {
3389 Error(E, "'asr' shift amount must be in range [1,32]");
3390 return MatchOperand_ParseFail;
3391 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003392 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3393 if (isThumb() && Val == 32) {
3394 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3395 return MatchOperand_ParseFail;
3396 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003397 if (Val == 32) Val = 0;
3398 } else {
3399 // Shift amount must be in [1,32]
3400 if (Val < 0 || Val > 31) {
3401 Error(E, "'lsr' shift amount must be in range [0,31]");
3402 return MatchOperand_ParseFail;
3403 }
3404 }
3405
3406 E = Parser.getTok().getLoc();
3407 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3408
3409 return MatchOperand_Success;
3410}
3411
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003412/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3413/// of instructions. Legal values are:
3414/// ror #n 'n' in {0, 8, 16, 24}
3415ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3416parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3417 const AsmToken &Tok = Parser.getTok();
3418 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003419 if (Tok.isNot(AsmToken::Identifier))
3420 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003421 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003422 if (ShiftName != "ror" && ShiftName != "ROR")
3423 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003424 Parser.Lex(); // Eat the operator.
3425
3426 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003427 if (Parser.getTok().isNot(AsmToken::Hash) &&
3428 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003429 Error(Parser.getTok().getLoc(), "'#' expected");
3430 return MatchOperand_ParseFail;
3431 }
3432 Parser.Lex(); // Eat hash token.
3433
3434 const MCExpr *ShiftAmount;
3435 SMLoc E = Parser.getTok().getLoc();
3436 if (getParser().ParseExpression(ShiftAmount)) {
3437 Error(E, "malformed rotate expression");
3438 return MatchOperand_ParseFail;
3439 }
3440 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3441 if (!CE) {
3442 Error(E, "rotate amount must be an immediate");
3443 return MatchOperand_ParseFail;
3444 }
3445
3446 int64_t Val = CE->getValue();
3447 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3448 // normally, zero is represented in asm by omitting the rotate operand
3449 // entirely.
3450 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3451 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3452 return MatchOperand_ParseFail;
3453 }
3454
3455 E = Parser.getTok().getLoc();
3456 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3457
3458 return MatchOperand_Success;
3459}
3460
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003461ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3462parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3463 SMLoc S = Parser.getTok().getLoc();
3464 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003465 if (Parser.getTok().isNot(AsmToken::Hash) &&
3466 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003467 Error(Parser.getTok().getLoc(), "'#' expected");
3468 return MatchOperand_ParseFail;
3469 }
3470 Parser.Lex(); // Eat hash token.
3471
3472 const MCExpr *LSBExpr;
3473 SMLoc E = Parser.getTok().getLoc();
3474 if (getParser().ParseExpression(LSBExpr)) {
3475 Error(E, "malformed immediate expression");
3476 return MatchOperand_ParseFail;
3477 }
3478 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3479 if (!CE) {
3480 Error(E, "'lsb' operand must be an immediate");
3481 return MatchOperand_ParseFail;
3482 }
3483
3484 int64_t LSB = CE->getValue();
3485 // The LSB must be in the range [0,31]
3486 if (LSB < 0 || LSB > 31) {
3487 Error(E, "'lsb' operand must be in the range [0,31]");
3488 return MatchOperand_ParseFail;
3489 }
3490 E = Parser.getTok().getLoc();
3491
3492 // Expect another immediate operand.
3493 if (Parser.getTok().isNot(AsmToken::Comma)) {
3494 Error(Parser.getTok().getLoc(), "too few operands");
3495 return MatchOperand_ParseFail;
3496 }
3497 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003498 if (Parser.getTok().isNot(AsmToken::Hash) &&
3499 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003500 Error(Parser.getTok().getLoc(), "'#' expected");
3501 return MatchOperand_ParseFail;
3502 }
3503 Parser.Lex(); // Eat hash token.
3504
3505 const MCExpr *WidthExpr;
3506 if (getParser().ParseExpression(WidthExpr)) {
3507 Error(E, "malformed immediate expression");
3508 return MatchOperand_ParseFail;
3509 }
3510 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3511 if (!CE) {
3512 Error(E, "'width' operand must be an immediate");
3513 return MatchOperand_ParseFail;
3514 }
3515
3516 int64_t Width = CE->getValue();
3517 // The LSB must be in the range [1,32-lsb]
3518 if (Width < 1 || Width > 32 - LSB) {
3519 Error(E, "'width' operand must be in the range [1,32-lsb]");
3520 return MatchOperand_ParseFail;
3521 }
3522 E = Parser.getTok().getLoc();
3523
3524 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3525
3526 return MatchOperand_Success;
3527}
3528
Jim Grosbach7ce05792011-08-03 23:50:40 +00003529ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3530parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3531 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003532 // postidx_reg := '+' register {, shift}
3533 // | '-' register {, shift}
3534 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003535
3536 // This method must return MatchOperand_NoMatch without consuming any tokens
3537 // in the case where there is no match, as other alternatives take other
3538 // parse methods.
3539 AsmToken Tok = Parser.getTok();
3540 SMLoc S = Tok.getLoc();
3541 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003542 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003543 int Reg = -1;
3544 if (Tok.is(AsmToken::Plus)) {
3545 Parser.Lex(); // Eat the '+' token.
3546 haveEaten = true;
3547 } else if (Tok.is(AsmToken::Minus)) {
3548 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003549 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003550 haveEaten = true;
3551 }
3552 if (Parser.getTok().is(AsmToken::Identifier))
3553 Reg = tryParseRegister();
3554 if (Reg == -1) {
3555 if (!haveEaten)
3556 return MatchOperand_NoMatch;
3557 Error(Parser.getTok().getLoc(), "register expected");
3558 return MatchOperand_ParseFail;
3559 }
3560 SMLoc E = Parser.getTok().getLoc();
3561
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003562 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3563 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003564 if (Parser.getTok().is(AsmToken::Comma)) {
3565 Parser.Lex(); // Eat the ','.
3566 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3567 return MatchOperand_ParseFail;
3568 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003569
3570 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3571 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003572
3573 return MatchOperand_Success;
3574}
3575
Jim Grosbach251bf252011-08-10 21:56:18 +00003576ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3577parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3578 // Check for a post-index addressing register operand. Specifically:
3579 // am3offset := '+' register
3580 // | '-' register
3581 // | register
3582 // | # imm
3583 // | # + imm
3584 // | # - imm
3585
3586 // This method must return MatchOperand_NoMatch without consuming any tokens
3587 // in the case where there is no match, as other alternatives take other
3588 // parse methods.
3589 AsmToken Tok = Parser.getTok();
3590 SMLoc S = Tok.getLoc();
3591
3592 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003593 if (Parser.getTok().is(AsmToken::Hash) ||
3594 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003595 Parser.Lex(); // Eat the '#'.
3596 // Explicitly look for a '-', as we need to encode negative zero
3597 // differently.
3598 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3599 const MCExpr *Offset;
3600 if (getParser().ParseExpression(Offset))
3601 return MatchOperand_ParseFail;
3602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3603 if (!CE) {
3604 Error(S, "constant expression expected");
3605 return MatchOperand_ParseFail;
3606 }
3607 SMLoc E = Tok.getLoc();
3608 // Negative zero is encoded as the flag value INT32_MIN.
3609 int32_t Val = CE->getValue();
3610 if (isNegative && Val == 0)
3611 Val = INT32_MIN;
3612
3613 Operands.push_back(
3614 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3615
3616 return MatchOperand_Success;
3617 }
3618
3619
3620 bool haveEaten = false;
3621 bool isAdd = true;
3622 int Reg = -1;
3623 if (Tok.is(AsmToken::Plus)) {
3624 Parser.Lex(); // Eat the '+' token.
3625 haveEaten = true;
3626 } else if (Tok.is(AsmToken::Minus)) {
3627 Parser.Lex(); // Eat the '-' token.
3628 isAdd = false;
3629 haveEaten = true;
3630 }
3631 if (Parser.getTok().is(AsmToken::Identifier))
3632 Reg = tryParseRegister();
3633 if (Reg == -1) {
3634 if (!haveEaten)
3635 return MatchOperand_NoMatch;
3636 Error(Parser.getTok().getLoc(), "register expected");
3637 return MatchOperand_ParseFail;
3638 }
3639 SMLoc E = Parser.getTok().getLoc();
3640
3641 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3642 0, S, E));
3643
3644 return MatchOperand_Success;
3645}
3646
Jim Grosbacha77295d2011-09-08 22:07:06 +00003647/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3648/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3649/// when they refer multiple MIOperands inside a single one.
3650bool ARMAsmParser::
3651cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3652 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3653 // Rt, Rt2
3654 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3655 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3656 // Create a writeback register dummy placeholder.
3657 Inst.addOperand(MCOperand::CreateReg(0));
3658 // addr
3659 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3660 // pred
3661 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3662 return true;
3663}
3664
3665/// cvtT2StrdPre - Convert parsed operands to MCInst.
3666/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3667/// when they refer multiple MIOperands inside a single one.
3668bool ARMAsmParser::
3669cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3670 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3671 // Create a writeback register dummy placeholder.
3672 Inst.addOperand(MCOperand::CreateReg(0));
3673 // Rt, Rt2
3674 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3675 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3676 // addr
3677 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3678 // pred
3679 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3680 return true;
3681}
3682
Jim Grosbacheeec0252011-09-08 00:39:19 +00003683/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3684/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3685/// when they refer multiple MIOperands inside a single one.
3686bool ARMAsmParser::
3687cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3688 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3689 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3690
3691 // Create a writeback register dummy placeholder.
3692 Inst.addOperand(MCOperand::CreateImm(0));
3693
3694 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3695 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3696 return true;
3697}
3698
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003699/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3700/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3701/// when they refer multiple MIOperands inside a single one.
3702bool ARMAsmParser::
3703cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3704 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3705 // Create a writeback register dummy placeholder.
3706 Inst.addOperand(MCOperand::CreateImm(0));
3707 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3708 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3709 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3710 return true;
3711}
3712
Jim Grosbach1355cf12011-07-26 17:10:22 +00003713/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003714/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3715/// when they refer multiple MIOperands inside a single one.
3716bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003717cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003718 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3719 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3720
3721 // Create a writeback register dummy placeholder.
3722 Inst.addOperand(MCOperand::CreateImm(0));
3723
Jim Grosbach7ce05792011-08-03 23:50:40 +00003724 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003725 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3726 return true;
3727}
3728
Owen Anderson9ab0f252011-08-26 20:43:14 +00003729/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3730/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3731/// when they refer multiple MIOperands inside a single one.
3732bool ARMAsmParser::
3733cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3734 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3735 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3736
3737 // Create a writeback register dummy placeholder.
3738 Inst.addOperand(MCOperand::CreateImm(0));
3739
3740 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3741 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3742 return true;
3743}
3744
3745
Jim Grosbach548340c2011-08-11 19:22:40 +00003746/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3747/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3748/// when they refer multiple MIOperands inside a single one.
3749bool ARMAsmParser::
3750cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3751 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3752 // Create a writeback register dummy placeholder.
3753 Inst.addOperand(MCOperand::CreateImm(0));
3754 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3755 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3756 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3757 return true;
3758}
3759
Jim Grosbach1355cf12011-07-26 17:10:22 +00003760/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003761/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3762/// when they refer multiple MIOperands inside a single one.
3763bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003764cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003765 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3766 // Create a writeback register dummy placeholder.
3767 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003768 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3769 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3770 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003771 return true;
3772}
3773
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003774/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3775/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3776/// when they refer multiple MIOperands inside a single one.
3777bool ARMAsmParser::
3778cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3779 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3780 // Create a writeback register dummy placeholder.
3781 Inst.addOperand(MCOperand::CreateImm(0));
3782 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3783 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3784 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3785 return true;
3786}
3787
Jim Grosbach7ce05792011-08-03 23:50:40 +00003788/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3789/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3790/// when they refer multiple MIOperands inside a single one.
3791bool ARMAsmParser::
3792cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3793 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3794 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003795 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003796 // Create a writeback register dummy placeholder.
3797 Inst.addOperand(MCOperand::CreateImm(0));
3798 // addr
3799 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3800 // offset
3801 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3802 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003803 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3804 return true;
3805}
3806
Jim Grosbach7ce05792011-08-03 23:50:40 +00003807/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003808/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3809/// when they refer multiple MIOperands inside a single one.
3810bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003811cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3812 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3813 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003814 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003815 // Create a writeback register dummy placeholder.
3816 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003817 // addr
3818 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3819 // offset
3820 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3821 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003822 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3823 return true;
3824}
3825
Jim Grosbach7ce05792011-08-03 23:50:40 +00003826/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003827/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3828/// when they refer multiple MIOperands inside a single one.
3829bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003830cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3831 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003832 // Create a writeback register dummy placeholder.
3833 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003834 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003835 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003836 // addr
3837 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3838 // offset
3839 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3840 // pred
3841 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3842 return true;
3843}
3844
3845/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3846/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3847/// when they refer multiple MIOperands inside a single one.
3848bool ARMAsmParser::
3849cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3850 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3851 // Create a writeback register dummy placeholder.
3852 Inst.addOperand(MCOperand::CreateImm(0));
3853 // Rt
3854 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3855 // addr
3856 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3857 // offset
3858 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3859 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003860 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3861 return true;
3862}
3863
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003864/// cvtLdrdPre - Convert parsed operands to MCInst.
3865/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3866/// when they refer multiple MIOperands inside a single one.
3867bool ARMAsmParser::
3868cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3869 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3870 // Rt, Rt2
3871 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3872 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3873 // Create a writeback register dummy placeholder.
3874 Inst.addOperand(MCOperand::CreateImm(0));
3875 // addr
3876 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3877 // pred
3878 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3879 return true;
3880}
3881
Jim Grosbach14605d12011-08-11 20:28:23 +00003882/// cvtStrdPre - Convert parsed operands to MCInst.
3883/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3884/// when they refer multiple MIOperands inside a single one.
3885bool ARMAsmParser::
3886cvtStrdPre(MCInst &Inst, unsigned Opcode,
3887 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3888 // Create a writeback register dummy placeholder.
3889 Inst.addOperand(MCOperand::CreateImm(0));
3890 // Rt, Rt2
3891 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3892 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3893 // addr
3894 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3895 // pred
3896 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3897 return true;
3898}
3899
Jim Grosbach623a4542011-08-10 22:42:16 +00003900/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3901/// 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::
3904cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3905 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3906 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3907 // Create a writeback register dummy placeholder.
3908 Inst.addOperand(MCOperand::CreateImm(0));
3909 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3910 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3911 return true;
3912}
3913
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003914/// cvtThumbMultiple- Convert parsed operands to MCInst.
3915/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3916/// when they refer multiple MIOperands inside a single one.
3917bool ARMAsmParser::
3918cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3919 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3920 // The second source operand must be the same register as the destination
3921 // operand.
3922 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003923 (((ARMOperand*)Operands[3])->getReg() !=
3924 ((ARMOperand*)Operands[5])->getReg()) &&
3925 (((ARMOperand*)Operands[3])->getReg() !=
3926 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003927 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003928 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003929 return false;
3930 }
3931 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3932 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003933 // If we have a three-operand form, make sure to set Rn to be the operand
3934 // that isn't the same as Rd.
3935 unsigned RegOp = 4;
3936 if (Operands.size() == 6 &&
3937 ((ARMOperand*)Operands[4])->getReg() ==
3938 ((ARMOperand*)Operands[3])->getReg())
3939 RegOp = 5;
3940 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3941 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003942 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3943
3944 return true;
3945}
Jim Grosbach623a4542011-08-10 22:42:16 +00003946
Jim Grosbach12431322011-10-24 22:16:58 +00003947bool ARMAsmParser::
3948cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3949 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3950 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003951 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003952 // Create a writeback register dummy placeholder.
3953 Inst.addOperand(MCOperand::CreateImm(0));
3954 // Vn
3955 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3956 // pred
3957 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3958 return true;
3959}
3960
3961bool ARMAsmParser::
3962cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3963 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3964 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003965 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003966 // Create a writeback register dummy placeholder.
3967 Inst.addOperand(MCOperand::CreateImm(0));
3968 // Vn
3969 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3970 // Vm
3971 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3972 // pred
3973 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3974 return true;
3975}
3976
Jim Grosbach4334e032011-10-31 21:50:31 +00003977bool ARMAsmParser::
3978cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3979 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3980 // Create a writeback register dummy placeholder.
3981 Inst.addOperand(MCOperand::CreateImm(0));
3982 // Vn
3983 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3984 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003985 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003986 // pred
3987 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3988 return true;
3989}
3990
3991bool ARMAsmParser::
3992cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3993 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3994 // Create a writeback register dummy placeholder.
3995 Inst.addOperand(MCOperand::CreateImm(0));
3996 // Vn
3997 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3998 // Vm
3999 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4000 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004001 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004002 // pred
4003 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4004 return true;
4005}
4006
Bill Wendlinge7176102010-11-06 22:36:58 +00004007/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004008/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004009bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004010parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004011 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004012 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004013 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004014 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004015 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004016
Sean Callanan18b83232010-01-19 21:44:56 +00004017 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004018 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004019 if (BaseRegNum == -1)
4020 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004021
Daniel Dunbar05710932011-01-18 05:34:17 +00004022 // The next token must either be a comma or a closing bracket.
4023 const AsmToken &Tok = Parser.getTok();
4024 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004025 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004026
Jim Grosbach7ce05792011-08-03 23:50:40 +00004027 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004028 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004029 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004030
Jim Grosbach7ce05792011-08-03 23:50:40 +00004031 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004032 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004033
Jim Grosbachfb12f352011-09-19 18:42:21 +00004034 // If there's a pre-indexing writeback marker, '!', just add it as a token
4035 // operand. It's rather odd, but syntactically valid.
4036 if (Parser.getTok().is(AsmToken::Exclaim)) {
4037 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4038 Parser.Lex(); // Eat the '!'.
4039 }
4040
Jim Grosbach7ce05792011-08-03 23:50:40 +00004041 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004042 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004043
Jim Grosbach7ce05792011-08-03 23:50:40 +00004044 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4045 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004046
Jim Grosbach57dcb852011-10-11 17:29:55 +00004047 // If we have a ':', it's an alignment specifier.
4048 if (Parser.getTok().is(AsmToken::Colon)) {
4049 Parser.Lex(); // Eat the ':'.
4050 E = Parser.getTok().getLoc();
4051
4052 const MCExpr *Expr;
4053 if (getParser().ParseExpression(Expr))
4054 return true;
4055
4056 // The expression has to be a constant. Memory references with relocations
4057 // don't come through here, as they use the <label> forms of the relevant
4058 // instructions.
4059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4060 if (!CE)
4061 return Error (E, "constant expression expected");
4062
4063 unsigned Align = 0;
4064 switch (CE->getValue()) {
4065 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004066 return Error(E,
4067 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4068 case 16: Align = 2; break;
4069 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004070 case 64: Align = 8; break;
4071 case 128: Align = 16; break;
4072 case 256: Align = 32; break;
4073 }
4074
4075 // Now we should have the closing ']'
4076 E = Parser.getTok().getLoc();
4077 if (Parser.getTok().isNot(AsmToken::RBrac))
4078 return Error(E, "']' expected");
4079 Parser.Lex(); // Eat right bracket token.
4080
4081 // Don't worry about range checking the value here. That's handled by
4082 // the is*() predicates.
4083 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4084 ARM_AM::no_shift, 0, Align,
4085 false, S, E));
4086
4087 // If there's a pre-indexing writeback marker, '!', just add it as a token
4088 // operand.
4089 if (Parser.getTok().is(AsmToken::Exclaim)) {
4090 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4091 Parser.Lex(); // Eat the '!'.
4092 }
4093
4094 return false;
4095 }
4096
4097 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004098 // offset. Be friendly and also accept a plain integer (without a leading
4099 // hash) for gas compatibility.
4100 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004101 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004102 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004103 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004104 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004105 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004106
Owen Anderson0da10cf2011-08-29 19:36:44 +00004107 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004108 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004109 if (getParser().ParseExpression(Offset))
4110 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004111
4112 // The expression has to be a constant. Memory references with relocations
4113 // don't come through here, as they use the <label> forms of the relevant
4114 // instructions.
4115 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4116 if (!CE)
4117 return Error (E, "constant expression expected");
4118
Owen Anderson0da10cf2011-08-29 19:36:44 +00004119 // If the constant was #-0, represent it as INT32_MIN.
4120 int32_t Val = CE->getValue();
4121 if (isNegative && Val == 0)
4122 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4123
Jim Grosbach7ce05792011-08-03 23:50:40 +00004124 // Now we should have the closing ']'
4125 E = Parser.getTok().getLoc();
4126 if (Parser.getTok().isNot(AsmToken::RBrac))
4127 return Error(E, "']' expected");
4128 Parser.Lex(); // Eat right bracket token.
4129
4130 // Don't worry about range checking the value here. That's handled by
4131 // the is*() predicates.
4132 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004133 ARM_AM::no_shift, 0, 0,
4134 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004135
4136 // If there's a pre-indexing writeback marker, '!', just add it as a token
4137 // operand.
4138 if (Parser.getTok().is(AsmToken::Exclaim)) {
4139 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4140 Parser.Lex(); // Eat the '!'.
4141 }
4142
4143 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004144 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004145
4146 // The register offset is optionally preceded by a '+' or '-'
4147 bool isNegative = false;
4148 if (Parser.getTok().is(AsmToken::Minus)) {
4149 isNegative = true;
4150 Parser.Lex(); // Eat the '-'.
4151 } else if (Parser.getTok().is(AsmToken::Plus)) {
4152 // Nothing to do.
4153 Parser.Lex(); // Eat the '+'.
4154 }
4155
4156 E = Parser.getTok().getLoc();
4157 int OffsetRegNum = tryParseRegister();
4158 if (OffsetRegNum == -1)
4159 return Error(E, "register expected");
4160
4161 // If there's a shift operator, handle it.
4162 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004163 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004164 if (Parser.getTok().is(AsmToken::Comma)) {
4165 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004166 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004167 return true;
4168 }
4169
4170 // Now we should have the closing ']'
4171 E = Parser.getTok().getLoc();
4172 if (Parser.getTok().isNot(AsmToken::RBrac))
4173 return Error(E, "']' expected");
4174 Parser.Lex(); // Eat right bracket token.
4175
4176 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004177 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004178 S, E));
4179
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004180 // If there's a pre-indexing writeback marker, '!', just add it as a token
4181 // operand.
4182 if (Parser.getTok().is(AsmToken::Exclaim)) {
4183 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4184 Parser.Lex(); // Eat the '!'.
4185 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004186
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004187 return false;
4188}
4189
Jim Grosbach7ce05792011-08-03 23:50:40 +00004190/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004191/// ( lsl | lsr | asr | ror ) , # shift_amount
4192/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004193/// return true if it parses a shift otherwise it returns false.
4194bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4195 unsigned &Amount) {
4196 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004197 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004198 if (Tok.isNot(AsmToken::Identifier))
4199 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004200 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004201 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4202 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004203 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004204 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004205 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004206 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004207 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004208 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004209 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004210 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004211 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004212 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004213 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004214 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004215
Jim Grosbach7ce05792011-08-03 23:50:40 +00004216 // rrx stands alone.
4217 Amount = 0;
4218 if (St != ARM_AM::rrx) {
4219 Loc = Parser.getTok().getLoc();
4220 // A '#' and a shift amount.
4221 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004222 if (HashTok.isNot(AsmToken::Hash) &&
4223 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004224 return Error(HashTok.getLoc(), "'#' expected");
4225 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004226
Jim Grosbach7ce05792011-08-03 23:50:40 +00004227 const MCExpr *Expr;
4228 if (getParser().ParseExpression(Expr))
4229 return true;
4230 // Range check the immediate.
4231 // lsl, ror: 0 <= imm <= 31
4232 // lsr, asr: 0 <= imm <= 32
4233 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4234 if (!CE)
4235 return Error(Loc, "shift amount must be an immediate");
4236 int64_t Imm = CE->getValue();
4237 if (Imm < 0 ||
4238 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4239 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4240 return Error(Loc, "immediate shift value out of range");
4241 Amount = Imm;
4242 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004243
4244 return false;
4245}
4246
Jim Grosbach9d390362011-10-03 23:38:36 +00004247/// parseFPImm - A floating point immediate expression operand.
4248ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4249parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4250 SMLoc S = Parser.getTok().getLoc();
4251
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004252 if (Parser.getTok().isNot(AsmToken::Hash) &&
4253 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004254 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004255
4256 // Disambiguate the VMOV forms that can accept an FP immediate.
4257 // vmov.f32 <sreg>, #imm
4258 // vmov.f64 <dreg>, #imm
4259 // vmov.f32 <dreg>, #imm @ vector f32x2
4260 // vmov.f32 <qreg>, #imm @ vector f32x4
4261 //
4262 // There are also the NEON VMOV instructions which expect an
4263 // integer constant. Make sure we don't try to parse an FPImm
4264 // for these:
4265 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4266 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4267 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4268 TyOp->getToken() != ".f64"))
4269 return MatchOperand_NoMatch;
4270
Jim Grosbach9d390362011-10-03 23:38:36 +00004271 Parser.Lex(); // Eat the '#'.
4272
4273 // Handle negation, as that still comes through as a separate token.
4274 bool isNegative = false;
4275 if (Parser.getTok().is(AsmToken::Minus)) {
4276 isNegative = true;
4277 Parser.Lex();
4278 }
4279 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004280 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004281 if (Tok.is(AsmToken::Real)) {
4282 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4283 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4284 // If we had a '-' in front, toggle the sign bit.
4285 IntVal ^= (uint64_t)isNegative << 63;
4286 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4287 Parser.Lex(); // Eat the token.
4288 if (Val == -1) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004289 Error(Loc, "floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004290 return MatchOperand_ParseFail;
4291 }
4292 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4293 return MatchOperand_Success;
4294 }
4295 if (Tok.is(AsmToken::Integer)) {
4296 int64_t Val = Tok.getIntVal();
4297 Parser.Lex(); // Eat the token.
4298 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004299 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004300 return MatchOperand_ParseFail;
4301 }
4302 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4303 return MatchOperand_Success;
4304 }
4305
Jim Grosbachae69f702012-01-19 02:47:30 +00004306 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004307 return MatchOperand_ParseFail;
4308}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004309/// Parse a arm instruction operand. For now this parses the operand regardless
4310/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004311bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004312 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004313 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004314
4315 // Check if the current operand has a custom associated parser, if so, try to
4316 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004317 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4318 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004319 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004320 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4321 // there was a match, but an error occurred, in which case, just return that
4322 // the operand parsing failed.
4323 if (ResTy == MatchOperand_ParseFail)
4324 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004325
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004326 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004327 default:
4328 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004329 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004330 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004331 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004332 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004333 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004334 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004335 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004336 else if (Res == -1) // irrecoverable error
4337 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004338 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004339 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4340 S = Parser.getTok().getLoc();
4341 Parser.Lex();
4342 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4343 return false;
4344 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004345
4346 // Fall though for the Identifier case that is not a register or a
4347 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004348 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004349 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004350 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004351 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004352 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004353 // This was not a register so parse other operands that start with an
4354 // identifier (like labels) as expressions and create them as immediates.
4355 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004356 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004357 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004358 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004359 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004360 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4361 return false;
4362 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004363 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004364 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004365 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004366 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004367 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004368 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004369 // #42 -> immediate.
4370 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004371 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004372 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004373 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004374 const MCExpr *ImmVal;
4375 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004376 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004377 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004378 if (CE) {
4379 int32_t Val = CE->getValue();
4380 if (isNegative && Val == 0)
4381 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004382 }
Sean Callanan76264762010-04-02 22:27:05 +00004383 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004384 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4385 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004386 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004387 case AsmToken::Colon: {
4388 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004389 // FIXME: Check it's an expression prefix,
4390 // e.g. (FOO - :lower16:BAR) isn't legal.
4391 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004392 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004393 return true;
4394
Evan Cheng75972122011-01-13 07:58:56 +00004395 const MCExpr *SubExprVal;
4396 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004397 return true;
4398
Evan Cheng75972122011-01-13 07:58:56 +00004399 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4400 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004401 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004402 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004403 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004404 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004405 }
4406}
4407
Jim Grosbach1355cf12011-07-26 17:10:22 +00004408// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004409// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004410bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004411 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004412
4413 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004414 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004415 Parser.Lex(); // Eat ':'
4416
4417 if (getLexer().isNot(AsmToken::Identifier)) {
4418 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4419 return true;
4420 }
4421
4422 StringRef IDVal = Parser.getTok().getIdentifier();
4423 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004424 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004425 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004426 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004427 } else {
4428 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4429 return true;
4430 }
4431 Parser.Lex();
4432
4433 if (getLexer().isNot(AsmToken::Colon)) {
4434 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4435 return true;
4436 }
4437 Parser.Lex(); // Eat the last ':'
4438 return false;
4439}
4440
Daniel Dunbar352e1482011-01-11 15:59:50 +00004441/// \brief Given a mnemonic, split out possible predication code and carry
4442/// setting letters to form a canonical mnemonic and flags.
4443//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004444// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004445// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004446StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004447 unsigned &PredicationCode,
4448 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004449 unsigned &ProcessorIMod,
4450 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004451 PredicationCode = ARMCC::AL;
4452 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004453 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004454
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004455 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004456 //
4457 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004458 if ((Mnemonic == "movs" && isThumb()) ||
4459 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4460 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4461 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4462 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4463 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4464 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004465 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4466 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004467 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004468
Jim Grosbach3f00e312011-07-11 17:09:57 +00004469 // First, split out any predication code. Ignore mnemonics we know aren't
4470 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004471 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004472 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004473 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004474 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004475 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4476 .Case("eq", ARMCC::EQ)
4477 .Case("ne", ARMCC::NE)
4478 .Case("hs", ARMCC::HS)
4479 .Case("cs", ARMCC::HS)
4480 .Case("lo", ARMCC::LO)
4481 .Case("cc", ARMCC::LO)
4482 .Case("mi", ARMCC::MI)
4483 .Case("pl", ARMCC::PL)
4484 .Case("vs", ARMCC::VS)
4485 .Case("vc", ARMCC::VC)
4486 .Case("hi", ARMCC::HI)
4487 .Case("ls", ARMCC::LS)
4488 .Case("ge", ARMCC::GE)
4489 .Case("lt", ARMCC::LT)
4490 .Case("gt", ARMCC::GT)
4491 .Case("le", ARMCC::LE)
4492 .Case("al", ARMCC::AL)
4493 .Default(~0U);
4494 if (CC != ~0U) {
4495 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4496 PredicationCode = CC;
4497 }
Bill Wendling52925b62010-10-29 23:50:21 +00004498 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004499
Daniel Dunbar352e1482011-01-11 15:59:50 +00004500 // Next, determine if we have a carry setting bit. We explicitly ignore all
4501 // the instructions we know end in 's'.
4502 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004503 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004504 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4505 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4506 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004507 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004508 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004509 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004510 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004511 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004512 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4513 CarrySetting = true;
4514 }
4515
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004516 // The "cps" instruction can have a interrupt mode operand which is glued into
4517 // the mnemonic. Check if this is the case, split it and parse the imod op
4518 if (Mnemonic.startswith("cps")) {
4519 // Split out any imod code.
4520 unsigned IMod =
4521 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4522 .Case("ie", ARM_PROC::IE)
4523 .Case("id", ARM_PROC::ID)
4524 .Default(~0U);
4525 if (IMod != ~0U) {
4526 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4527 ProcessorIMod = IMod;
4528 }
4529 }
4530
Jim Grosbach89df9962011-08-26 21:43:41 +00004531 // The "it" instruction has the condition mask on the end of the mnemonic.
4532 if (Mnemonic.startswith("it")) {
4533 ITMask = Mnemonic.slice(2, Mnemonic.size());
4534 Mnemonic = Mnemonic.slice(0, 2);
4535 }
4536
Daniel Dunbar352e1482011-01-11 15:59:50 +00004537 return Mnemonic;
4538}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004539
4540/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4541/// inclusion of carry set or predication code operands.
4542//
4543// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004544void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004545getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004546 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004547 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4548 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004549 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004550 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004551 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004552 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004553 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004554 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004555 Mnemonic == "mla" || Mnemonic == "smlal" ||
4556 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004557 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004558 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004559 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004560
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004561 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4562 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4563 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4564 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004565 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4566 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004567 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004568 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4569 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4570 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004571 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4572 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004573 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004574 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004575 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004576 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004577
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004578 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004579 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004580 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004581 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004582 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004583}
4584
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004585bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4586 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004587 // FIXME: This is all horribly hacky. We really need a better way to deal
4588 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004589
4590 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4591 // another does not. Specifically, the MOVW instruction does not. So we
4592 // special case it here and remove the defaulted (non-setting) cc_out
4593 // operand if that's the instruction we're trying to match.
4594 //
4595 // We do this as post-processing of the explicit operands rather than just
4596 // conditionally adding the cc_out in the first place because we need
4597 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004598 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004599 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4600 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4601 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4602 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004603
4604 // Register-register 'add' for thumb does not have a cc_out operand
4605 // when there are only two register operands.
4606 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4607 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4608 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4609 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4610 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004611 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004612 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4613 // have to check the immediate range here since Thumb2 has a variant
4614 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004615 if (((isThumb() && Mnemonic == "add") ||
4616 (isThumbTwo() && Mnemonic == "sub")) &&
4617 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004618 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4619 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4620 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004621 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4622 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4623 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004624 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004625 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4626 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004627 // selecting via the generic "add" mnemonic, so to know that we
4628 // should remove the cc_out operand, we have to explicitly check that
4629 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004630 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4631 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004632 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4633 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4634 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4635 // Nest conditions rather than one big 'if' statement for readability.
4636 //
4637 // If either register is a high reg, it's either one of the SP
4638 // variants (handled above) or a 32-bit encoding, so we just
4639 // check against T3.
4640 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4641 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4642 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4643 return false;
4644 // If both registers are low, we're in an IT block, and the immediate is
4645 // in range, we should use encoding T1 instead, which has a cc_out.
4646 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004647 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004648 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4649 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4650 return false;
4651
4652 // Otherwise, we use encoding T4, which does not have a cc_out
4653 // operand.
4654 return true;
4655 }
4656
Jim Grosbach64944f42011-09-14 21:00:40 +00004657 // The thumb2 multiply instruction doesn't have a CCOut register, so
4658 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4659 // use the 16-bit encoding or not.
4660 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4661 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4662 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4663 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4664 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4665 // If the registers aren't low regs, the destination reg isn't the
4666 // same as one of the source regs, or the cc_out operand is zero
4667 // outside of an IT block, we have to use the 32-bit encoding, so
4668 // remove the cc_out operand.
4669 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4670 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004671 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004672 !inITBlock() ||
4673 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4674 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4675 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4676 static_cast<ARMOperand*>(Operands[4])->getReg())))
4677 return true;
4678
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004679 // Also check the 'mul' syntax variant that doesn't specify an explicit
4680 // destination register.
4681 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4682 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4683 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4684 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4685 // If the registers aren't low regs or the cc_out operand is zero
4686 // outside of an IT block, we have to use the 32-bit encoding, so
4687 // remove the cc_out operand.
4688 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4689 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4690 !inITBlock()))
4691 return true;
4692
Jim Grosbach64944f42011-09-14 21:00:40 +00004693
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004694
Jim Grosbachf69c8042011-08-24 21:42:27 +00004695 // Register-register 'add/sub' for thumb does not have a cc_out operand
4696 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4697 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4698 // right, this will result in better diagnostics (which operand is off)
4699 // anyway.
4700 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4701 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004702 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4703 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4704 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4705 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004706
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004707 return false;
4708}
4709
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004710static bool isDataTypeToken(StringRef Tok) {
4711 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4712 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4713 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4714 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4715 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4716 Tok == ".f" || Tok == ".d";
4717}
4718
4719// FIXME: This bit should probably be handled via an explicit match class
4720// in the .td files that matches the suffix instead of having it be
4721// a literal string token the way it is now.
4722static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4723 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4724}
4725
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004726static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004727/// Parse an arm instruction mnemonic followed by its operands.
4728bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4729 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004730 // Apply mnemonic aliases before doing anything else, as the destination
4731 // mnemnonic may include suffices and we want to handle them normally.
4732 // The generic tblgen'erated code does this later, at the start of
4733 // MatchInstructionImpl(), but that's too late for aliases that include
4734 // any sort of suffix.
4735 unsigned AvailableFeatures = getAvailableFeatures();
4736 applyMnemonicAliases(Name, AvailableFeatures);
4737
Jim Grosbacha39cda72011-12-14 02:16:11 +00004738 // First check for the ARM-specific .req directive.
4739 if (Parser.getTok().is(AsmToken::Identifier) &&
4740 Parser.getTok().getIdentifier() == ".req") {
4741 parseDirectiveReq(Name, NameLoc);
4742 // We always return 'error' for this, as we're done with this
4743 // statement and don't need to match the 'instruction."
4744 return true;
4745 }
4746
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004747 // Create the leading tokens for the mnemonic, split by '.' characters.
4748 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004749 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004750
Daniel Dunbar352e1482011-01-11 15:59:50 +00004751 // Split out the predication code and carry setting flag from the mnemonic.
4752 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004753 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004754 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004755 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004756 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004757 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004758
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004759 // In Thumb1, only the branch (B) instruction can be predicated.
4760 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4761 Parser.EatToEndOfStatement();
4762 return Error(NameLoc, "conditional execution not supported in Thumb1");
4763 }
4764
Jim Grosbachffa32252011-07-19 19:13:28 +00004765 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4766
Jim Grosbach89df9962011-08-26 21:43:41 +00004767 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4768 // is the mask as it will be for the IT encoding if the conditional
4769 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4770 // where the conditional bit0 is zero, the instruction post-processing
4771 // will adjust the mask accordingly.
4772 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004773 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4774 if (ITMask.size() > 3) {
4775 Parser.EatToEndOfStatement();
4776 return Error(Loc, "too many conditions on IT instruction");
4777 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004778 unsigned Mask = 8;
4779 for (unsigned i = ITMask.size(); i != 0; --i) {
4780 char pos = ITMask[i - 1];
4781 if (pos != 't' && pos != 'e') {
4782 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004783 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004784 }
4785 Mask >>= 1;
4786 if (ITMask[i - 1] == 't')
4787 Mask |= 8;
4788 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004789 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004790 }
4791
Jim Grosbachffa32252011-07-19 19:13:28 +00004792 // FIXME: This is all a pretty gross hack. We should automatically handle
4793 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004794
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004795 // Next, add the CCOut and ConditionCode operands, if needed.
4796 //
4797 // For mnemonics which can ever incorporate a carry setting bit or predication
4798 // code, our matching model involves us always generating CCOut and
4799 // ConditionCode operands to match the mnemonic "as written" and then we let
4800 // the matcher deal with finding the right instruction or generating an
4801 // appropriate error.
4802 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004803 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004804
Jim Grosbach33c16a22011-07-14 22:04:21 +00004805 // If we had a carry-set on an instruction that can't do that, issue an
4806 // error.
4807 if (!CanAcceptCarrySet && CarrySetting) {
4808 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004809 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004810 "' can not set flags, but 's' suffix specified");
4811 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004812 // If we had a predication code on an instruction that can't do that, issue an
4813 // error.
4814 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4815 Parser.EatToEndOfStatement();
4816 return Error(NameLoc, "instruction '" + Mnemonic +
4817 "' is not predicable, but condition code specified");
4818 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004819
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004820 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004821 if (CanAcceptCarrySet) {
4822 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004823 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004824 Loc));
4825 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004826
4827 // Add the predication code operand, if necessary.
4828 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004829 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4830 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004831 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004832 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004833 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004834
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004835 // Add the processor imod operand, if necessary.
4836 if (ProcessorIMod) {
4837 Operands.push_back(ARMOperand::CreateImm(
4838 MCConstantExpr::Create(ProcessorIMod, getContext()),
4839 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004840 }
4841
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004842 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004843 while (Next != StringRef::npos) {
4844 Start = Next;
4845 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004846 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004847
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004848 // Some NEON instructions have an optional datatype suffix that is
4849 // completely ignored. Check for that.
4850 if (isDataTypeToken(ExtraToken) &&
4851 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4852 continue;
4853
Jim Grosbach81d2e392011-09-07 16:06:04 +00004854 if (ExtraToken != ".n") {
4855 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4856 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4857 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004858 }
4859
4860 // Read the remaining operands.
4861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004862 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004863 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004864 Parser.EatToEndOfStatement();
4865 return true;
4866 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004867
4868 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004869 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004870
4871 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004872 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004873 Parser.EatToEndOfStatement();
4874 return true;
4875 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004876 }
4877 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004878
Chris Lattnercbf8a982010-09-11 16:18:25 +00004879 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004880 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004881 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004882 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004883 }
Bill Wendling146018f2010-11-06 21:42:12 +00004884
Chris Lattner34e53142010-09-08 05:10:46 +00004885 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004886
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004887 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4888 // do and don't have a cc_out optional-def operand. With some spot-checks
4889 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004890 // parse and adjust accordingly before actually matching. We shouldn't ever
4891 // try to remove a cc_out operand that was explicitly set on the the
4892 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4893 // table driven matcher doesn't fit well with the ARM instruction set.
4894 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004895 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4896 Operands.erase(Operands.begin() + 1);
4897 delete Op;
4898 }
4899
Jim Grosbachcf121c32011-07-28 21:57:55 +00004900 // ARM mode 'blx' need special handling, as the register operand version
4901 // is predicable, but the label operand version is not. So, we can't rely
4902 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004903 // a k_CondCode operand in the list. If we're trying to match the label
4904 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004905 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4906 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4907 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4908 Operands.erase(Operands.begin() + 1);
4909 delete Op;
4910 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004911
4912 // The vector-compare-to-zero instructions have a literal token "#0" at
4913 // the end that comes to here as an immediate operand. Convert it to a
4914 // token to play nicely with the matcher.
4915 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4916 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4917 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4918 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4919 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4920 if (CE && CE->getValue() == 0) {
4921 Operands.erase(Operands.begin() + 5);
4922 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4923 delete Op;
4924 }
4925 }
Jim Grosbach68259142011-10-03 22:30:24 +00004926 // VCMP{E} does the same thing, but with a different operand count.
4927 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4928 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4929 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4930 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4931 if (CE && CE->getValue() == 0) {
4932 Operands.erase(Operands.begin() + 4);
4933 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4934 delete Op;
4935 }
4936 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004937 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004938 // end. Convert it to a token here. Take care not to convert those
4939 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004940 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004941 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4942 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004943 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4944 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4945 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004946 if (CE && CE->getValue() == 0 &&
4947 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004948 // The cc_out operand matches the IT block.
4949 ((inITBlock() != CarrySetting) &&
4950 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004951 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004952 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004953 Operands.erase(Operands.begin() + 5);
4954 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4955 delete Op;
4956 }
4957 }
4958
Chris Lattner98986712010-01-14 22:21:20 +00004959 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004960}
4961
Jim Grosbach189610f2011-07-26 18:25:39 +00004962// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004963
4964// return 'true' if register list contains non-low GPR registers,
4965// 'false' otherwise. If Reg is in the register list or is HiReg, set
4966// 'containsReg' to true.
4967static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4968 unsigned HiReg, bool &containsReg) {
4969 containsReg = false;
4970 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4971 unsigned OpReg = Inst.getOperand(i).getReg();
4972 if (OpReg == Reg)
4973 containsReg = true;
4974 // Anything other than a low register isn't legal here.
4975 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4976 return true;
4977 }
4978 return false;
4979}
4980
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004981// Check if the specified regisgter is in the register list of the inst,
4982// starting at the indicated operand number.
4983static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4984 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4985 unsigned OpReg = Inst.getOperand(i).getReg();
4986 if (OpReg == Reg)
4987 return true;
4988 }
4989 return false;
4990}
4991
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004992// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4993// the ARMInsts array) instead. Getting that here requires awkward
4994// API changes, though. Better way?
4995namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004996extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004997}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004998static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004999 return ARMInsts[Opcode];
5000}
5001
Jim Grosbach189610f2011-07-26 18:25:39 +00005002// FIXME: We would really like to be able to tablegen'erate this.
5003bool ARMAsmParser::
5004validateInstruction(MCInst &Inst,
5005 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005006 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005007 SMLoc Loc = Operands[0]->getStartLoc();
5008 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005009 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5010 // being allowed in IT blocks, but not being predicable. It just always
5011 // executes.
5012 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005013 unsigned bit = 1;
5014 if (ITState.FirstCond)
5015 ITState.FirstCond = false;
5016 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005017 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005018 // The instruction must be predicable.
5019 if (!MCID.isPredicable())
5020 return Error(Loc, "instructions in IT block must be predicable");
5021 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5022 unsigned ITCond = bit ? ITState.Cond :
5023 ARMCC::getOppositeCondition(ITState.Cond);
5024 if (Cond != ITCond) {
5025 // Find the condition code Operand to get its SMLoc information.
5026 SMLoc CondLoc;
5027 for (unsigned i = 1; i < Operands.size(); ++i)
5028 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5029 CondLoc = Operands[i]->getStartLoc();
5030 return Error(CondLoc, "incorrect condition in IT block; got '" +
5031 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5032 "', but expected '" +
5033 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5034 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005035 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005036 } else if (isThumbTwo() && MCID.isPredicable() &&
5037 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005038 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5039 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005040 return Error(Loc, "predicated instructions must be in IT block");
5041
Jim Grosbach189610f2011-07-26 18:25:39 +00005042 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005043 case ARM::LDRD:
5044 case ARM::LDRD_PRE:
5045 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005046 case ARM::LDREXD: {
5047 // Rt2 must be Rt + 1.
5048 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5049 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5050 if (Rt2 != Rt + 1)
5051 return Error(Operands[3]->getStartLoc(),
5052 "destination operands must be sequential");
5053 return false;
5054 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005055 case ARM::STRD: {
5056 // Rt2 must be Rt + 1.
5057 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5058 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5059 if (Rt2 != Rt + 1)
5060 return Error(Operands[3]->getStartLoc(),
5061 "source operands must be sequential");
5062 return false;
5063 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005064 case ARM::STRD_PRE:
5065 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005066 case ARM::STREXD: {
5067 // Rt2 must be Rt + 1.
5068 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5069 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5070 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005071 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005072 "source operands must be sequential");
5073 return false;
5074 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005075 case ARM::SBFX:
5076 case ARM::UBFX: {
5077 // width must be in range [1, 32-lsb]
5078 unsigned lsb = Inst.getOperand(2).getImm();
5079 unsigned widthm1 = Inst.getOperand(3).getImm();
5080 if (widthm1 >= 32 - lsb)
5081 return Error(Operands[5]->getStartLoc(),
5082 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005083 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005084 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005085 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005086 // If we're parsing Thumb2, the .w variant is available and handles
5087 // most cases that are normally illegal for a Thumb1 LDM
5088 // instruction. We'll make the transformation in processInstruction()
5089 // if necessary.
5090 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005091 // Thumb LDM instructions are writeback iff the base register is not
5092 // in the register list.
5093 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005094 bool hasWritebackToken =
5095 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5096 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005097 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005098 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005099 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5100 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005101 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005102 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005103 return Error(Operands[2]->getStartLoc(),
5104 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005105 // If we should not have writeback, there must not be a '!'. This is
5106 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005107 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005108 return Error(Operands[3]->getStartLoc(),
5109 "writeback operator '!' not allowed when base register "
5110 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005111
5112 break;
5113 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005114 case ARM::t2LDMIA_UPD: {
5115 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5116 return Error(Operands[4]->getStartLoc(),
5117 "writeback operator '!' not allowed when base register "
5118 "in register list");
5119 break;
5120 }
Jim Grosbach54026372011-11-10 23:17:11 +00005121 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5122 // so only issue a diagnostic for thumb1. The instructions will be
5123 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005124 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005125 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005126 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5127 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005128 return Error(Operands[2]->getStartLoc(),
5129 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005130 break;
5131 }
5132 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005133 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005134 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5135 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005136 return Error(Operands[2]->getStartLoc(),
5137 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005138 break;
5139 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005140 case ARM::tSTMIA_UPD: {
5141 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005142 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005143 return Error(Operands[4]->getStartLoc(),
5144 "registers must be in range r0-r7");
5145 break;
5146 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005147 }
5148
5149 return false;
5150}
5151
Jim Grosbach5b484312011-12-20 20:46:29 +00005152static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005153 switch(Opc) {
5154 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005155 // VST1LN
5156 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5157 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5158 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005159 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005160 return ARM::VST1LNd8_UPD;
5161 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5162 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5163 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005164 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005165 return ARM::VST1LNd16_UPD;
5166 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5167 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5168 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005169 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005170 return ARM::VST1LNd32_UPD;
5171 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5172 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5173 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005174 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005175 return ARM::VST1LNd8_UPD;
5176 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5177 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5178 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005179 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005180 return ARM::VST1LNd16_UPD;
5181 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5182 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5183 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005184 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005185 return ARM::VST1LNd32_UPD;
5186 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5187 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5188 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005189 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005190 return ARM::VST1LNd8;
5191 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5192 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5193 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005194 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005195 return ARM::VST1LNd16;
5196 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5197 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5198 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005199 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005200 return ARM::VST1LNd32;
5201
5202 // VST2LN
5203 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5204 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5205 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005206 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005207 return ARM::VST2LNd8_UPD;
5208 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5209 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5210 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005211 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005212 return ARM::VST2LNd16_UPD;
5213 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5214 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5215 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005216 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005217 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005218 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5219 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5220 case ARM::VST2LNqWB_fixed_Asm_U16:
5221 Spacing = 2;
5222 return ARM::VST2LNq16_UPD;
5223 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5224 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5225 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5226 Spacing = 2;
5227 return ARM::VST2LNq32_UPD;
5228
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005229 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5230 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5231 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005232 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005233 return ARM::VST2LNd8_UPD;
5234 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5235 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5236 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005237 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005238 return ARM::VST2LNd16_UPD;
5239 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5240 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5241 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005242 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005243 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005244 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5245 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5246 case ARM::VST2LNqWB_register_Asm_U16:
5247 Spacing = 2;
5248 return ARM::VST2LNq16_UPD;
5249 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5250 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5251 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5252 Spacing = 2;
5253 return ARM::VST2LNq32_UPD;
5254
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005255 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5256 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5257 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005258 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005259 return ARM::VST2LNd8;
5260 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5261 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5262 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005263 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005264 return ARM::VST2LNd16;
5265 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5266 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5267 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005268 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005269 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005270 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5271 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5272 case ARM::VST2LNqAsm_U16:
5273 Spacing = 2;
5274 return ARM::VST2LNq16;
5275 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5276 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5277 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5278 Spacing = 2;
5279 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005280 }
5281}
5282
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005283static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005284 switch(Opc) {
5285 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005286 // VLD1LN
5287 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5288 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5289 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005290 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005291 return ARM::VLD1LNd8_UPD;
5292 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5293 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5294 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005295 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005296 return ARM::VLD1LNd16_UPD;
5297 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5298 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5299 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005300 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005301 return ARM::VLD1LNd32_UPD;
5302 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5303 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5304 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005305 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005306 return ARM::VLD1LNd8_UPD;
5307 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5308 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5309 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005310 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005311 return ARM::VLD1LNd16_UPD;
5312 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5313 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5314 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005315 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005316 return ARM::VLD1LNd32_UPD;
5317 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5318 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5319 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005320 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005321 return ARM::VLD1LNd8;
5322 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5323 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5324 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005325 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005326 return ARM::VLD1LNd16;
5327 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5328 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5329 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005330 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005331 return ARM::VLD1LNd32;
5332
5333 // VLD2LN
5334 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5335 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5336 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005337 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005338 return ARM::VLD2LNd8_UPD;
5339 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5340 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5341 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005342 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005343 return ARM::VLD2LNd16_UPD;
5344 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5345 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5346 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005347 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005348 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005349 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5350 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5351 case ARM::VLD2LNqWB_fixed_Asm_U16:
5352 Spacing = 1;
5353 return ARM::VLD2LNq16_UPD;
5354 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5355 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5356 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5357 Spacing = 2;
5358 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005359 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5360 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5361 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005362 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005363 return ARM::VLD2LNd8_UPD;
5364 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5365 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5366 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005367 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005368 return ARM::VLD2LNd16_UPD;
5369 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5370 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5371 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005372 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005373 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005374 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5375 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5376 case ARM::VLD2LNqWB_register_Asm_U16:
5377 Spacing = 2;
5378 return ARM::VLD2LNq16_UPD;
5379 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5380 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5381 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5382 Spacing = 2;
5383 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005384 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5385 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5386 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005387 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005388 return ARM::VLD2LNd8;
5389 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5390 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5391 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005392 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005393 return ARM::VLD2LNd16;
5394 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5395 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5396 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005397 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005398 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005399 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5400 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5401 case ARM::VLD2LNqAsm_U16:
5402 Spacing = 2;
5403 return ARM::VLD2LNq16;
5404 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5405 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5406 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5407 Spacing = 2;
5408 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005409 }
5410}
5411
Jim Grosbach83ec8772011-11-10 23:42:14 +00005412bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005413processInstruction(MCInst &Inst,
5414 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5415 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005416 // Aliases for alternate PC+imm syntax of LDR instructions.
5417 case ARM::t2LDRpcrel:
5418 Inst.setOpcode(ARM::t2LDRpci);
5419 return true;
5420 case ARM::t2LDRBpcrel:
5421 Inst.setOpcode(ARM::t2LDRBpci);
5422 return true;
5423 case ARM::t2LDRHpcrel:
5424 Inst.setOpcode(ARM::t2LDRHpci);
5425 return true;
5426 case ARM::t2LDRSBpcrel:
5427 Inst.setOpcode(ARM::t2LDRSBpci);
5428 return true;
5429 case ARM::t2LDRSHpcrel:
5430 Inst.setOpcode(ARM::t2LDRSHpci);
5431 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005432 // Handle NEON VST complex aliases.
5433 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5434 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5435 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5436 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5437 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5438 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5439 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5440 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005441 MCInst TmpInst;
5442 // Shuffle the operands around so the lane index operand is in the
5443 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005444 unsigned Spacing;
5445 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005446 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5447 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5448 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5449 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5450 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5451 TmpInst.addOperand(Inst.getOperand(1)); // lane
5452 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5453 TmpInst.addOperand(Inst.getOperand(6));
5454 Inst = TmpInst;
5455 return true;
5456 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005457
Jim Grosbach5b484312011-12-20 20:46:29 +00005458 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5459 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5460 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005461 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5462 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005463 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005464 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005465 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5466 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5467 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5468 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5469 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5470 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5471 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005472 MCInst TmpInst;
5473 // Shuffle the operands around so the lane index operand is in the
5474 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005475 unsigned Spacing;
5476 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005477 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5478 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5479 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5480 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5481 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005482 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5483 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005484 TmpInst.addOperand(Inst.getOperand(1)); // lane
5485 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5486 TmpInst.addOperand(Inst.getOperand(6));
5487 Inst = TmpInst;
5488 return true;
5489 }
5490 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5491 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5492 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5493 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5494 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5495 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5496 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5497 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005498 MCInst TmpInst;
5499 // Shuffle the operands around so the lane index operand is in the
5500 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005501 unsigned Spacing;
5502 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005503 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5504 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5505 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5506 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5507 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5508 TmpInst.addOperand(Inst.getOperand(1)); // lane
5509 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5510 TmpInst.addOperand(Inst.getOperand(5));
5511 Inst = TmpInst;
5512 return true;
5513 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005514
Jim Grosbach5b484312011-12-20 20:46:29 +00005515 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5516 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5517 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005518 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5519 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005520 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005521 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005522 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5523 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5524 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5525 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5526 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5527 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5528 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005529 MCInst TmpInst;
5530 // Shuffle the operands around so the lane index operand is in the
5531 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005532 unsigned Spacing;
5533 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005534 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5535 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5536 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5537 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5538 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005539 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5540 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005541 TmpInst.addOperand(Inst.getOperand(1)); // lane
5542 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5543 TmpInst.addOperand(Inst.getOperand(5));
5544 Inst = TmpInst;
5545 return true;
5546 }
5547 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5548 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5549 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5550 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5551 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005552 case ARM::VST1LNdAsm_U32: {
5553 MCInst TmpInst;
5554 // Shuffle the operands around so the lane index operand is in the
5555 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005556 unsigned Spacing;
5557 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005558 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5559 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5560 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5561 TmpInst.addOperand(Inst.getOperand(1)); // lane
5562 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5563 TmpInst.addOperand(Inst.getOperand(5));
5564 Inst = TmpInst;
5565 return true;
5566 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005567
Jim Grosbach5b484312011-12-20 20:46:29 +00005568 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5569 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005570 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005571 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005572 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005573 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5574 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5575 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5576 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005577 MCInst TmpInst;
5578 // Shuffle the operands around so the lane index operand is in the
5579 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005580 unsigned Spacing;
5581 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005582 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5583 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5584 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005585 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5586 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005587 TmpInst.addOperand(Inst.getOperand(1)); // lane
5588 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5589 TmpInst.addOperand(Inst.getOperand(5));
5590 Inst = TmpInst;
5591 return true;
5592 }
5593 // Handle NEON VLD complex aliases.
5594 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5595 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5596 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5597 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5598 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5599 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5600 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5601 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005602 MCInst TmpInst;
5603 // Shuffle the operands around so the lane index operand is in the
5604 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005605 unsigned Spacing;
5606 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005607 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5608 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5609 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5610 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5611 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5612 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5613 TmpInst.addOperand(Inst.getOperand(1)); // lane
5614 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5615 TmpInst.addOperand(Inst.getOperand(6));
5616 Inst = TmpInst;
5617 return true;
5618 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005619
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005620 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5621 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5622 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005623 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5624 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005625 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005626 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005627 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005628 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5629 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5630 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5631 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5632 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5633 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005634 MCInst TmpInst;
5635 // Shuffle the operands around so the lane index operand is in the
5636 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005637 unsigned Spacing;
5638 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005639 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005640 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5641 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005642 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5643 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5644 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5645 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5646 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005647 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5648 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005649 TmpInst.addOperand(Inst.getOperand(1)); // lane
5650 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5651 TmpInst.addOperand(Inst.getOperand(6));
5652 Inst = TmpInst;
5653 return true;
5654 }
5655
5656 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5657 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5658 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5659 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5660 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5661 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5662 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5663 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005664 MCInst TmpInst;
5665 // Shuffle the operands around so the lane index operand is in the
5666 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005667 unsigned Spacing;
5668 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005669 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5670 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5671 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5672 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5673 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5674 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5675 TmpInst.addOperand(Inst.getOperand(1)); // lane
5676 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5677 TmpInst.addOperand(Inst.getOperand(5));
5678 Inst = TmpInst;
5679 return true;
5680 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005681
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005682 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5683 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5684 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005685 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5686 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005687 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005688 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005689 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005690 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5691 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5692 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5693 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5694 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5695 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005696 MCInst TmpInst;
5697 // Shuffle the operands around so the lane index operand is in the
5698 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005699 unsigned Spacing;
5700 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005701 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005702 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5703 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005704 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5705 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5706 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5707 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5708 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005709 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5710 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005711 TmpInst.addOperand(Inst.getOperand(1)); // lane
5712 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5713 TmpInst.addOperand(Inst.getOperand(5));
5714 Inst = TmpInst;
5715 return true;
5716 }
5717
Jim Grosbach5b484312011-12-20 20:46:29 +00005718 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5719 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005720 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005721 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005722 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005723 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005724 MCInst TmpInst;
5725 // Shuffle the operands around so the lane index operand is in the
5726 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005727 unsigned Spacing;
5728 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005729 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5730 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5731 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5732 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5733 TmpInst.addOperand(Inst.getOperand(1)); // lane
5734 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5735 TmpInst.addOperand(Inst.getOperand(5));
5736 Inst = TmpInst;
5737 return true;
5738 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005739
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005740 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5741 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005742 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005743 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005744 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005745 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5746 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5747 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5748 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5749 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005750 MCInst TmpInst;
5751 // Shuffle the operands around so the lane index operand is in the
5752 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005753 unsigned Spacing;
5754 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005755 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005756 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5757 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005758 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5759 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5760 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005761 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5762 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005763 TmpInst.addOperand(Inst.getOperand(1)); // lane
5764 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5765 TmpInst.addOperand(Inst.getOperand(5));
5766 Inst = TmpInst;
5767 return true;
5768 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005769 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00005770 case ARM::t2MOVsr:
5771 case ARM::t2MOVSsr: {
5772 // Which instruction to expand to depends on the CCOut operand and
5773 // whether we're in an IT block if the register operands are low
5774 // registers.
5775 bool isNarrow = false;
5776 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5777 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5778 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5779 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5780 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5781 isNarrow = true;
5782 MCInst TmpInst;
5783 unsigned newOpc;
5784 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5785 default: llvm_unreachable("unexpected opcode!");
5786 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5787 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5788 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5789 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5790 }
5791 TmpInst.setOpcode(newOpc);
5792 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5793 if (isNarrow)
5794 TmpInst.addOperand(MCOperand::CreateReg(
5795 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5796 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5797 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5798 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5799 TmpInst.addOperand(Inst.getOperand(5));
5800 if (!isNarrow)
5801 TmpInst.addOperand(MCOperand::CreateReg(
5802 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5803 Inst = TmpInst;
5804 return true;
5805 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005806 case ARM::t2MOVsi:
5807 case ARM::t2MOVSsi: {
5808 // Which instruction to expand to depends on the CCOut operand and
5809 // whether we're in an IT block if the register operands are low
5810 // registers.
5811 bool isNarrow = false;
5812 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5813 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5814 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5815 isNarrow = true;
5816 MCInst TmpInst;
5817 unsigned newOpc;
5818 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5819 default: llvm_unreachable("unexpected opcode!");
5820 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5821 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5822 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5823 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00005824 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00005825 }
5826 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5827 if (Ammount == 32) Ammount = 0;
5828 TmpInst.setOpcode(newOpc);
5829 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5830 if (isNarrow)
5831 TmpInst.addOperand(MCOperand::CreateReg(
5832 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5833 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00005834 if (newOpc != ARM::t2RRX)
5835 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00005836 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5837 TmpInst.addOperand(Inst.getOperand(4));
5838 if (!isNarrow)
5839 TmpInst.addOperand(MCOperand::CreateReg(
5840 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5841 Inst = TmpInst;
5842 return true;
5843 }
5844 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005845 case ARM::ASRr:
5846 case ARM::LSRr:
5847 case ARM::LSLr:
5848 case ARM::RORr: {
5849 ARM_AM::ShiftOpc ShiftTy;
5850 switch(Inst.getOpcode()) {
5851 default: llvm_unreachable("unexpected opcode!");
5852 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5853 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5854 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5855 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5856 }
Jim Grosbach23f22072011-11-16 18:31:45 +00005857 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5858 MCInst TmpInst;
5859 TmpInst.setOpcode(ARM::MOVsr);
5860 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5861 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5862 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5863 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5864 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5865 TmpInst.addOperand(Inst.getOperand(4));
5866 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5867 Inst = TmpInst;
5868 return true;
5869 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005870 case ARM::ASRi:
5871 case ARM::LSRi:
5872 case ARM::LSLi:
5873 case ARM::RORi: {
5874 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005875 switch(Inst.getOpcode()) {
5876 default: llvm_unreachable("unexpected opcode!");
5877 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5878 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5879 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5880 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5881 }
5882 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005883 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005884 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5885 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005886 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005887 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005888 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5889 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005890 if (Opc == ARM::MOVsi)
5891 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005892 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5893 TmpInst.addOperand(Inst.getOperand(4));
5894 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5895 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005896 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005897 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005898 case ARM::RRXi: {
5899 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5900 MCInst TmpInst;
5901 TmpInst.setOpcode(ARM::MOVsi);
5902 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5903 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5904 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5905 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5906 TmpInst.addOperand(Inst.getOperand(3));
5907 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5908 Inst = TmpInst;
5909 return true;
5910 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005911 case ARM::t2LDMIA_UPD: {
5912 // If this is a load of a single register, then we should use
5913 // a post-indexed LDR instruction instead, per the ARM ARM.
5914 if (Inst.getNumOperands() != 5)
5915 return false;
5916 MCInst TmpInst;
5917 TmpInst.setOpcode(ARM::t2LDR_POST);
5918 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5919 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5920 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5921 TmpInst.addOperand(MCOperand::CreateImm(4));
5922 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5923 TmpInst.addOperand(Inst.getOperand(3));
5924 Inst = TmpInst;
5925 return true;
5926 }
5927 case ARM::t2STMDB_UPD: {
5928 // If this is a store of a single register, then we should use
5929 // a pre-indexed STR instruction instead, per the ARM ARM.
5930 if (Inst.getNumOperands() != 5)
5931 return false;
5932 MCInst TmpInst;
5933 TmpInst.setOpcode(ARM::t2STR_PRE);
5934 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5935 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5936 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5937 TmpInst.addOperand(MCOperand::CreateImm(-4));
5938 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5939 TmpInst.addOperand(Inst.getOperand(3));
5940 Inst = TmpInst;
5941 return true;
5942 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005943 case ARM::LDMIA_UPD:
5944 // If this is a load of a single register via a 'pop', then we should use
5945 // a post-indexed LDR instruction instead, per the ARM ARM.
5946 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5947 Inst.getNumOperands() == 5) {
5948 MCInst TmpInst;
5949 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5950 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5951 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5952 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5953 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5954 TmpInst.addOperand(MCOperand::CreateImm(4));
5955 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5956 TmpInst.addOperand(Inst.getOperand(3));
5957 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005958 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005959 }
5960 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005961 case ARM::STMDB_UPD:
5962 // If this is a store of a single register via a 'push', then we should use
5963 // a pre-indexed STR instruction instead, per the ARM ARM.
5964 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5965 Inst.getNumOperands() == 5) {
5966 MCInst TmpInst;
5967 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5968 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5969 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5970 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5971 TmpInst.addOperand(MCOperand::CreateImm(-4));
5972 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5973 TmpInst.addOperand(Inst.getOperand(3));
5974 Inst = TmpInst;
5975 }
5976 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005977 case ARM::t2ADDri12:
5978 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5979 // mnemonic was used (not "addw"), encoding T3 is preferred.
5980 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5981 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5982 break;
5983 Inst.setOpcode(ARM::t2ADDri);
5984 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5985 break;
5986 case ARM::t2SUBri12:
5987 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5988 // mnemonic was used (not "subw"), encoding T3 is preferred.
5989 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5990 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5991 break;
5992 Inst.setOpcode(ARM::t2SUBri);
5993 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5994 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005995 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005996 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5997 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5998 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5999 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006000 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006001 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006002 return true;
6003 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006004 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006005 case ARM::tSUBi8:
6006 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6007 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6008 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6009 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006010 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006011 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006012 return true;
6013 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006014 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006015 case ARM::t2ADDrr: {
6016 // If the destination and first source operand are the same, and
6017 // there's no setting of the flags, use encoding T2 instead of T3.
6018 // Note that this is only for ADD, not SUB. This mirrors the system
6019 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6020 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6021 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006022 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6023 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006024 break;
6025 MCInst TmpInst;
6026 TmpInst.setOpcode(ARM::tADDhirr);
6027 TmpInst.addOperand(Inst.getOperand(0));
6028 TmpInst.addOperand(Inst.getOperand(0));
6029 TmpInst.addOperand(Inst.getOperand(2));
6030 TmpInst.addOperand(Inst.getOperand(3));
6031 TmpInst.addOperand(Inst.getOperand(4));
6032 Inst = TmpInst;
6033 return true;
6034 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006035 case ARM::tB:
6036 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006037 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006038 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006039 return true;
6040 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006041 break;
6042 case ARM::t2B:
6043 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006044 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006045 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006046 return true;
6047 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006048 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006049 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006050 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006051 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006052 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006053 return true;
6054 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006055 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006056 case ARM::tBcc:
6057 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006058 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006059 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006060 return true;
6061 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006062 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006063 case ARM::tLDMIA: {
6064 // If the register list contains any high registers, or if the writeback
6065 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6066 // instead if we're in Thumb2. Otherwise, this should have generated
6067 // an error in validateInstruction().
6068 unsigned Rn = Inst.getOperand(0).getReg();
6069 bool hasWritebackToken =
6070 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6071 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6072 bool listContainsBase;
6073 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6074 (!listContainsBase && !hasWritebackToken) ||
6075 (listContainsBase && hasWritebackToken)) {
6076 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6077 assert (isThumbTwo());
6078 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6079 // If we're switching to the updating version, we need to insert
6080 // the writeback tied operand.
6081 if (hasWritebackToken)
6082 Inst.insert(Inst.begin(),
6083 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006084 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006085 }
6086 break;
6087 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006088 case ARM::tSTMIA_UPD: {
6089 // If the register list contains any high registers, we need to use
6090 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6091 // should have generated an error in validateInstruction().
6092 unsigned Rn = Inst.getOperand(0).getReg();
6093 bool listContainsBase;
6094 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6095 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6096 assert (isThumbTwo());
6097 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006098 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006099 }
6100 break;
6101 }
Jim Grosbach54026372011-11-10 23:17:11 +00006102 case ARM::tPOP: {
6103 bool listContainsBase;
6104 // If the register list contains any high registers, we need to use
6105 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6106 // should have generated an error in validateInstruction().
6107 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006108 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006109 assert (isThumbTwo());
6110 Inst.setOpcode(ARM::t2LDMIA_UPD);
6111 // Add the base register and writeback operands.
6112 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6113 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006114 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006115 }
6116 case ARM::tPUSH: {
6117 bool listContainsBase;
6118 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006119 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006120 assert (isThumbTwo());
6121 Inst.setOpcode(ARM::t2STMDB_UPD);
6122 // Add the base register and writeback operands.
6123 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6124 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006125 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006126 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006127 case ARM::t2MOVi: {
6128 // If we can use the 16-bit encoding and the user didn't explicitly
6129 // request the 32-bit variant, transform it here.
6130 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6131 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006132 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6133 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6134 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006135 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6136 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6137 // The operands aren't in the same order for tMOVi8...
6138 MCInst TmpInst;
6139 TmpInst.setOpcode(ARM::tMOVi8);
6140 TmpInst.addOperand(Inst.getOperand(0));
6141 TmpInst.addOperand(Inst.getOperand(4));
6142 TmpInst.addOperand(Inst.getOperand(1));
6143 TmpInst.addOperand(Inst.getOperand(2));
6144 TmpInst.addOperand(Inst.getOperand(3));
6145 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006146 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006147 }
6148 break;
6149 }
6150 case ARM::t2MOVr: {
6151 // If we can use the 16-bit encoding and the user didn't explicitly
6152 // request the 32-bit variant, transform it here.
6153 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6154 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6155 Inst.getOperand(2).getImm() == ARMCC::AL &&
6156 Inst.getOperand(4).getReg() == ARM::CPSR &&
6157 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6158 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6159 // The operands aren't the same for tMOV[S]r... (no cc_out)
6160 MCInst TmpInst;
6161 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6162 TmpInst.addOperand(Inst.getOperand(0));
6163 TmpInst.addOperand(Inst.getOperand(1));
6164 TmpInst.addOperand(Inst.getOperand(2));
6165 TmpInst.addOperand(Inst.getOperand(3));
6166 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006167 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006168 }
6169 break;
6170 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006171 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006172 case ARM::t2SXTB:
6173 case ARM::t2UXTH:
6174 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006175 // If we can use the 16-bit encoding and the user didn't explicitly
6176 // request the 32-bit variant, transform it here.
6177 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6178 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6179 Inst.getOperand(2).getImm() == 0 &&
6180 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6181 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006182 unsigned NewOpc;
6183 switch (Inst.getOpcode()) {
6184 default: llvm_unreachable("Illegal opcode!");
6185 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6186 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6187 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6188 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6189 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006190 // The operands aren't the same for thumb1 (no rotate operand).
6191 MCInst TmpInst;
6192 TmpInst.setOpcode(NewOpc);
6193 TmpInst.addOperand(Inst.getOperand(0));
6194 TmpInst.addOperand(Inst.getOperand(1));
6195 TmpInst.addOperand(Inst.getOperand(3));
6196 TmpInst.addOperand(Inst.getOperand(4));
6197 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006198 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006199 }
6200 break;
6201 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006202 case ARM::MOVsi: {
6203 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6204 if (SOpc == ARM_AM::rrx) return false;
6205 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6206 // Shifting by zero is accepted as a vanilla 'MOVr'
6207 MCInst TmpInst;
6208 TmpInst.setOpcode(ARM::MOVr);
6209 TmpInst.addOperand(Inst.getOperand(0));
6210 TmpInst.addOperand(Inst.getOperand(1));
6211 TmpInst.addOperand(Inst.getOperand(3));
6212 TmpInst.addOperand(Inst.getOperand(4));
6213 TmpInst.addOperand(Inst.getOperand(5));
6214 Inst = TmpInst;
6215 return true;
6216 }
6217 return false;
6218 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006219 case ARM::ANDrsi:
6220 case ARM::ORRrsi:
6221 case ARM::EORrsi:
6222 case ARM::BICrsi:
6223 case ARM::SUBrsi:
6224 case ARM::ADDrsi: {
6225 unsigned newOpc;
6226 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6227 if (SOpc == ARM_AM::rrx) return false;
6228 switch (Inst.getOpcode()) {
Matt Beaumont-Gay19055cc2012-01-03 19:03:59 +00006229 default: assert(0 && "unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006230 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6231 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6232 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6233 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6234 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6235 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6236 }
6237 // If the shift is by zero, use the non-shifted instruction definition.
6238 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6239 MCInst TmpInst;
6240 TmpInst.setOpcode(newOpc);
6241 TmpInst.addOperand(Inst.getOperand(0));
6242 TmpInst.addOperand(Inst.getOperand(1));
6243 TmpInst.addOperand(Inst.getOperand(2));
6244 TmpInst.addOperand(Inst.getOperand(4));
6245 TmpInst.addOperand(Inst.getOperand(5));
6246 TmpInst.addOperand(Inst.getOperand(6));
6247 Inst = TmpInst;
6248 return true;
6249 }
6250 return false;
6251 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006252 case ARM::t2IT: {
6253 // The mask bits for all but the first condition are represented as
6254 // the low bit of the condition code value implies 't'. We currently
6255 // always have 1 implies 't', so XOR toggle the bits if the low bit
6256 // of the condition code is zero. The encoding also expects the low
6257 // bit of the condition to be encoded as bit 4 of the mask operand,
6258 // so mask that in if needed
6259 MCOperand &MO = Inst.getOperand(1);
6260 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006261 unsigned OrigMask = Mask;
6262 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006263 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006264 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6265 for (unsigned i = 3; i != TZ; --i)
6266 Mask ^= 1 << i;
6267 } else
6268 Mask |= 0x10;
6269 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006270
6271 // Set up the IT block state according to the IT instruction we just
6272 // matched.
6273 assert(!inITBlock() && "nested IT blocks?!");
6274 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6275 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6276 ITState.CurPosition = 0;
6277 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006278 break;
6279 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006280 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006281 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006282}
6283
Jim Grosbach47a0d522011-08-16 20:45:50 +00006284unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6285 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6286 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006287 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006288 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006289 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6290 assert(MCID.hasOptionalDef() &&
6291 "optionally flag setting instruction missing optional def operand");
6292 assert(MCID.NumOperands == Inst.getNumOperands() &&
6293 "operand count mismatch!");
6294 // Find the optional-def operand (cc_out).
6295 unsigned OpNo;
6296 for (OpNo = 0;
6297 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6298 ++OpNo)
6299 ;
6300 // If we're parsing Thumb1, reject it completely.
6301 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6302 return Match_MnemonicFail;
6303 // If we're parsing Thumb2, which form is legal depends on whether we're
6304 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006305 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6306 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006307 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006308 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6309 inITBlock())
6310 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006311 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006312 // Some high-register supporting Thumb1 encodings only allow both registers
6313 // to be from r0-r7 when in Thumb2.
6314 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6315 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6316 isARMLowRegister(Inst.getOperand(2).getReg()))
6317 return Match_RequiresThumb2;
6318 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006319 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006320 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6321 isARMLowRegister(Inst.getOperand(1).getReg()))
6322 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006323 return Match_Success;
6324}
6325
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006326bool ARMAsmParser::
6327MatchAndEmitInstruction(SMLoc IDLoc,
6328 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6329 MCStreamer &Out) {
6330 MCInst Inst;
6331 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006332 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006333 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006334 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006335 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006336 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006337 // Context sensitive operand constraints aren't handled by the matcher,
6338 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006339 if (validateInstruction(Inst, Operands)) {
6340 // Still progress the IT block, otherwise one wrong condition causes
6341 // nasty cascading errors.
6342 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006343 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006344 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006345
Jim Grosbachf8fce712011-08-11 17:35:48 +00006346 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006347 // encoding is selected. Loop on it while changes happen so the
6348 // individual transformations can chain off each other. E.g.,
6349 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6350 while (processInstruction(Inst, Operands))
6351 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006352
Jim Grosbacha1109882011-09-02 23:22:08 +00006353 // Only move forward at the very end so that everything in validate
6354 // and process gets a consistent answer about whether we're in an IT
6355 // block.
6356 forwardITPosition();
6357
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006358 Out.EmitInstruction(Inst);
6359 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006360 case Match_MissingFeature:
6361 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6362 return true;
6363 case Match_InvalidOperand: {
6364 SMLoc ErrorLoc = IDLoc;
6365 if (ErrorInfo != ~0U) {
6366 if (ErrorInfo >= Operands.size())
6367 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006368
Chris Lattnere73d4f82010-10-28 21:41:58 +00006369 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6370 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6371 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006372
Chris Lattnere73d4f82010-10-28 21:41:58 +00006373 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006374 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006375 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006376 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006377 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006378 // The converter function will have already emited a diagnostic.
6379 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006380 case Match_RequiresNotITBlock:
6381 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006382 case Match_RequiresITBlock:
6383 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006384 case Match_RequiresV6:
6385 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6386 case Match_RequiresThumb2:
6387 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006388 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006389
Eric Christopherc223e2b2010-10-29 09:26:59 +00006390 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006391 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006392}
6393
Jim Grosbach1355cf12011-07-26 17:10:22 +00006394/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006395bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6396 StringRef IDVal = DirectiveID.getIdentifier();
6397 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006398 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006399 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006400 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006401 else if (IDVal == ".arm")
6402 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006403 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006404 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006405 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006406 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006407 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006408 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006409 else if (IDVal == ".unreq")
6410 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006411 else if (IDVal == ".arch")
6412 return parseDirectiveArch(DirectiveID.getLoc());
6413 else if (IDVal == ".eabi_attribute")
6414 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006415 return true;
6416}
6417
Jim Grosbach1355cf12011-07-26 17:10:22 +00006418/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006419/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006420bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6422 for (;;) {
6423 const MCExpr *Value;
6424 if (getParser().ParseExpression(Value))
6425 return true;
6426
Chris Lattneraaec2052010-01-19 19:46:13 +00006427 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006428
6429 if (getLexer().is(AsmToken::EndOfStatement))
6430 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006431
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006432 // FIXME: Improve diagnostic.
6433 if (getLexer().isNot(AsmToken::Comma))
6434 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006435 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006436 }
6437 }
6438
Sean Callananb9a25b72010-01-19 20:27:46 +00006439 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006440 return false;
6441}
6442
Jim Grosbach1355cf12011-07-26 17:10:22 +00006443/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006444/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006445bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006446 if (getLexer().isNot(AsmToken::EndOfStatement))
6447 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006448 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006449
Jim Grosbach9a70df92011-12-07 18:04:19 +00006450 if (!isThumb())
6451 SwitchMode();
6452 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6453 return false;
6454}
6455
6456/// parseDirectiveARM
6457/// ::= .arm
6458bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6459 if (getLexer().isNot(AsmToken::EndOfStatement))
6460 return Error(L, "unexpected token in directive");
6461 Parser.Lex();
6462
6463 if (isThumb())
6464 SwitchMode();
6465 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006466 return false;
6467}
6468
Jim Grosbach1355cf12011-07-26 17:10:22 +00006469/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006470/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006471bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006472 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6473 bool isMachO = MAI.hasSubsectionsViaSymbols();
6474 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006475 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006476
Jim Grosbachde4d8392011-12-21 22:30:16 +00006477 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006478 // ELF doesn't
6479 if (isMachO) {
6480 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006481 if (Tok.isNot(AsmToken::EndOfStatement)) {
6482 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6483 return Error(L, "unexpected token in .thumb_func directive");
6484 Name = Tok.getIdentifier();
6485 Parser.Lex(); // Consume the identifier token.
6486 needFuncName = false;
6487 }
Rafael Espindola64695402011-05-16 16:17:21 +00006488 }
6489
Jim Grosbachde4d8392011-12-21 22:30:16 +00006490 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006491 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006492
6493 // Eat the end of statement and any blank lines that follow.
6494 while (getLexer().is(AsmToken::EndOfStatement))
6495 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006496
Rafael Espindola64695402011-05-16 16:17:21 +00006497 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006498 // We really should be checking the next symbol definition even if there's
6499 // stuff in between.
6500 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006501 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006502 }
6503
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006504 // Mark symbol as a thumb symbol.
6505 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6506 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006507 return false;
6508}
6509
Jim Grosbach1355cf12011-07-26 17:10:22 +00006510/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006511/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006512bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006513 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006514 if (Tok.isNot(AsmToken::Identifier))
6515 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006516 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006517 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006518 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006519 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006520 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006521 else
6522 return Error(L, "unrecognized syntax mode in .syntax directive");
6523
6524 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006525 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006526 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006527
6528 // TODO tell the MC streamer the mode
6529 // getParser().getStreamer().Emit???();
6530 return false;
6531}
6532
Jim Grosbach1355cf12011-07-26 17:10:22 +00006533/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006534/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006535bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006536 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006537 if (Tok.isNot(AsmToken::Integer))
6538 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006539 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006540 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006541 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006542 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006543 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006544 else
6545 return Error(L, "invalid operand to .code directive");
6546
6547 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006548 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006549 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006550
Evan Cheng32869202011-07-08 22:36:29 +00006551 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006552 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006553 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006554 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006555 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006556 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006557 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006558 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006559 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006560
Kevin Enderby515d5092009-10-15 20:48:48 +00006561 return false;
6562}
6563
Jim Grosbacha39cda72011-12-14 02:16:11 +00006564/// parseDirectiveReq
6565/// ::= name .req registername
6566bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6567 Parser.Lex(); // Eat the '.req' token.
6568 unsigned Reg;
6569 SMLoc SRegLoc, ERegLoc;
6570 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6571 Parser.EatToEndOfStatement();
6572 return Error(SRegLoc, "register name expected");
6573 }
6574
6575 // Shouldn't be anything else.
6576 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6577 Parser.EatToEndOfStatement();
6578 return Error(Parser.getTok().getLoc(),
6579 "unexpected input in .req directive.");
6580 }
6581
6582 Parser.Lex(); // Consume the EndOfStatement
6583
6584 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6585 return Error(SRegLoc, "redefinition of '" + Name +
6586 "' does not match original.");
6587
6588 return false;
6589}
6590
6591/// parseDirectiveUneq
6592/// ::= .unreq registername
6593bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6594 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6595 Parser.EatToEndOfStatement();
6596 return Error(L, "unexpected input in .unreq directive.");
6597 }
6598 RegisterReqs.erase(Parser.getTok().getIdentifier());
6599 Parser.Lex(); // Eat the identifier.
6600 return false;
6601}
6602
Jason W Kimd7c9e082011-12-20 17:38:12 +00006603/// parseDirectiveArch
6604/// ::= .arch token
6605bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6606 return true;
6607}
6608
6609/// parseDirectiveEabiAttr
6610/// ::= .eabi_attribute int, int
6611bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6612 return true;
6613}
6614
Sean Callanan90b70972010-04-07 20:29:34 +00006615extern "C" void LLVMInitializeARMAsmLexer();
6616
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006617/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006618extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006619 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6620 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006621 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006622}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006623
Chris Lattner0692ee62010-09-06 19:11:01 +00006624#define GET_REGISTER_MATCHER
6625#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006626#include "ARMGenAsmMatcher.inc"