blob: 01c3c6dc5aa4d3cbb514524ffd7f669f78ce19d5 [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,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_MemBarrierOpt,
274 k_Memory,
275 k_PostIndexRegister,
276 k_MSRMask,
277 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000278 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_Register,
280 k_RegisterList,
281 k_DPRRegisterList,
282 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000283 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000284 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000285 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000286 k_ShiftedRegister,
287 k_ShiftedImmediate,
288 k_ShifterImmediate,
289 k_RotateImmediate,
290 k_BitfieldDescriptor,
291 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000292 } Kind;
293
Sean Callanan76264762010-04-02 22:27:05 +0000294 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000295 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296
297 union {
298 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000299 ARMCC::CondCodes Val;
300 } CC;
301
302 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000303 unsigned Val;
304 } Cop;
305
306 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000307 unsigned Val;
308 } CoprocOption;
309
310 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000311 unsigned Mask:4;
312 } ITMask;
313
314 struct {
315 ARM_MB::MemBOpt Val;
316 } MBOpt;
317
318 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000319 ARM_PROC::IFlags Val;
320 } IFlags;
321
322 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000323 unsigned Val;
324 } MMask;
325
326 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 const char *Data;
328 unsigned Length;
329 } Tok;
330
331 struct {
332 unsigned RegNum;
333 } Reg;
334
Jim Grosbach862019c2011-10-18 23:02:30 +0000335 // A vector register list is a sequential list of 1 to 4 registers.
336 struct {
337 unsigned RegNum;
338 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000339 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000340 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000341 } VectorList;
342
Bill Wendling8155e5b2010-11-06 22:19:43 +0000343 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000344 unsigned Val;
345 } VectorIndex;
346
347 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000348 const MCExpr *Val;
349 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000350
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000351 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000352 struct {
353 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000354 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
355 // was specified.
356 const MCConstantExpr *OffsetImm; // Offset immediate value
357 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
358 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000359 unsigned ShiftImm; // shift for OffsetReg.
360 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000361 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000362 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000363 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000364
365 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000367 bool isAdd;
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000370 } PostIdxReg;
371
372 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000373 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000374 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000375 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftReg;
380 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000381 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000382 struct {
383 ARM_AM::ShiftOpc ShiftTy;
384 unsigned SrcReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000387 struct {
388 unsigned Imm;
389 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000390 struct {
391 unsigned LSB;
392 unsigned Width;
393 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000394 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000395
Bill Wendling146018f2010-11-06 21:42:12 +0000396 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
397public:
Sean Callanan76264762010-04-02 22:27:05 +0000398 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
399 Kind = o.Kind;
400 StartLoc = o.StartLoc;
401 EndLoc = o.EndLoc;
402 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000404 CC = o.CC;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000407 ITMask = o.ITMask;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000410 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_CCOut:
413 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000414 Reg = o.Reg;
415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_RegisterList:
417 case k_DPRRegisterList:
418 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000419 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000420 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000422 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000423 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000424 VectorList = o.VectorList;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_CoprocNum:
427 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000428 Cop = o.Cop;
429 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000430 case k_CoprocOption:
431 CoprocOption = o.CoprocOption;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000434 Imm = o.Imm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000504 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach460a9052011-10-07 23:56:00 +0000508 unsigned getVectorIndex() const {
509 assert(Kind == k_VectorIndex && "Invalid access!");
510 return VectorIndex.Val;
511 }
512
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000513 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000514 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000515 return MBOpt.Val;
516 }
517
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000518 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000520 return IFlags.Val;
521 }
522
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000523 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000525 return MMask.Val;
526 }
527
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 bool isCoprocNum() const { return Kind == k_CoprocNum; }
529 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000530 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 bool isCondCode() const { return Kind == k_CondCode; }
532 bool isCCOut() const { return Kind == k_CCOut; }
533 bool isITMask() const { return Kind == k_ITCondMask; }
534 bool isITCondCode() const { return Kind == k_CondCode; }
535 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000536 bool isFPImm() const {
537 if (!isImm()) return false;
538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
539 if (!CE) return false;
540 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
541 return Val != -1;
542 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000543 bool isFBits16() const {
544 if (!isImm()) return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return Value >= 0 && Value <= 16;
549 }
550 bool isFBits32() 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 >= 1 && Value <= 32;
556 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000557 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000558 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
563 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000564 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +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 >= 0 && Value <= 1020;
570 }
571 bool isImm0_508s4() 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 <= 508;
577 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000578 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return Value >= 0 && Value < 256;
584 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000585 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 2;
591 }
592 bool isImm0_3() 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 < 4;
598 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000599 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() 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 < 16;
612 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000613 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 32;
619 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000620 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000627 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value == 8;
633 }
634 bool isImm16() 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 == 16;
640 }
641 bool isImm32() 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 == 32;
647 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000648 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 8;
654 }
655 bool isShrImm16() 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 <= 16;
661 }
662 bool isShrImm32() 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 <= 32;
668 }
669 bool isShrImm64() 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 <= 64;
675 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000676 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value < 8;
682 }
683 bool isImm1_15() 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 < 16;
689 }
690 bool isImm1_31() 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 < 32;
696 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000697 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 17;
703 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000704 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 33;
710 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000711 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +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 Grosbachfff76ee2011-07-13 20:10:10 +0000718 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 65536;
724 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000725 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 // If it's not a constant expression, it'll generate a fixup and be
729 // handled later.
730 if (!CE) return true;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 65536;
733 }
Jim Grosbached838482011-07-26 16:24:27 +0000734 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value <= 0xffffff;
740 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000741 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51: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 < 33;
747 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000748 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 32;
754 }
755 bool isPKHASRImm() 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 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000762 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return ARM_AM::getSOImmVal(Value) != -1;
768 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000769 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +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 Grosbach3bc8a3d2011-12-08 00:31:07 +0000776 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +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 Grosbach6b8f1e32011-06-27 23:54:06 +0000783 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getT2SOImmVal(Value) != -1;
789 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000790 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +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 Grosbach3bc8a3d2011-12-08 00:31:07 +0000797 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +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 Grosbachc27d4f92011-07-22 17:44:50 +0000804 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return Value == 1 || Value == 0;
810 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000811 bool isReg() const { return Kind == k_Register; }
812 bool isRegList() const { return Kind == k_RegisterList; }
813 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
814 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
815 bool isToken() const { return Kind == k_Token; }
816 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
817 bool isMemory() const { return Kind == k_Memory; }
818 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
819 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
820 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
821 bool isRotImm() const { return Kind == k_RotateImmediate; }
822 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
823 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000824 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000825 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000826 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000828 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000829 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
832 (alignOK || Memory.Alignment == 0);
833 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000834 bool isMemPCRelImm12() const {
835 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
836 return false;
837 // Base register must be PC.
838 if (Memory.BaseRegNum != ARM::PC)
839 return false;
840 // Immediate offset in range [-4095, 4095].
841 if (!Memory.OffsetImm) return true;
842 int64_t Val = Memory.OffsetImm->getValue();
843 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
844 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 bool isAlignedMemory() const {
846 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000847 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000848 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000850 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000853 if (!Memory.OffsetImm) return true;
854 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000856 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000857 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000858 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000859 // Immediate offset in range [-4095, 4095].
860 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
861 if (!CE) return false;
862 int64_t Val = CE->getValue();
863 return Val > -4096 && Val < 4096;
864 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000865 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000866 // If we have an immediate that's not a constant, treat it as a label
867 // reference needing a fixup. If it is a constant, it's something else
868 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000869 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000870 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000871 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000872 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000873 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000874 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000875 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (!Memory.OffsetImm) return true;
878 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000879 return Val > -256 && Val < 256;
880 }
881 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000882 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000884 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
886 // Immediate offset in range [-255, 255].
887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
888 if (!CE) return false;
889 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000890 // Special case, #-0 is INT32_MIN.
891 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000892 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000894 // If we have an immediate that's not a constant, treat it as a label
895 // reference needing a fixup. If it is a constant, it's something else
896 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000897 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000898 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000899 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000900 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000901 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000902 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000905 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000906 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000907 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000908 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000910 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000911 return false;
912 return true;
913 }
914 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
917 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000918 return false;
919 return true;
920 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000923 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000924 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000925 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000926 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000927 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
928 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000929 return false;
930 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000931 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000932 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000933 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000934 return false;
935 return true;
936 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000937 bool isMemThumbRR() const {
938 // Thumb reg+reg addressing is simple. Just two registers, a base and
939 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000940 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000942 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 return isARMLowRegister(Memory.BaseRegNum) &&
944 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000945 }
946 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000949 return false;
950 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000953 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
954 }
Jim Grosbach38466302011-08-19 18:55:51 +0000955 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000958 return false;
959 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000962 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
963 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000964 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000966 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000967 return false;
968 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (!Memory.OffsetImm) return true;
970 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 return Val >= 0 && Val <= 31;
972 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000973 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000974 if (!isMemory() || Memory.OffsetRegNum != 0 ||
975 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000976 return false;
977 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000978 if (!Memory.OffsetImm) return true;
979 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000981 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000982 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000983 // If we have an immediate that's not a constant, treat it as a label
984 // reference needing a fixup. If it is a constant, it's something else
985 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000986 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000987 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000988 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000989 return false;
990 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000991 if (!Memory.OffsetImm) return true;
992 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
994 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000995 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001003 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001005 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001006 // Base reg of PC isn't allowed for these encodings.
1007 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001008 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001009 if (!Memory.OffsetImm) return true;
1010 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001011 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001013 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001014 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001015 return false;
1016 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return Val >= 0 && Val < 256;
1020 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001021 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001023 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001024 // Base reg of PC isn't allowed for these encodings.
1025 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001026 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001027 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001028 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001029 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 }
1031 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001032 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001033 return false;
1034 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001035 if (!Memory.OffsetImm) return true;
1036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 return (Val >= 0 && Val < 4096);
1038 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001039 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001040 // If we have an immediate that's not a constant, treat it as a label
1041 // reference needing a fixup. If it is a constant, it's something else
1042 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001043 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001044 return true;
1045
Jim Grosbach57dcb852011-10-11 17:29:55 +00001046 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001047 return false;
1048 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001049 if (!Memory.OffsetImm) return true;
1050 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001051 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001052 }
1053 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001054 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 if (!CE) return false;
1057 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001058 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001060 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001061 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001062 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1063 if (!CE) return false;
1064 int64_t Val = CE->getValue();
1065 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1066 (Val == INT32_MIN);
1067 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001068
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 bool isMSRMask() const { return Kind == k_MSRMask; }
1070 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001071
Jim Grosbach0e387b22011-10-17 22:26:03 +00001072 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001073 bool isSingleSpacedVectorList() const {
1074 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1075 }
1076 bool isDoubleSpacedVectorList() const {
1077 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1078 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001079 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001080 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001081 return VectorList.Count == 1;
1082 }
1083
Jim Grosbach280dfad2011-10-21 18:54:25 +00001084 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001085 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001086 return VectorList.Count == 2;
1087 }
1088
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001089 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001091 return VectorList.Count == 3;
1092 }
1093
Jim Grosbachb6310312011-10-21 20:35:01 +00001094 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001096 return VectorList.Count == 4;
1097 }
1098
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001099 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isDoubleSpacedVectorList()) return false;
1101 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001102 }
1103
Jim Grosbachc387fc62012-01-23 23:20:46 +00001104 bool isVecListThreeQ() const {
1105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 3;
1107 }
1108
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001109 bool isSingleSpacedVectorAllLanes() const {
1110 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1111 }
1112 bool isDoubleSpacedVectorAllLanes() const {
1113 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1114 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001115 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001116 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001117 return VectorList.Count == 1;
1118 }
1119
Jim Grosbach13af2222011-11-30 18:21:25 +00001120 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001121 if (!isSingleSpacedVectorAllLanes()) return false;
1122 return VectorList.Count == 2;
1123 }
1124
1125 bool isVecListTwoQAllLanes() const {
1126 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001127 return VectorList.Count == 2;
1128 }
1129
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001130 bool isSingleSpacedVectorIndexed() const {
1131 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1132 }
1133 bool isDoubleSpacedVectorIndexed() const {
1134 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1135 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001136 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001137 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001138 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1139 }
1140
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001141 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001142 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001143 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1144 }
1145
1146 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001147 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001148 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1149 }
1150
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001151 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001152 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001153 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1154 }
1155
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001156 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001157 if (!isSingleSpacedVectorIndexed()) return false;
1158 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1159 }
1160
1161 bool isVecListTwoQWordIndexed() const {
1162 if (!isDoubleSpacedVectorIndexed()) return false;
1163 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1164 }
1165
1166 bool isVecListTwoQHWordIndexed() const {
1167 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001168 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1169 }
1170
1171 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001172 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001173 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1174 }
1175
Jim Grosbach3a678af2012-01-23 21:53:26 +00001176 bool isVecListThreeDByteIndexed() const {
1177 if (!isSingleSpacedVectorIndexed()) return false;
1178 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1179 }
1180
1181 bool isVecListThreeDHWordIndexed() const {
1182 if (!isSingleSpacedVectorIndexed()) return false;
1183 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1184 }
1185
1186 bool isVecListThreeQWordIndexed() const {
1187 if (!isDoubleSpacedVectorIndexed()) return false;
1188 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1189 }
1190
1191 bool isVecListThreeQHWordIndexed() const {
1192 if (!isDoubleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1194 }
1195
1196 bool isVecListThreeDWordIndexed() const {
1197 if (!isSingleSpacedVectorIndexed()) return false;
1198 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1199 }
1200
Jim Grosbach460a9052011-10-07 23:56:00 +00001201 bool isVectorIndex8() const {
1202 if (Kind != k_VectorIndex) return false;
1203 return VectorIndex.Val < 8;
1204 }
1205 bool isVectorIndex16() const {
1206 if (Kind != k_VectorIndex) return false;
1207 return VectorIndex.Val < 4;
1208 }
1209 bool isVectorIndex32() const {
1210 if (Kind != k_VectorIndex) return false;
1211 return VectorIndex.Val < 2;
1212 }
1213
Jim Grosbach0e387b22011-10-17 22:26:03 +00001214 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001215 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 // Must be a constant.
1218 if (!CE) return false;
1219 int64_t Value = CE->getValue();
1220 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1221 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001222 return Value >= 0 && Value < 256;
1223 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001224
Jim Grosbachea461102011-10-17 23:09:09 +00001225 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001226 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +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 // i16 value in the range [0,255] or [0x0100, 0xff00]
1232 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1233 }
1234
Jim Grosbach6248a542011-10-18 00:22:00 +00001235 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001236 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001237 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1238 // Must be a constant.
1239 if (!CE) return false;
1240 int64_t Value = CE->getValue();
1241 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1242 return (Value >= 0 && Value < 256) ||
1243 (Value >= 0x0100 && Value <= 0xff00) ||
1244 (Value >= 0x010000 && Value <= 0xff0000) ||
1245 (Value >= 0x01000000 && Value <= 0xff000000);
1246 }
1247
1248 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001249 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001250 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1251 // Must be a constant.
1252 if (!CE) return false;
1253 int64_t Value = CE->getValue();
1254 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1255 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1256 return (Value >= 0 && Value < 256) ||
1257 (Value >= 0x0100 && Value <= 0xff00) ||
1258 (Value >= 0x010000 && Value <= 0xff0000) ||
1259 (Value >= 0x01000000 && Value <= 0xff000000) ||
1260 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1261 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1262 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001263 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001264 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001265 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1266 // Must be a constant.
1267 if (!CE) return false;
1268 int64_t Value = ~CE->getValue();
1269 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1270 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1271 return (Value >= 0 && Value < 256) ||
1272 (Value >= 0x0100 && Value <= 0xff00) ||
1273 (Value >= 0x010000 && Value <= 0xff0000) ||
1274 (Value >= 0x01000000 && Value <= 0xff000000) ||
1275 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1276 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1277 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001278
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001279 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001280 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001281 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1282 // Must be a constant.
1283 if (!CE) return false;
1284 uint64_t Value = CE->getValue();
1285 // i64 value with each byte being either 0 or 0xff.
1286 for (unsigned i = 0; i < 8; ++i)
1287 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1288 return true;
1289 }
1290
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001291 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001292 // Add as immediates when possible. Null MCExpr = 0.
1293 if (Expr == 0)
1294 Inst.addOperand(MCOperand::CreateImm(0));
1295 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001296 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1297 else
1298 Inst.addOperand(MCOperand::CreateExpr(Expr));
1299 }
1300
Daniel Dunbar8462b302010-08-11 06:36:53 +00001301 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001302 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001303 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001304 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1305 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001306 }
1307
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001308 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1309 assert(N == 1 && "Invalid number of operands!");
1310 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1311 }
1312
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001313 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1314 assert(N == 1 && "Invalid number of operands!");
1315 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1316 }
1317
1318 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1319 assert(N == 1 && "Invalid number of operands!");
1320 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1321 }
1322
Jim Grosbach89df9962011-08-26 21:43:41 +00001323 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
1325 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1326 }
1327
1328 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
1330 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1331 }
1332
Jim Grosbachd67641b2010-12-06 18:21:12 +00001333 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1334 assert(N == 1 && "Invalid number of operands!");
1335 Inst.addOperand(MCOperand::CreateReg(getReg()));
1336 }
1337
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001338 void addRegOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 Inst.addOperand(MCOperand::CreateReg(getReg()));
1341 }
1342
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001343 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001344 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001345 assert(isRegShiftedReg() &&
1346 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001347 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1348 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001349 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001350 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001351 }
1352
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001353 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001354 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001355 assert(isRegShiftedImm() &&
1356 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001357 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001358 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001359 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001360 }
1361
Jim Grosbach580f4a92011-07-25 22:20:28 +00001362 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001363 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001364 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1365 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001366 }
1367
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001368 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001369 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001370 const SmallVectorImpl<unsigned> &RegList = getRegList();
1371 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001372 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1373 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001374 }
1375
Bill Wendling0f630752010-11-17 04:32:08 +00001376 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1377 addRegListOperands(Inst, N);
1378 }
1379
1380 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1381 addRegListOperands(Inst, N);
1382 }
1383
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001384 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1387 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1388 }
1389
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001390 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1391 assert(N == 1 && "Invalid number of operands!");
1392 // Munge the lsb/width into a bitfield mask.
1393 unsigned lsb = Bitfield.LSB;
1394 unsigned width = Bitfield.Width;
1395 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1396 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1397 (32 - (lsb + width)));
1398 Inst.addOperand(MCOperand::CreateImm(Mask));
1399 }
1400
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001401 void addImmOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 addExpr(Inst, getImm());
1404 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001405
Jim Grosbach4050bc42011-12-22 22:19:05 +00001406 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1407 assert(N == 1 && "Invalid number of operands!");
1408 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1409 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1410 }
1411
1412 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
1414 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1415 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1416 }
1417
Jim Grosbach9d390362011-10-03 23:38:36 +00001418 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1419 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001420 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1421 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1422 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001423 }
1424
Jim Grosbacha77295d2011-09-08 22:07:06 +00001425 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 // FIXME: We really want to scale the value here, but the LDRD/STRD
1428 // instruction don't encode operands that way yet.
1429 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1430 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1431 }
1432
Jim Grosbach72f39f82011-08-24 21:22:15 +00001433 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 // The immediate is scaled by four in the encoding and is stored
1436 // in the MCInst as such. Lop off the low two bits here.
1437 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1438 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1439 }
1440
1441 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 // The immediate is scaled by four in the encoding and is stored
1444 // in the MCInst as such. Lop off the low two bits here.
1445 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1446 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1447 }
1448
Jim Grosbachf4943352011-07-25 23:09:14 +00001449 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 // The constant encodes as the immediate-1, and we store in the instruction
1452 // the bits as encoded, so subtract off one here.
1453 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1454 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1455 }
1456
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001457 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1458 assert(N == 1 && "Invalid number of operands!");
1459 // The constant encodes as the immediate-1, and we store in the instruction
1460 // the bits as encoded, so subtract off one here.
1461 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1462 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1463 }
1464
Jim Grosbach70939ee2011-08-17 21:51:27 +00001465 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
1467 // The constant encodes as the immediate, except for 32, which encodes as
1468 // zero.
1469 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1470 unsigned Imm = CE->getValue();
1471 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1472 }
1473
Jim Grosbachf6c05252011-07-21 17:23:04 +00001474 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1475 assert(N == 1 && "Invalid number of operands!");
1476 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1477 // the instruction as well.
1478 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1479 int Val = CE->getValue();
1480 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1481 }
1482
Jim Grosbach89a63372011-10-28 22:36:30 +00001483 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485 // The operand is actually a t2_so_imm, but we have its bitwise
1486 // negation in the assembly source, so twiddle it here.
1487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1488 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1489 }
1490
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001491 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 // The operand is actually a t2_so_imm, but we have its
1494 // negation in the assembly source, so twiddle it here.
1495 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1496 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1497 }
1498
Jim Grosbache70ec842011-10-28 22:50:54 +00001499 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 // The operand is actually a so_imm, but we have its bitwise
1502 // negation in the assembly source, so twiddle it here.
1503 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1504 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1505 }
1506
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001507 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 // The operand is actually a so_imm, but we have its
1510 // negation in the assembly source, so twiddle it here.
1511 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1512 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1513 }
1514
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001515 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 1 && "Invalid number of operands!");
1517 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1518 }
1519
Jim Grosbach7ce05792011-08-03 23:50:40 +00001520 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001522 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001523 }
1524
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001525 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 int32_t Imm = Memory.OffsetImm->getValue();
1528 // FIXME: Handle #-0
1529 if (Imm == INT32_MIN) Imm = 0;
1530 Inst.addOperand(MCOperand::CreateImm(Imm));
1531 }
1532
Jim Grosbach57dcb852011-10-11 17:29:55 +00001533 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1534 assert(N == 2 && "Invalid number of operands!");
1535 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1536 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1537 }
1538
Jim Grosbach7ce05792011-08-03 23:50:40 +00001539 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1540 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001541 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1542 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001543 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1544 // Special case for #-0
1545 if (Val == INT32_MIN) Val = 0;
1546 if (Val < 0) Val = -Val;
1547 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1548 } else {
1549 // For register offset, we encode the shift type and negation flag
1550 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001551 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1552 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001553 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001554 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1555 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001556 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001557 }
1558
Jim Grosbach039c2e12011-08-04 23:01:30 +00001559 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1560 assert(N == 2 && "Invalid number of operands!");
1561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1562 assert(CE && "non-constant AM2OffsetImm operand!");
1563 int32_t Val = CE->getValue();
1564 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1565 // Special case for #-0
1566 if (Val == INT32_MIN) Val = 0;
1567 if (Val < 0) Val = -Val;
1568 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1569 Inst.addOperand(MCOperand::CreateReg(0));
1570 Inst.addOperand(MCOperand::CreateImm(Val));
1571 }
1572
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001573 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1574 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001575 // If we have an immediate that's not a constant, treat it as a label
1576 // reference needing a fixup. If it is a constant, it's something else
1577 // and we reject it.
1578 if (isImm()) {
1579 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1580 Inst.addOperand(MCOperand::CreateReg(0));
1581 Inst.addOperand(MCOperand::CreateImm(0));
1582 return;
1583 }
1584
Jim Grosbache53c87b2011-10-11 15:59:20 +00001585 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1586 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001587 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1588 // Special case for #-0
1589 if (Val == INT32_MIN) Val = 0;
1590 if (Val < 0) Val = -Val;
1591 Val = ARM_AM::getAM3Opc(AddSub, Val);
1592 } else {
1593 // For register offset, we encode the shift type and negation flag
1594 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001595 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001596 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001597 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1598 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001599 Inst.addOperand(MCOperand::CreateImm(Val));
1600 }
1601
1602 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1603 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001604 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001605 int32_t Val =
1606 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1607 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1608 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001609 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001610 }
1611
1612 // Constant offset.
1613 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1614 int32_t Val = CE->getValue();
1615 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1616 // Special case for #-0
1617 if (Val == INT32_MIN) Val = 0;
1618 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001619 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001620 Inst.addOperand(MCOperand::CreateReg(0));
1621 Inst.addOperand(MCOperand::CreateImm(Val));
1622 }
1623
Jim Grosbach7ce05792011-08-03 23:50:40 +00001624 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1625 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001626 // If we have an immediate that's not a constant, treat it as a label
1627 // reference needing a fixup. If it is a constant, it's something else
1628 // and we reject it.
1629 if (isImm()) {
1630 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1631 Inst.addOperand(MCOperand::CreateImm(0));
1632 return;
1633 }
1634
Jim Grosbach7ce05792011-08-03 23:50:40 +00001635 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001636 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001637 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1638 // Special case for #-0
1639 if (Val == INT32_MIN) Val = 0;
1640 if (Val < 0) Val = -Val;
1641 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001642 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001643 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001644 }
1645
Jim Grosbacha77295d2011-09-08 22:07:06 +00001646 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1647 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001648 // If we have an immediate that's not a constant, treat it as a label
1649 // reference needing a fixup. If it is a constant, it's something else
1650 // and we reject it.
1651 if (isImm()) {
1652 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1653 Inst.addOperand(MCOperand::CreateImm(0));
1654 return;
1655 }
1656
Jim Grosbache53c87b2011-10-11 15:59:20 +00001657 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1658 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001659 Inst.addOperand(MCOperand::CreateImm(Val));
1660 }
1661
Jim Grosbachb6aed502011-09-09 18:37:27 +00001662 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1663 assert(N == 2 && "Invalid number of operands!");
1664 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001665 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1666 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001667 Inst.addOperand(MCOperand::CreateImm(Val));
1668 }
1669
Jim Grosbach7ce05792011-08-03 23:50:40 +00001670 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001672 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1673 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001674 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001675 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001676
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001677 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1678 addMemImm8OffsetOperands(Inst, N);
1679 }
1680
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001681 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001682 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001683 }
1684
1685 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 2 && "Invalid number of operands!");
1687 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001688 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001689 addExpr(Inst, getImm());
1690 Inst.addOperand(MCOperand::CreateImm(0));
1691 return;
1692 }
1693
1694 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001695 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1696 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001697 Inst.addOperand(MCOperand::CreateImm(Val));
1698 }
1699
Jim Grosbach7ce05792011-08-03 23:50:40 +00001700 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1701 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001702 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001703 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001704 addExpr(Inst, getImm());
1705 Inst.addOperand(MCOperand::CreateImm(0));
1706 return;
1707 }
1708
1709 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001710 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1711 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001712 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001713 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001714
Jim Grosbach7f739be2011-09-19 22:21:13 +00001715 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001717 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1718 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001719 }
1720
1721 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1722 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001723 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1724 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001725 }
1726
Jim Grosbach7ce05792011-08-03 23:50:40 +00001727 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1728 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001729 unsigned Val =
1730 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1731 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001732 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1733 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001734 Inst.addOperand(MCOperand::CreateImm(Val));
1735 }
1736
Jim Grosbachab899c12011-09-07 23:10:15 +00001737 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1738 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001739 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1740 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1741 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001742 }
1743
Jim Grosbach7ce05792011-08-03 23:50:40 +00001744 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1745 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001746 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1747 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001748 }
1749
Jim Grosbach60f91a32011-08-19 17:55:24 +00001750 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1751 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001752 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1753 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001754 Inst.addOperand(MCOperand::CreateImm(Val));
1755 }
1756
Jim Grosbach38466302011-08-19 18:55:51 +00001757 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1758 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001759 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1760 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001761 Inst.addOperand(MCOperand::CreateImm(Val));
1762 }
1763
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001764 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1765 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001766 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1767 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001768 Inst.addOperand(MCOperand::CreateImm(Val));
1769 }
1770
Jim Grosbachecd85892011-08-19 18:13:48 +00001771 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1772 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001773 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1774 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001775 Inst.addOperand(MCOperand::CreateImm(Val));
1776 }
1777
Jim Grosbach7ce05792011-08-03 23:50:40 +00001778 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1779 assert(N == 1 && "Invalid number of operands!");
1780 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1781 assert(CE && "non-constant post-idx-imm8 operand!");
1782 int Imm = CE->getValue();
1783 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001784 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001785 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1786 Inst.addOperand(MCOperand::CreateImm(Imm));
1787 }
1788
Jim Grosbach2bd01182011-10-11 21:55:36 +00001789 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1790 assert(N == 1 && "Invalid number of operands!");
1791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1792 assert(CE && "non-constant post-idx-imm8s4 operand!");
1793 int Imm = CE->getValue();
1794 bool isAdd = Imm >= 0;
1795 if (Imm == INT32_MIN) Imm = 0;
1796 // Immediate is scaled by 4.
1797 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1798 Inst.addOperand(MCOperand::CreateImm(Imm));
1799 }
1800
Jim Grosbach7ce05792011-08-03 23:50:40 +00001801 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1802 assert(N == 2 && "Invalid number of operands!");
1803 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001804 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1805 }
1806
1807 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1808 assert(N == 2 && "Invalid number of operands!");
1809 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1810 // The sign, shift type, and shift amount are encoded in a single operand
1811 // using the AM2 encoding helpers.
1812 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1813 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1814 PostIdxReg.ShiftTy);
1815 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001816 }
1817
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001818 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1819 assert(N == 1 && "Invalid number of operands!");
1820 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1821 }
1822
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001823 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1824 assert(N == 1 && "Invalid number of operands!");
1825 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1826 }
1827
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001828 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001829 assert(N == 1 && "Invalid number of operands!");
1830 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1831 }
1832
Jim Grosbach7636bf62011-12-02 00:35:16 +00001833 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1834 assert(N == 2 && "Invalid number of operands!");
1835 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1836 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1837 }
1838
Jim Grosbach460a9052011-10-07 23:56:00 +00001839 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1840 assert(N == 1 && "Invalid number of operands!");
1841 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1842 }
1843
1844 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1845 assert(N == 1 && "Invalid number of operands!");
1846 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1847 }
1848
1849 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1850 assert(N == 1 && "Invalid number of operands!");
1851 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1852 }
1853
Jim Grosbach0e387b22011-10-17 22:26:03 +00001854 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1855 assert(N == 1 && "Invalid number of operands!");
1856 // The immediate encodes the type of constant as well as the value.
1857 // Mask in that this is an i8 splat.
1858 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1859 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1860 }
1861
Jim Grosbachea461102011-10-17 23:09:09 +00001862 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1863 assert(N == 1 && "Invalid number of operands!");
1864 // The immediate encodes the type of constant as well as the value.
1865 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1866 unsigned Value = CE->getValue();
1867 if (Value >= 256)
1868 Value = (Value >> 8) | 0xa00;
1869 else
1870 Value |= 0x800;
1871 Inst.addOperand(MCOperand::CreateImm(Value));
1872 }
1873
Jim Grosbach6248a542011-10-18 00:22:00 +00001874 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1875 assert(N == 1 && "Invalid number of operands!");
1876 // The immediate encodes the type of constant as well as the value.
1877 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1878 unsigned Value = CE->getValue();
1879 if (Value >= 256 && Value <= 0xff00)
1880 Value = (Value >> 8) | 0x200;
1881 else if (Value > 0xffff && Value <= 0xff0000)
1882 Value = (Value >> 16) | 0x400;
1883 else if (Value > 0xffffff)
1884 Value = (Value >> 24) | 0x600;
1885 Inst.addOperand(MCOperand::CreateImm(Value));
1886 }
1887
1888 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1889 assert(N == 1 && "Invalid number of operands!");
1890 // The immediate encodes the type of constant as well as the value.
1891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1892 unsigned Value = CE->getValue();
1893 if (Value >= 256 && Value <= 0xffff)
1894 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1895 else if (Value > 0xffff && Value <= 0xffffff)
1896 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1897 else if (Value > 0xffffff)
1898 Value = (Value >> 24) | 0x600;
1899 Inst.addOperand(MCOperand::CreateImm(Value));
1900 }
1901
Jim Grosbach9b087852011-12-19 23:51:07 +00001902 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1903 assert(N == 1 && "Invalid number of operands!");
1904 // The immediate encodes the type of constant as well as the value.
1905 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1906 unsigned Value = ~CE->getValue();
1907 if (Value >= 256 && Value <= 0xffff)
1908 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1909 else if (Value > 0xffff && Value <= 0xffffff)
1910 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1911 else if (Value > 0xffffff)
1912 Value = (Value >> 24) | 0x600;
1913 Inst.addOperand(MCOperand::CreateImm(Value));
1914 }
1915
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001916 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1917 assert(N == 1 && "Invalid number of operands!");
1918 // The immediate encodes the type of constant as well as the value.
1919 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1920 uint64_t Value = CE->getValue();
1921 unsigned Imm = 0;
1922 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1923 Imm |= (Value & 1) << i;
1924 }
1925 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1926 }
1927
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001928 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001929
Jim Grosbach89df9962011-08-26 21:43:41 +00001930 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001932 Op->ITMask.Mask = Mask;
1933 Op->StartLoc = S;
1934 Op->EndLoc = S;
1935 return Op;
1936 }
1937
Chris Lattner3a697562010-10-28 17:20:03 +00001938 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001939 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001940 Op->CC.Val = CC;
1941 Op->StartLoc = S;
1942 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001943 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001944 }
1945
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001946 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001947 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001948 Op->Cop.Val = CopVal;
1949 Op->StartLoc = S;
1950 Op->EndLoc = S;
1951 return Op;
1952 }
1953
1954 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001955 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001956 Op->Cop.Val = CopVal;
1957 Op->StartLoc = S;
1958 Op->EndLoc = S;
1959 return Op;
1960 }
1961
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001962 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1963 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1964 Op->Cop.Val = Val;
1965 Op->StartLoc = S;
1966 Op->EndLoc = E;
1967 return Op;
1968 }
1969
Jim Grosbachd67641b2010-12-06 18:21:12 +00001970 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001971 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001972 Op->Reg.RegNum = RegNum;
1973 Op->StartLoc = S;
1974 Op->EndLoc = S;
1975 return Op;
1976 }
1977
Chris Lattner3a697562010-10-28 17:20:03 +00001978 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001979 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001980 Op->Tok.Data = Str.data();
1981 Op->Tok.Length = Str.size();
1982 Op->StartLoc = S;
1983 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001984 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001985 }
1986
Bill Wendling50d0f582010-11-18 23:43:05 +00001987 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001989 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001990 Op->StartLoc = S;
1991 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001992 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001993 }
1994
Jim Grosbache8606dc2011-07-13 17:50:29 +00001995 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1996 unsigned SrcReg,
1997 unsigned ShiftReg,
1998 unsigned ShiftImm,
1999 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002000 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002001 Op->RegShiftedReg.ShiftTy = ShTy;
2002 Op->RegShiftedReg.SrcReg = SrcReg;
2003 Op->RegShiftedReg.ShiftReg = ShiftReg;
2004 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002005 Op->StartLoc = S;
2006 Op->EndLoc = E;
2007 return Op;
2008 }
2009
Owen Anderson92a20222011-07-21 18:54:16 +00002010 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2011 unsigned SrcReg,
2012 unsigned ShiftImm,
2013 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002014 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002015 Op->RegShiftedImm.ShiftTy = ShTy;
2016 Op->RegShiftedImm.SrcReg = SrcReg;
2017 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002018 Op->StartLoc = S;
2019 Op->EndLoc = E;
2020 return Op;
2021 }
2022
Jim Grosbach580f4a92011-07-25 22:20:28 +00002023 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002024 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002025 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002026 Op->ShifterImm.isASR = isASR;
2027 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002028 Op->StartLoc = S;
2029 Op->EndLoc = E;
2030 return Op;
2031 }
2032
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002033 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002034 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002035 Op->RotImm.Imm = Imm;
2036 Op->StartLoc = S;
2037 Op->EndLoc = E;
2038 return Op;
2039 }
2040
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002041 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2042 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002043 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002044 Op->Bitfield.LSB = LSB;
2045 Op->Bitfield.Width = Width;
2046 Op->StartLoc = S;
2047 Op->EndLoc = E;
2048 return Op;
2049 }
2050
Bill Wendling7729e062010-11-09 22:44:22 +00002051 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002052 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002053 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002054 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002055
Jim Grosbachd300b942011-09-13 22:56:44 +00002056 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002057 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002058 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002059 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002060 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002061
2062 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002063 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002064 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002065 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002066 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002067 Op->StartLoc = StartLoc;
2068 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002069 return Op;
2070 }
2071
Jim Grosbach862019c2011-10-18 23:02:30 +00002072 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002073 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002074 ARMOperand *Op = new ARMOperand(k_VectorList);
2075 Op->VectorList.RegNum = RegNum;
2076 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002077 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002078 Op->StartLoc = S;
2079 Op->EndLoc = E;
2080 return Op;
2081 }
2082
Jim Grosbach98b05a52011-11-30 01:09:44 +00002083 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002084 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002085 SMLoc S, SMLoc E) {
2086 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2087 Op->VectorList.RegNum = RegNum;
2088 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002089 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002090 Op->StartLoc = S;
2091 Op->EndLoc = E;
2092 return Op;
2093 }
2094
Jim Grosbach7636bf62011-12-02 00:35:16 +00002095 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002096 unsigned Index,
2097 bool isDoubleSpaced,
2098 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002099 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2100 Op->VectorList.RegNum = RegNum;
2101 Op->VectorList.Count = Count;
2102 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002103 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002104 Op->StartLoc = S;
2105 Op->EndLoc = E;
2106 return Op;
2107 }
2108
Jim Grosbach460a9052011-10-07 23:56:00 +00002109 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2110 MCContext &Ctx) {
2111 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2112 Op->VectorIndex.Val = Idx;
2113 Op->StartLoc = S;
2114 Op->EndLoc = E;
2115 return Op;
2116 }
2117
Chris Lattner3a697562010-10-28 17:20:03 +00002118 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002119 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002120 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002121 Op->StartLoc = S;
2122 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002123 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002124 }
2125
Jim Grosbach7ce05792011-08-03 23:50:40 +00002126 static ARMOperand *CreateMem(unsigned BaseRegNum,
2127 const MCConstantExpr *OffsetImm,
2128 unsigned OffsetRegNum,
2129 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002130 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002131 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002132 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002133 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002134 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002135 Op->Memory.BaseRegNum = BaseRegNum;
2136 Op->Memory.OffsetImm = OffsetImm;
2137 Op->Memory.OffsetRegNum = OffsetRegNum;
2138 Op->Memory.ShiftType = ShiftType;
2139 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002140 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002141 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002142 Op->StartLoc = S;
2143 Op->EndLoc = E;
2144 return Op;
2145 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002146
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002147 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2148 ARM_AM::ShiftOpc ShiftTy,
2149 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002150 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002151 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002152 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002153 Op->PostIdxReg.isAdd = isAdd;
2154 Op->PostIdxReg.ShiftTy = ShiftTy;
2155 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002156 Op->StartLoc = S;
2157 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002158 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002159 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002160
2161 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002162 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002163 Op->MBOpt.Val = Opt;
2164 Op->StartLoc = S;
2165 Op->EndLoc = S;
2166 return Op;
2167 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002168
2169 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002170 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002171 Op->IFlags.Val = IFlags;
2172 Op->StartLoc = S;
2173 Op->EndLoc = S;
2174 return Op;
2175 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002176
2177 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002178 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002179 Op->MMask.Val = MMask;
2180 Op->StartLoc = S;
2181 Op->EndLoc = S;
2182 return Op;
2183 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002184};
2185
2186} // end anonymous namespace.
2187
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002188void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002189 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002190 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002191 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002192 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002193 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002194 OS << "<ccout " << getReg() << ">";
2195 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002196 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002197 static const char *MaskStr[] = {
2198 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2199 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2200 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002201 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2202 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2203 break;
2204 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002205 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002206 OS << "<coprocessor number: " << getCoproc() << ">";
2207 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002208 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002209 OS << "<coprocessor register: " << getCoproc() << ">";
2210 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002211 case k_CoprocOption:
2212 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2213 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002214 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002215 OS << "<mask: " << getMSRMask() << ">";
2216 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002217 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002218 getImm()->print(OS);
2219 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002220 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002221 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2222 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002223 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002224 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002225 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002226 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002227 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002229 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2230 << PostIdxReg.RegNum;
2231 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2232 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2233 << PostIdxReg.ShiftImm;
2234 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002235 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002236 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002237 OS << "<ARM_PROC::";
2238 unsigned IFlags = getProcIFlags();
2239 for (int i=2; i >= 0; --i)
2240 if (IFlags & (1 << i))
2241 OS << ARM_PROC::IFlagsToString(1 << i);
2242 OS << ">";
2243 break;
2244 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002245 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002246 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002247 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002248 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002249 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2250 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002251 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002252 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002253 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002254 << RegShiftedReg.SrcReg << " "
2255 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2256 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002257 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002258 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002259 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002260 << RegShiftedImm.SrcReg << " "
2261 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2262 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002263 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002264 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002265 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2266 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002267 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002268 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2269 << ", width: " << Bitfield.Width << ">";
2270 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002271 case k_RegisterList:
2272 case k_DPRRegisterList:
2273 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002274 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002275
Bill Wendling5fa22a12010-11-09 23:28:44 +00002276 const SmallVectorImpl<unsigned> &RegList = getRegList();
2277 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002278 I = RegList.begin(), E = RegList.end(); I != E; ) {
2279 OS << *I;
2280 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002281 }
2282
2283 OS << ">";
2284 break;
2285 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002286 case k_VectorList:
2287 OS << "<vector_list " << VectorList.Count << " * "
2288 << VectorList.RegNum << ">";
2289 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002290 case k_VectorListAllLanes:
2291 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2292 << VectorList.RegNum << ">";
2293 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002294 case k_VectorListIndexed:
2295 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2296 << VectorList.Count << " * " << VectorList.RegNum << ">";
2297 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002298 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002299 OS << "'" << getToken() << "'";
2300 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002301 case k_VectorIndex:
2302 OS << "<vectorindex " << getVectorIndex() << ">";
2303 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002304 }
2305}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002306
2307/// @name Auto-generated Match Functions
2308/// {
2309
2310static unsigned MatchRegisterName(StringRef Name);
2311
2312/// }
2313
Bob Wilson69df7232011-02-03 21:46:10 +00002314bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2315 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002316 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002317 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002318 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002319
2320 return (RegNo == (unsigned)-1);
2321}
2322
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002323/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002324/// and if it is a register name the token is eaten and the register number is
2325/// returned. Otherwise return -1.
2326///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002327int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002328 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002329 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002330
Benjamin Kramer59085362011-11-06 20:37:06 +00002331 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002332 unsigned RegNum = MatchRegisterName(lowerCase);
2333 if (!RegNum) {
2334 RegNum = StringSwitch<unsigned>(lowerCase)
2335 .Case("r13", ARM::SP)
2336 .Case("r14", ARM::LR)
2337 .Case("r15", ARM::PC)
2338 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002339 // Additional register name aliases for 'gas' compatibility.
2340 .Case("a1", ARM::R0)
2341 .Case("a2", ARM::R1)
2342 .Case("a3", ARM::R2)
2343 .Case("a4", ARM::R3)
2344 .Case("v1", ARM::R4)
2345 .Case("v2", ARM::R5)
2346 .Case("v3", ARM::R6)
2347 .Case("v4", ARM::R7)
2348 .Case("v5", ARM::R8)
2349 .Case("v6", ARM::R9)
2350 .Case("v7", ARM::R10)
2351 .Case("v8", ARM::R11)
2352 .Case("sb", ARM::R9)
2353 .Case("sl", ARM::R10)
2354 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002355 .Default(0);
2356 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002357 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002358 // Check for aliases registered via .req. Canonicalize to lower case.
2359 // That's more consistent since register names are case insensitive, and
2360 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2361 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002362 // If no match, return failure.
2363 if (Entry == RegisterReqs.end())
2364 return -1;
2365 Parser.Lex(); // Eat identifier token.
2366 return Entry->getValue();
2367 }
Bob Wilson69df7232011-02-03 21:46:10 +00002368
Chris Lattnere5658fa2010-10-30 04:09:10 +00002369 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002370
Chris Lattnere5658fa2010-10-30 04:09:10 +00002371 return RegNum;
2372}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002373
Jim Grosbach19906722011-07-13 18:49:30 +00002374// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2375// If a recoverable error occurs, return 1. If an irrecoverable error
2376// occurs, return -1. An irrecoverable error is one where tokens have been
2377// consumed in the process of trying to parse the shifter (i.e., when it is
2378// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002379int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002380 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2381 SMLoc S = Parser.getTok().getLoc();
2382 const AsmToken &Tok = Parser.getTok();
2383 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2384
Benjamin Kramer59085362011-11-06 20:37:06 +00002385 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002386 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002387 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002388 .Case("lsl", ARM_AM::lsl)
2389 .Case("lsr", ARM_AM::lsr)
2390 .Case("asr", ARM_AM::asr)
2391 .Case("ror", ARM_AM::ror)
2392 .Case("rrx", ARM_AM::rrx)
2393 .Default(ARM_AM::no_shift);
2394
2395 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002396 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002397
Jim Grosbache8606dc2011-07-13 17:50:29 +00002398 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002399
Jim Grosbache8606dc2011-07-13 17:50:29 +00002400 // The source register for the shift has already been added to the
2401 // operand list, so we need to pop it off and combine it into the shifted
2402 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002403 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002404 if (!PrevOp->isReg())
2405 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2406 int SrcReg = PrevOp->getReg();
2407 int64_t Imm = 0;
2408 int ShiftReg = 0;
2409 if (ShiftTy == ARM_AM::rrx) {
2410 // RRX Doesn't have an explicit shift amount. The encoder expects
2411 // the shift register to be the same as the source register. Seems odd,
2412 // but OK.
2413 ShiftReg = SrcReg;
2414 } else {
2415 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002416 if (Parser.getTok().is(AsmToken::Hash) ||
2417 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002418 Parser.Lex(); // Eat hash.
2419 SMLoc ImmLoc = Parser.getTok().getLoc();
2420 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002421 if (getParser().ParseExpression(ShiftExpr)) {
2422 Error(ImmLoc, "invalid immediate shift value");
2423 return -1;
2424 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002425 // The expression must be evaluatable as an immediate.
2426 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002427 if (!CE) {
2428 Error(ImmLoc, "invalid immediate shift value");
2429 return -1;
2430 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002431 // Range check the immediate.
2432 // lsl, ror: 0 <= imm <= 31
2433 // lsr, asr: 0 <= imm <= 32
2434 Imm = CE->getValue();
2435 if (Imm < 0 ||
2436 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2437 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002438 Error(ImmLoc, "immediate shift value out of range");
2439 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002440 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002441 // shift by zero is a nop. Always send it through as lsl.
2442 // ('as' compatibility)
2443 if (Imm == 0)
2444 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002445 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002446 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002447 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002448 if (ShiftReg == -1) {
2449 Error (L, "expected immediate or register in shift operand");
2450 return -1;
2451 }
2452 } else {
2453 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002454 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002455 return -1;
2456 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002457 }
2458
Owen Anderson92a20222011-07-21 18:54:16 +00002459 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2460 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002461 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002462 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002463 else
2464 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2465 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002466
Jim Grosbach19906722011-07-13 18:49:30 +00002467 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002468}
2469
2470
Bill Wendling50d0f582010-11-18 23:43:05 +00002471/// Try to parse a register name. The token must be an Identifier when called.
2472/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2473/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002474///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002475/// TODO this is likely to change to allow different register types and or to
2476/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002477bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002478tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002479 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002480 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002481 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002482 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002483
Bill Wendling50d0f582010-11-18 23:43:05 +00002484 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002485
Chris Lattnere5658fa2010-10-30 04:09:10 +00002486 const AsmToken &ExclaimTok = Parser.getTok();
2487 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002488 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2489 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002490 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002491 return false;
2492 }
2493
2494 // Also check for an index operand. This is only legal for vector registers,
2495 // but that'll get caught OK in operand matching, so we don't need to
2496 // explicitly filter everything else out here.
2497 if (Parser.getTok().is(AsmToken::LBrac)) {
2498 SMLoc SIdx = Parser.getTok().getLoc();
2499 Parser.Lex(); // Eat left bracket token.
2500
2501 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002502 if (getParser().ParseExpression(ImmVal))
2503 return MatchOperand_ParseFail;
2504 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2505 if (!MCE) {
2506 TokError("immediate value expected for vector index");
2507 return MatchOperand_ParseFail;
2508 }
2509
2510 SMLoc E = Parser.getTok().getLoc();
2511 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2512 Error(E, "']' expected");
2513 return MatchOperand_ParseFail;
2514 }
2515
2516 Parser.Lex(); // Eat right bracket token.
2517
2518 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2519 SIdx, E,
2520 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002521 }
2522
Bill Wendling50d0f582010-11-18 23:43:05 +00002523 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002524}
2525
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002526/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2527/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2528/// "c5", ...
2529static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002530 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2531 // but efficient.
2532 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002533 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002534 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002535 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002536 return -1;
2537 switch (Name[1]) {
2538 default: return -1;
2539 case '0': return 0;
2540 case '1': return 1;
2541 case '2': return 2;
2542 case '3': return 3;
2543 case '4': return 4;
2544 case '5': return 5;
2545 case '6': return 6;
2546 case '7': return 7;
2547 case '8': return 8;
2548 case '9': return 9;
2549 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002550 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002551 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002552 return -1;
2553 switch (Name[2]) {
2554 default: return -1;
2555 case '0': return 10;
2556 case '1': return 11;
2557 case '2': return 12;
2558 case '3': return 13;
2559 case '4': return 14;
2560 case '5': return 15;
2561 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002562 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002563}
2564
Jim Grosbach89df9962011-08-26 21:43:41 +00002565/// parseITCondCode - Try to parse a condition code for an IT instruction.
2566ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2567parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2568 SMLoc S = Parser.getTok().getLoc();
2569 const AsmToken &Tok = Parser.getTok();
2570 if (!Tok.is(AsmToken::Identifier))
2571 return MatchOperand_NoMatch;
2572 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2573 .Case("eq", ARMCC::EQ)
2574 .Case("ne", ARMCC::NE)
2575 .Case("hs", ARMCC::HS)
2576 .Case("cs", ARMCC::HS)
2577 .Case("lo", ARMCC::LO)
2578 .Case("cc", ARMCC::LO)
2579 .Case("mi", ARMCC::MI)
2580 .Case("pl", ARMCC::PL)
2581 .Case("vs", ARMCC::VS)
2582 .Case("vc", ARMCC::VC)
2583 .Case("hi", ARMCC::HI)
2584 .Case("ls", ARMCC::LS)
2585 .Case("ge", ARMCC::GE)
2586 .Case("lt", ARMCC::LT)
2587 .Case("gt", ARMCC::GT)
2588 .Case("le", ARMCC::LE)
2589 .Case("al", ARMCC::AL)
2590 .Default(~0U);
2591 if (CC == ~0U)
2592 return MatchOperand_NoMatch;
2593 Parser.Lex(); // Eat the token.
2594
2595 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2596
2597 return MatchOperand_Success;
2598}
2599
Jim Grosbach43904292011-07-25 20:14:50 +00002600/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002601/// token must be an Identifier when called, and if it is a coprocessor
2602/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002603ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002604parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002605 SMLoc S = Parser.getTok().getLoc();
2606 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002607 if (Tok.isNot(AsmToken::Identifier))
2608 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002609
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002610 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002611 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002612 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002613
2614 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002615 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002616 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002617}
2618
Jim Grosbach43904292011-07-25 20:14:50 +00002619/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002620/// token must be an Identifier when called, and if it is a coprocessor
2621/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002622ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002623parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002624 SMLoc S = Parser.getTok().getLoc();
2625 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002626 if (Tok.isNot(AsmToken::Identifier))
2627 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002628
2629 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2630 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002631 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002632
2633 Parser.Lex(); // Eat identifier token.
2634 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002635 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002636}
2637
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002638/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2639/// coproc_option : '{' imm0_255 '}'
2640ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2641parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2642 SMLoc S = Parser.getTok().getLoc();
2643
2644 // If this isn't a '{', this isn't a coprocessor immediate operand.
2645 if (Parser.getTok().isNot(AsmToken::LCurly))
2646 return MatchOperand_NoMatch;
2647 Parser.Lex(); // Eat the '{'
2648
2649 const MCExpr *Expr;
2650 SMLoc Loc = Parser.getTok().getLoc();
2651 if (getParser().ParseExpression(Expr)) {
2652 Error(Loc, "illegal expression");
2653 return MatchOperand_ParseFail;
2654 }
2655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2656 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2657 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2658 return MatchOperand_ParseFail;
2659 }
2660 int Val = CE->getValue();
2661
2662 // Check for and consume the closing '}'
2663 if (Parser.getTok().isNot(AsmToken::RCurly))
2664 return MatchOperand_ParseFail;
2665 SMLoc E = Parser.getTok().getLoc();
2666 Parser.Lex(); // Eat the '}'
2667
2668 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2669 return MatchOperand_Success;
2670}
2671
Jim Grosbachd0588e22011-09-14 18:08:35 +00002672// For register list parsing, we need to map from raw GPR register numbering
2673// to the enumeration values. The enumeration values aren't sorted by
2674// register number due to our using "sp", "lr" and "pc" as canonical names.
2675static unsigned getNextRegister(unsigned Reg) {
2676 // If this is a GPR, we need to do it manually, otherwise we can rely
2677 // on the sort ordering of the enumeration since the other reg-classes
2678 // are sane.
2679 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2680 return Reg + 1;
2681 switch(Reg) {
2682 default: assert(0 && "Invalid GPR number!");
2683 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2684 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2685 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2686 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2687 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2688 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2689 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2690 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2691 }
2692}
2693
Jim Grosbachce485e72011-11-11 21:27:40 +00002694// Return the low-subreg of a given Q register.
2695static unsigned getDRegFromQReg(unsigned QReg) {
2696 switch (QReg) {
2697 default: llvm_unreachable("expected a Q register!");
2698 case ARM::Q0: return ARM::D0;
2699 case ARM::Q1: return ARM::D2;
2700 case ARM::Q2: return ARM::D4;
2701 case ARM::Q3: return ARM::D6;
2702 case ARM::Q4: return ARM::D8;
2703 case ARM::Q5: return ARM::D10;
2704 case ARM::Q6: return ARM::D12;
2705 case ARM::Q7: return ARM::D14;
2706 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002707 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002708 case ARM::Q10: return ARM::D20;
2709 case ARM::Q11: return ARM::D22;
2710 case ARM::Q12: return ARM::D24;
2711 case ARM::Q13: return ARM::D26;
2712 case ARM::Q14: return ARM::D28;
2713 case ARM::Q15: return ARM::D30;
2714 }
2715}
2716
Jim Grosbachd0588e22011-09-14 18:08:35 +00002717/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002718bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002719parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002720 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002721 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002722 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002723 Parser.Lex(); // Eat '{' token.
2724 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002725
Jim Grosbachd0588e22011-09-14 18:08:35 +00002726 // Check the first register in the list to see what register class
2727 // this is a list of.
2728 int Reg = tryParseRegister();
2729 if (Reg == -1)
2730 return Error(RegLoc, "register expected");
2731
Jim Grosbachce485e72011-11-11 21:27:40 +00002732 // The reglist instructions have at most 16 registers, so reserve
2733 // space for that many.
2734 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2735
2736 // Allow Q regs and just interpret them as the two D sub-registers.
2737 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2738 Reg = getDRegFromQReg(Reg);
2739 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2740 ++Reg;
2741 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002742 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002743 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2744 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2745 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2746 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2747 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2748 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2749 else
2750 return Error(RegLoc, "invalid register in register list");
2751
Jim Grosbachce485e72011-11-11 21:27:40 +00002752 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002753 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002754
Jim Grosbachd0588e22011-09-14 18:08:35 +00002755 // This starts immediately after the first register token in the list,
2756 // so we can see either a comma or a minus (range separator) as a legal
2757 // next token.
2758 while (Parser.getTok().is(AsmToken::Comma) ||
2759 Parser.getTok().is(AsmToken::Minus)) {
2760 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002761 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002762 SMLoc EndLoc = Parser.getTok().getLoc();
2763 int EndReg = tryParseRegister();
2764 if (EndReg == -1)
2765 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002766 // Allow Q regs and just interpret them as the two D sub-registers.
2767 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2768 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002769 // If the register is the same as the start reg, there's nothing
2770 // more to do.
2771 if (Reg == EndReg)
2772 continue;
2773 // The register must be in the same register class as the first.
2774 if (!RC->contains(EndReg))
2775 return Error(EndLoc, "invalid register in register list");
2776 // Ranges must go from low to high.
2777 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2778 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002779
Jim Grosbachd0588e22011-09-14 18:08:35 +00002780 // Add all the registers in the range to the register list.
2781 while (Reg != EndReg) {
2782 Reg = getNextRegister(Reg);
2783 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2784 }
2785 continue;
2786 }
2787 Parser.Lex(); // Eat the comma.
2788 RegLoc = Parser.getTok().getLoc();
2789 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002790 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002791 Reg = tryParseRegister();
2792 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002793 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002794 // Allow Q regs and just interpret them as the two D sub-registers.
2795 bool isQReg = false;
2796 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2797 Reg = getDRegFromQReg(Reg);
2798 isQReg = true;
2799 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002800 // The register must be in the same register class as the first.
2801 if (!RC->contains(Reg))
2802 return Error(RegLoc, "invalid register in register list");
2803 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002804 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002805 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002806 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2807 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2808 ") in register list");
2809 continue;
2810 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002811 // VFP register lists must also be contiguous.
2812 // It's OK to use the enumeration values directly here rather, as the
2813 // VFP register classes have the enum sorted properly.
2814 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2815 Reg != OldReg + 1)
2816 return Error(RegLoc, "non-contiguous register range");
2817 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002818 if (isQReg)
2819 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002820 }
2821
Jim Grosbachd0588e22011-09-14 18:08:35 +00002822 SMLoc E = Parser.getTok().getLoc();
2823 if (Parser.getTok().isNot(AsmToken::RCurly))
2824 return Error(E, "'}' expected");
2825 Parser.Lex(); // Eat '}' token.
2826
Jim Grosbach27debd62011-12-13 21:48:29 +00002827 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002828 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002829
2830 // The ARM system instruction variants for LDM/STM have a '^' token here.
2831 if (Parser.getTok().is(AsmToken::Caret)) {
2832 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2833 Parser.Lex(); // Eat '^' token.
2834 }
2835
Bill Wendling50d0f582010-11-18 23:43:05 +00002836 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002837}
2838
Jim Grosbach98b05a52011-11-30 01:09:44 +00002839// Helper function to parse the lane index for vector lists.
2840ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002841parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2842 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002843 if (Parser.getTok().is(AsmToken::LBrac)) {
2844 Parser.Lex(); // Eat the '['.
2845 if (Parser.getTok().is(AsmToken::RBrac)) {
2846 // "Dn[]" is the 'all lanes' syntax.
2847 LaneKind = AllLanes;
2848 Parser.Lex(); // Eat the ']'.
2849 return MatchOperand_Success;
2850 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002851 const MCExpr *LaneIndex;
2852 SMLoc Loc = Parser.getTok().getLoc();
2853 if (getParser().ParseExpression(LaneIndex)) {
2854 Error(Loc, "illegal expression");
2855 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002856 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002857 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2858 if (!CE) {
2859 Error(Loc, "lane index must be empty or an integer");
2860 return MatchOperand_ParseFail;
2861 }
2862 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2863 Error(Parser.getTok().getLoc(), "']' expected");
2864 return MatchOperand_ParseFail;
2865 }
2866 Parser.Lex(); // Eat the ']'.
2867 int64_t Val = CE->getValue();
2868
2869 // FIXME: Make this range check context sensitive for .8, .16, .32.
2870 if (Val < 0 || Val > 7) {
2871 Error(Parser.getTok().getLoc(), "lane index out of range");
2872 return MatchOperand_ParseFail;
2873 }
2874 Index = Val;
2875 LaneKind = IndexedLane;
2876 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002877 }
2878 LaneKind = NoLanes;
2879 return MatchOperand_Success;
2880}
2881
Jim Grosbach862019c2011-10-18 23:02:30 +00002882// parse a vector register list
2883ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2884parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002885 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002886 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002887 SMLoc S = Parser.getTok().getLoc();
2888 // As an extension (to match gas), support a plain D register or Q register
2889 // (without encosing curly braces) as a single or double entry list,
2890 // respectively.
2891 if (Parser.getTok().is(AsmToken::Identifier)) {
2892 int Reg = tryParseRegister();
2893 if (Reg == -1)
2894 return MatchOperand_NoMatch;
2895 SMLoc E = Parser.getTok().getLoc();
2896 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002897 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002898 if (Res != MatchOperand_Success)
2899 return Res;
2900 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002901 case NoLanes:
2902 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002903 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002904 break;
2905 case AllLanes:
2906 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002907 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2908 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002909 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002910 case IndexedLane:
2911 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002912 LaneIndex,
2913 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002914 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002915 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002916 return MatchOperand_Success;
2917 }
2918 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2919 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002920 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002921 if (Res != MatchOperand_Success)
2922 return Res;
2923 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002924 case NoLanes:
2925 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002926 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002927 break;
2928 case AllLanes:
2929 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002930 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2931 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002932 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002933 case IndexedLane:
2934 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002935 LaneIndex,
2936 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002937 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002938 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002939 return MatchOperand_Success;
2940 }
2941 Error(S, "vector register expected");
2942 return MatchOperand_ParseFail;
2943 }
2944
2945 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002946 return MatchOperand_NoMatch;
2947
Jim Grosbach862019c2011-10-18 23:02:30 +00002948 Parser.Lex(); // Eat '{' token.
2949 SMLoc RegLoc = Parser.getTok().getLoc();
2950
2951 int Reg = tryParseRegister();
2952 if (Reg == -1) {
2953 Error(RegLoc, "register expected");
2954 return MatchOperand_ParseFail;
2955 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002956 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002957 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002958 unsigned FirstReg = Reg;
2959 // The list is of D registers, but we also allow Q regs and just interpret
2960 // them as the two D sub-registers.
2961 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2962 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002963 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2964 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002965 ++Reg;
2966 ++Count;
2967 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002968 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002969 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002970
Jim Grosbache43862b2011-11-15 23:19:15 +00002971 while (Parser.getTok().is(AsmToken::Comma) ||
2972 Parser.getTok().is(AsmToken::Minus)) {
2973 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002974 if (!Spacing)
2975 Spacing = 1; // Register range implies a single spaced list.
2976 else if (Spacing == 2) {
2977 Error(Parser.getTok().getLoc(),
2978 "sequential registers in double spaced list");
2979 return MatchOperand_ParseFail;
2980 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002981 Parser.Lex(); // Eat the minus.
2982 SMLoc EndLoc = Parser.getTok().getLoc();
2983 int EndReg = tryParseRegister();
2984 if (EndReg == -1) {
2985 Error(EndLoc, "register expected");
2986 return MatchOperand_ParseFail;
2987 }
2988 // Allow Q regs and just interpret them as the two D sub-registers.
2989 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2990 EndReg = getDRegFromQReg(EndReg) + 1;
2991 // If the register is the same as the start reg, there's nothing
2992 // more to do.
2993 if (Reg == EndReg)
2994 continue;
2995 // The register must be in the same register class as the first.
2996 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2997 Error(EndLoc, "invalid register in register list");
2998 return MatchOperand_ParseFail;
2999 }
3000 // Ranges must go from low to high.
3001 if (Reg > EndReg) {
3002 Error(EndLoc, "bad range in register list");
3003 return MatchOperand_ParseFail;
3004 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003005 // Parse the lane specifier if present.
3006 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003007 unsigned NextLaneIndex;
3008 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003009 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003010 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003011 Error(EndLoc, "mismatched lane index in register list");
3012 return MatchOperand_ParseFail;
3013 }
3014 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003015
3016 // Add all the registers in the range to the register list.
3017 Count += EndReg - Reg;
3018 Reg = EndReg;
3019 continue;
3020 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003021 Parser.Lex(); // Eat the comma.
3022 RegLoc = Parser.getTok().getLoc();
3023 int OldReg = Reg;
3024 Reg = tryParseRegister();
3025 if (Reg == -1) {
3026 Error(RegLoc, "register expected");
3027 return MatchOperand_ParseFail;
3028 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003029 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003030 // It's OK to use the enumeration values directly here rather, as the
3031 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003032 //
3033 // The list is of D registers, but we also allow Q regs and just interpret
3034 // them as the two D sub-registers.
3035 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003036 if (!Spacing)
3037 Spacing = 1; // Register range implies a single spaced list.
3038 else if (Spacing == 2) {
3039 Error(RegLoc,
3040 "invalid register in double-spaced list (must be 'D' register')");
3041 return MatchOperand_ParseFail;
3042 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003043 Reg = getDRegFromQReg(Reg);
3044 if (Reg != OldReg + 1) {
3045 Error(RegLoc, "non-contiguous register range");
3046 return MatchOperand_ParseFail;
3047 }
3048 ++Reg;
3049 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003050 // Parse the lane specifier if present.
3051 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003052 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003053 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003054 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003055 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003056 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003057 Error(EndLoc, "mismatched lane index in register list");
3058 return MatchOperand_ParseFail;
3059 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003060 continue;
3061 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003062 // Normal D register.
3063 // Figure out the register spacing (single or double) of the list if
3064 // we don't know it already.
3065 if (!Spacing)
3066 Spacing = 1 + (Reg == OldReg + 2);
3067
3068 // Just check that it's contiguous and keep going.
3069 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003070 Error(RegLoc, "non-contiguous register range");
3071 return MatchOperand_ParseFail;
3072 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003073 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003074 // Parse the lane specifier if present.
3075 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003076 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003077 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003078 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003079 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003080 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003081 Error(EndLoc, "mismatched lane index in register list");
3082 return MatchOperand_ParseFail;
3083 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003084 }
3085
3086 SMLoc E = Parser.getTok().getLoc();
3087 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3088 Error(E, "'}' expected");
3089 return MatchOperand_ParseFail;
3090 }
3091 Parser.Lex(); // Eat '}' token.
3092
Jim Grosbach98b05a52011-11-30 01:09:44 +00003093 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003094 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003095 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3096 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003097 break;
3098 case AllLanes:
3099 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003100 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003101 S, E));
3102 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003103 case IndexedLane:
3104 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003105 LaneIndex,
3106 (Spacing == 2),
3107 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003108 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003109 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003110 return MatchOperand_Success;
3111}
3112
Jim Grosbach43904292011-07-25 20:14:50 +00003113/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003114ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003115parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003116 SMLoc S = Parser.getTok().getLoc();
3117 const AsmToken &Tok = Parser.getTok();
3118 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3119 StringRef OptStr = Tok.getString();
3120
3121 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3122 .Case("sy", ARM_MB::SY)
3123 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003124 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003125 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003126 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003127 .Case("ishst", ARM_MB::ISHST)
3128 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003129 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003130 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003131 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003132 .Case("osh", ARM_MB::OSH)
3133 .Case("oshst", ARM_MB::OSHST)
3134 .Default(~0U);
3135
3136 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003137 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003138
3139 Parser.Lex(); // Eat identifier token.
3140 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003141 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003142}
3143
Jim Grosbach43904292011-07-25 20:14:50 +00003144/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003145ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003146parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003147 SMLoc S = Parser.getTok().getLoc();
3148 const AsmToken &Tok = Parser.getTok();
3149 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3150 StringRef IFlagsStr = Tok.getString();
3151
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003152 // An iflags string of "none" is interpreted to mean that none of the AIF
3153 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003154 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003155 if (IFlagsStr != "none") {
3156 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3157 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3158 .Case("a", ARM_PROC::A)
3159 .Case("i", ARM_PROC::I)
3160 .Case("f", ARM_PROC::F)
3161 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003162
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003163 // If some specific iflag is already set, it means that some letter is
3164 // present more than once, this is not acceptable.
3165 if (Flag == ~0U || (IFlags & Flag))
3166 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003167
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003168 IFlags |= Flag;
3169 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003170 }
3171
3172 Parser.Lex(); // Eat identifier token.
3173 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3174 return MatchOperand_Success;
3175}
3176
Jim Grosbach43904292011-07-25 20:14:50 +00003177/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003178ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003179parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003180 SMLoc S = Parser.getTok().getLoc();
3181 const AsmToken &Tok = Parser.getTok();
3182 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3183 StringRef Mask = Tok.getString();
3184
James Molloyacad68d2011-09-28 14:21:38 +00003185 if (isMClass()) {
3186 // See ARMv6-M 10.1.1
3187 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3188 .Case("apsr", 0)
3189 .Case("iapsr", 1)
3190 .Case("eapsr", 2)
3191 .Case("xpsr", 3)
3192 .Case("ipsr", 5)
3193 .Case("epsr", 6)
3194 .Case("iepsr", 7)
3195 .Case("msp", 8)
3196 .Case("psp", 9)
3197 .Case("primask", 16)
3198 .Case("basepri", 17)
3199 .Case("basepri_max", 18)
3200 .Case("faultmask", 19)
3201 .Case("control", 20)
3202 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003203
James Molloyacad68d2011-09-28 14:21:38 +00003204 if (FlagsVal == ~0U)
3205 return MatchOperand_NoMatch;
3206
3207 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3208 // basepri, basepri_max and faultmask only valid for V7m.
3209 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003210
James Molloyacad68d2011-09-28 14:21:38 +00003211 Parser.Lex(); // Eat identifier token.
3212 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3213 return MatchOperand_Success;
3214 }
3215
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003216 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3217 size_t Start = 0, Next = Mask.find('_');
3218 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003219 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003220 if (Next != StringRef::npos)
3221 Flags = Mask.slice(Next+1, Mask.size());
3222
3223 // FlagsVal contains the complete mask:
3224 // 3-0: Mask
3225 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3226 unsigned FlagsVal = 0;
3227
3228 if (SpecReg == "apsr") {
3229 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003230 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003231 .Case("g", 0x4) // same as CPSR_s
3232 .Case("nzcvqg", 0xc) // same as CPSR_fs
3233 .Default(~0U);
3234
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003235 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003236 if (!Flags.empty())
3237 return MatchOperand_NoMatch;
3238 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003239 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003240 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003241 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003242 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3243 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003244 for (int i = 0, e = Flags.size(); i != e; ++i) {
3245 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3246 .Case("c", 1)
3247 .Case("x", 2)
3248 .Case("s", 4)
3249 .Case("f", 8)
3250 .Default(~0U);
3251
3252 // If some specific flag is already set, it means that some letter is
3253 // present more than once, this is not acceptable.
3254 if (FlagsVal == ~0U || (FlagsVal & Flag))
3255 return MatchOperand_NoMatch;
3256 FlagsVal |= Flag;
3257 }
3258 } else // No match for special register.
3259 return MatchOperand_NoMatch;
3260
Owen Anderson7784f1d2011-10-21 18:43:28 +00003261 // Special register without flags is NOT equivalent to "fc" flags.
3262 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3263 // two lines would enable gas compatibility at the expense of breaking
3264 // round-tripping.
3265 //
3266 // if (!FlagsVal)
3267 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003268
3269 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3270 if (SpecReg == "spsr")
3271 FlagsVal |= 16;
3272
3273 Parser.Lex(); // Eat identifier token.
3274 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3275 return MatchOperand_Success;
3276}
3277
Jim Grosbachf6c05252011-07-21 17:23:04 +00003278ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3279parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3280 int Low, int High) {
3281 const AsmToken &Tok = Parser.getTok();
3282 if (Tok.isNot(AsmToken::Identifier)) {
3283 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3284 return MatchOperand_ParseFail;
3285 }
3286 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003287 std::string LowerOp = Op.lower();
3288 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003289 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3290 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3291 return MatchOperand_ParseFail;
3292 }
3293 Parser.Lex(); // Eat shift type token.
3294
3295 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003296 if (Parser.getTok().isNot(AsmToken::Hash) &&
3297 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003298 Error(Parser.getTok().getLoc(), "'#' expected");
3299 return MatchOperand_ParseFail;
3300 }
3301 Parser.Lex(); // Eat hash token.
3302
3303 const MCExpr *ShiftAmount;
3304 SMLoc Loc = Parser.getTok().getLoc();
3305 if (getParser().ParseExpression(ShiftAmount)) {
3306 Error(Loc, "illegal expression");
3307 return MatchOperand_ParseFail;
3308 }
3309 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3310 if (!CE) {
3311 Error(Loc, "constant expression expected");
3312 return MatchOperand_ParseFail;
3313 }
3314 int Val = CE->getValue();
3315 if (Val < Low || Val > High) {
3316 Error(Loc, "immediate value out of range");
3317 return MatchOperand_ParseFail;
3318 }
3319
3320 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3321
3322 return MatchOperand_Success;
3323}
3324
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003325ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3326parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3327 const AsmToken &Tok = Parser.getTok();
3328 SMLoc S = Tok.getLoc();
3329 if (Tok.isNot(AsmToken::Identifier)) {
3330 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3331 return MatchOperand_ParseFail;
3332 }
3333 int Val = StringSwitch<int>(Tok.getString())
3334 .Case("be", 1)
3335 .Case("le", 0)
3336 .Default(-1);
3337 Parser.Lex(); // Eat the token.
3338
3339 if (Val == -1) {
3340 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3341 return MatchOperand_ParseFail;
3342 }
3343 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3344 getContext()),
3345 S, Parser.getTok().getLoc()));
3346 return MatchOperand_Success;
3347}
3348
Jim Grosbach580f4a92011-07-25 22:20:28 +00003349/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3350/// instructions. Legal values are:
3351/// lsl #n 'n' in [0,31]
3352/// asr #n 'n' in [1,32]
3353/// n == 32 encoded as n == 0.
3354ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3355parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3356 const AsmToken &Tok = Parser.getTok();
3357 SMLoc S = Tok.getLoc();
3358 if (Tok.isNot(AsmToken::Identifier)) {
3359 Error(S, "shift operator 'asr' or 'lsl' expected");
3360 return MatchOperand_ParseFail;
3361 }
3362 StringRef ShiftName = Tok.getString();
3363 bool isASR;
3364 if (ShiftName == "lsl" || ShiftName == "LSL")
3365 isASR = false;
3366 else if (ShiftName == "asr" || ShiftName == "ASR")
3367 isASR = true;
3368 else {
3369 Error(S, "shift operator 'asr' or 'lsl' expected");
3370 return MatchOperand_ParseFail;
3371 }
3372 Parser.Lex(); // Eat the operator.
3373
3374 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003375 if (Parser.getTok().isNot(AsmToken::Hash) &&
3376 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003377 Error(Parser.getTok().getLoc(), "'#' expected");
3378 return MatchOperand_ParseFail;
3379 }
3380 Parser.Lex(); // Eat hash token.
3381
3382 const MCExpr *ShiftAmount;
3383 SMLoc E = Parser.getTok().getLoc();
3384 if (getParser().ParseExpression(ShiftAmount)) {
3385 Error(E, "malformed shift expression");
3386 return MatchOperand_ParseFail;
3387 }
3388 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3389 if (!CE) {
3390 Error(E, "shift amount must be an immediate");
3391 return MatchOperand_ParseFail;
3392 }
3393
3394 int64_t Val = CE->getValue();
3395 if (isASR) {
3396 // Shift amount must be in [1,32]
3397 if (Val < 1 || Val > 32) {
3398 Error(E, "'asr' shift amount must be in range [1,32]");
3399 return MatchOperand_ParseFail;
3400 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003401 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3402 if (isThumb() && Val == 32) {
3403 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3404 return MatchOperand_ParseFail;
3405 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003406 if (Val == 32) Val = 0;
3407 } else {
3408 // Shift amount must be in [1,32]
3409 if (Val < 0 || Val > 31) {
3410 Error(E, "'lsr' shift amount must be in range [0,31]");
3411 return MatchOperand_ParseFail;
3412 }
3413 }
3414
3415 E = Parser.getTok().getLoc();
3416 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3417
3418 return MatchOperand_Success;
3419}
3420
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003421/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3422/// of instructions. Legal values are:
3423/// ror #n 'n' in {0, 8, 16, 24}
3424ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3425parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3426 const AsmToken &Tok = Parser.getTok();
3427 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003428 if (Tok.isNot(AsmToken::Identifier))
3429 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003430 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003431 if (ShiftName != "ror" && ShiftName != "ROR")
3432 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003433 Parser.Lex(); // Eat the operator.
3434
3435 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003436 if (Parser.getTok().isNot(AsmToken::Hash) &&
3437 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003438 Error(Parser.getTok().getLoc(), "'#' expected");
3439 return MatchOperand_ParseFail;
3440 }
3441 Parser.Lex(); // Eat hash token.
3442
3443 const MCExpr *ShiftAmount;
3444 SMLoc E = Parser.getTok().getLoc();
3445 if (getParser().ParseExpression(ShiftAmount)) {
3446 Error(E, "malformed rotate expression");
3447 return MatchOperand_ParseFail;
3448 }
3449 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3450 if (!CE) {
3451 Error(E, "rotate amount must be an immediate");
3452 return MatchOperand_ParseFail;
3453 }
3454
3455 int64_t Val = CE->getValue();
3456 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3457 // normally, zero is represented in asm by omitting the rotate operand
3458 // entirely.
3459 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3460 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3461 return MatchOperand_ParseFail;
3462 }
3463
3464 E = Parser.getTok().getLoc();
3465 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3466
3467 return MatchOperand_Success;
3468}
3469
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003470ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3471parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3472 SMLoc S = Parser.getTok().getLoc();
3473 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003474 if (Parser.getTok().isNot(AsmToken::Hash) &&
3475 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003476 Error(Parser.getTok().getLoc(), "'#' expected");
3477 return MatchOperand_ParseFail;
3478 }
3479 Parser.Lex(); // Eat hash token.
3480
3481 const MCExpr *LSBExpr;
3482 SMLoc E = Parser.getTok().getLoc();
3483 if (getParser().ParseExpression(LSBExpr)) {
3484 Error(E, "malformed immediate expression");
3485 return MatchOperand_ParseFail;
3486 }
3487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3488 if (!CE) {
3489 Error(E, "'lsb' operand must be an immediate");
3490 return MatchOperand_ParseFail;
3491 }
3492
3493 int64_t LSB = CE->getValue();
3494 // The LSB must be in the range [0,31]
3495 if (LSB < 0 || LSB > 31) {
3496 Error(E, "'lsb' operand must be in the range [0,31]");
3497 return MatchOperand_ParseFail;
3498 }
3499 E = Parser.getTok().getLoc();
3500
3501 // Expect another immediate operand.
3502 if (Parser.getTok().isNot(AsmToken::Comma)) {
3503 Error(Parser.getTok().getLoc(), "too few operands");
3504 return MatchOperand_ParseFail;
3505 }
3506 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003507 if (Parser.getTok().isNot(AsmToken::Hash) &&
3508 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003509 Error(Parser.getTok().getLoc(), "'#' expected");
3510 return MatchOperand_ParseFail;
3511 }
3512 Parser.Lex(); // Eat hash token.
3513
3514 const MCExpr *WidthExpr;
3515 if (getParser().ParseExpression(WidthExpr)) {
3516 Error(E, "malformed immediate expression");
3517 return MatchOperand_ParseFail;
3518 }
3519 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3520 if (!CE) {
3521 Error(E, "'width' operand must be an immediate");
3522 return MatchOperand_ParseFail;
3523 }
3524
3525 int64_t Width = CE->getValue();
3526 // The LSB must be in the range [1,32-lsb]
3527 if (Width < 1 || Width > 32 - LSB) {
3528 Error(E, "'width' operand must be in the range [1,32-lsb]");
3529 return MatchOperand_ParseFail;
3530 }
3531 E = Parser.getTok().getLoc();
3532
3533 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3534
3535 return MatchOperand_Success;
3536}
3537
Jim Grosbach7ce05792011-08-03 23:50:40 +00003538ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3539parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3540 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003541 // postidx_reg := '+' register {, shift}
3542 // | '-' register {, shift}
3543 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003544
3545 // This method must return MatchOperand_NoMatch without consuming any tokens
3546 // in the case where there is no match, as other alternatives take other
3547 // parse methods.
3548 AsmToken Tok = Parser.getTok();
3549 SMLoc S = Tok.getLoc();
3550 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003551 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003552 int Reg = -1;
3553 if (Tok.is(AsmToken::Plus)) {
3554 Parser.Lex(); // Eat the '+' token.
3555 haveEaten = true;
3556 } else if (Tok.is(AsmToken::Minus)) {
3557 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003558 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003559 haveEaten = true;
3560 }
3561 if (Parser.getTok().is(AsmToken::Identifier))
3562 Reg = tryParseRegister();
3563 if (Reg == -1) {
3564 if (!haveEaten)
3565 return MatchOperand_NoMatch;
3566 Error(Parser.getTok().getLoc(), "register expected");
3567 return MatchOperand_ParseFail;
3568 }
3569 SMLoc E = Parser.getTok().getLoc();
3570
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003571 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3572 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003573 if (Parser.getTok().is(AsmToken::Comma)) {
3574 Parser.Lex(); // Eat the ','.
3575 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3576 return MatchOperand_ParseFail;
3577 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003578
3579 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3580 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003581
3582 return MatchOperand_Success;
3583}
3584
Jim Grosbach251bf252011-08-10 21:56:18 +00003585ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3586parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3587 // Check for a post-index addressing register operand. Specifically:
3588 // am3offset := '+' register
3589 // | '-' register
3590 // | register
3591 // | # imm
3592 // | # + imm
3593 // | # - imm
3594
3595 // This method must return MatchOperand_NoMatch without consuming any tokens
3596 // in the case where there is no match, as other alternatives take other
3597 // parse methods.
3598 AsmToken Tok = Parser.getTok();
3599 SMLoc S = Tok.getLoc();
3600
3601 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003602 if (Parser.getTok().is(AsmToken::Hash) ||
3603 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003604 Parser.Lex(); // Eat the '#'.
3605 // Explicitly look for a '-', as we need to encode negative zero
3606 // differently.
3607 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3608 const MCExpr *Offset;
3609 if (getParser().ParseExpression(Offset))
3610 return MatchOperand_ParseFail;
3611 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3612 if (!CE) {
3613 Error(S, "constant expression expected");
3614 return MatchOperand_ParseFail;
3615 }
3616 SMLoc E = Tok.getLoc();
3617 // Negative zero is encoded as the flag value INT32_MIN.
3618 int32_t Val = CE->getValue();
3619 if (isNegative && Val == 0)
3620 Val = INT32_MIN;
3621
3622 Operands.push_back(
3623 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3624
3625 return MatchOperand_Success;
3626 }
3627
3628
3629 bool haveEaten = false;
3630 bool isAdd = true;
3631 int Reg = -1;
3632 if (Tok.is(AsmToken::Plus)) {
3633 Parser.Lex(); // Eat the '+' token.
3634 haveEaten = true;
3635 } else if (Tok.is(AsmToken::Minus)) {
3636 Parser.Lex(); // Eat the '-' token.
3637 isAdd = false;
3638 haveEaten = true;
3639 }
3640 if (Parser.getTok().is(AsmToken::Identifier))
3641 Reg = tryParseRegister();
3642 if (Reg == -1) {
3643 if (!haveEaten)
3644 return MatchOperand_NoMatch;
3645 Error(Parser.getTok().getLoc(), "register expected");
3646 return MatchOperand_ParseFail;
3647 }
3648 SMLoc E = Parser.getTok().getLoc();
3649
3650 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3651 0, S, E));
3652
3653 return MatchOperand_Success;
3654}
3655
Jim Grosbacha77295d2011-09-08 22:07:06 +00003656/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3657/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3658/// when they refer multiple MIOperands inside a single one.
3659bool ARMAsmParser::
3660cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3661 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3662 // Rt, Rt2
3663 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3664 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3665 // Create a writeback register dummy placeholder.
3666 Inst.addOperand(MCOperand::CreateReg(0));
3667 // addr
3668 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3669 // pred
3670 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3671 return true;
3672}
3673
3674/// cvtT2StrdPre - Convert parsed operands to MCInst.
3675/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3676/// when they refer multiple MIOperands inside a single one.
3677bool ARMAsmParser::
3678cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3679 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3680 // Create a writeback register dummy placeholder.
3681 Inst.addOperand(MCOperand::CreateReg(0));
3682 // Rt, Rt2
3683 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3684 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3685 // addr
3686 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3687 // pred
3688 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3689 return true;
3690}
3691
Jim Grosbacheeec0252011-09-08 00:39:19 +00003692/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3693/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3694/// when they refer multiple MIOperands inside a single one.
3695bool ARMAsmParser::
3696cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3697 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3698 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3699
3700 // Create a writeback register dummy placeholder.
3701 Inst.addOperand(MCOperand::CreateImm(0));
3702
3703 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3704 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3705 return true;
3706}
3707
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003708/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3709/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3710/// when they refer multiple MIOperands inside a single one.
3711bool ARMAsmParser::
3712cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3713 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3714 // Create a writeback register dummy placeholder.
3715 Inst.addOperand(MCOperand::CreateImm(0));
3716 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3717 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3718 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3719 return true;
3720}
3721
Jim Grosbach1355cf12011-07-26 17:10:22 +00003722/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003723/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3724/// when they refer multiple MIOperands inside a single one.
3725bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003726cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003727 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3728 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3729
3730 // Create a writeback register dummy placeholder.
3731 Inst.addOperand(MCOperand::CreateImm(0));
3732
Jim Grosbach7ce05792011-08-03 23:50:40 +00003733 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003734 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3735 return true;
3736}
3737
Owen Anderson9ab0f252011-08-26 20:43:14 +00003738/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3739/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3740/// when they refer multiple MIOperands inside a single one.
3741bool ARMAsmParser::
3742cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3743 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3744 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3745
3746 // Create a writeback register dummy placeholder.
3747 Inst.addOperand(MCOperand::CreateImm(0));
3748
3749 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3750 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3751 return true;
3752}
3753
3754
Jim Grosbach548340c2011-08-11 19:22:40 +00003755/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3756/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3757/// when they refer multiple MIOperands inside a single one.
3758bool ARMAsmParser::
3759cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3760 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3761 // Create a writeback register dummy placeholder.
3762 Inst.addOperand(MCOperand::CreateImm(0));
3763 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3764 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3765 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3766 return true;
3767}
3768
Jim Grosbach1355cf12011-07-26 17:10:22 +00003769/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003770/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3771/// when they refer multiple MIOperands inside a single one.
3772bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003773cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003774 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3775 // Create a writeback register dummy placeholder.
3776 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003777 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3778 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3779 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003780 return true;
3781}
3782
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003783/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3784/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3785/// when they refer multiple MIOperands inside a single one.
3786bool ARMAsmParser::
3787cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3788 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3789 // Create a writeback register dummy placeholder.
3790 Inst.addOperand(MCOperand::CreateImm(0));
3791 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3792 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3793 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3794 return true;
3795}
3796
Jim Grosbach7ce05792011-08-03 23:50:40 +00003797/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3798/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3799/// when they refer multiple MIOperands inside a single one.
3800bool ARMAsmParser::
3801cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3803 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003804 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003805 // Create a writeback register dummy placeholder.
3806 Inst.addOperand(MCOperand::CreateImm(0));
3807 // addr
3808 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3809 // offset
3810 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3811 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003812 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3813 return true;
3814}
3815
Jim Grosbach7ce05792011-08-03 23:50:40 +00003816/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003817/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3818/// when they refer multiple MIOperands inside a single one.
3819bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003820cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3821 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3822 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003823 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003824 // Create a writeback register dummy placeholder.
3825 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003826 // addr
3827 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3828 // offset
3829 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3830 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003831 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3832 return true;
3833}
3834
Jim Grosbach7ce05792011-08-03 23:50:40 +00003835/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003836/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3837/// when they refer multiple MIOperands inside a single one.
3838bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003839cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3840 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003841 // Create a writeback register dummy placeholder.
3842 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003843 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003844 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003845 // addr
3846 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3847 // offset
3848 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3849 // pred
3850 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3851 return true;
3852}
3853
3854/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3855/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3856/// when they refer multiple MIOperands inside a single one.
3857bool ARMAsmParser::
3858cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3859 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3860 // Create a writeback register dummy placeholder.
3861 Inst.addOperand(MCOperand::CreateImm(0));
3862 // Rt
3863 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3864 // addr
3865 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3866 // offset
3867 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3868 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003869 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3870 return true;
3871}
3872
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003873/// cvtLdrdPre - Convert parsed operands to MCInst.
3874/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3875/// when they refer multiple MIOperands inside a single one.
3876bool ARMAsmParser::
3877cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3878 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3879 // Rt, Rt2
3880 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3881 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3882 // Create a writeback register dummy placeholder.
3883 Inst.addOperand(MCOperand::CreateImm(0));
3884 // addr
3885 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3886 // pred
3887 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3888 return true;
3889}
3890
Jim Grosbach14605d12011-08-11 20:28:23 +00003891/// cvtStrdPre - Convert parsed operands to MCInst.
3892/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3893/// when they refer multiple MIOperands inside a single one.
3894bool ARMAsmParser::
3895cvtStrdPre(MCInst &Inst, unsigned Opcode,
3896 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3897 // Create a writeback register dummy placeholder.
3898 Inst.addOperand(MCOperand::CreateImm(0));
3899 // Rt, Rt2
3900 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3901 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3902 // addr
3903 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3904 // pred
3905 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3906 return true;
3907}
3908
Jim Grosbach623a4542011-08-10 22:42:16 +00003909/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3910/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3911/// when they refer multiple MIOperands inside a single one.
3912bool ARMAsmParser::
3913cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3914 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3915 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3916 // Create a writeback register dummy placeholder.
3917 Inst.addOperand(MCOperand::CreateImm(0));
3918 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3919 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3920 return true;
3921}
3922
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003923/// cvtThumbMultiple- Convert parsed operands to MCInst.
3924/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3925/// when they refer multiple MIOperands inside a single one.
3926bool ARMAsmParser::
3927cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3928 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3929 // The second source operand must be the same register as the destination
3930 // operand.
3931 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003932 (((ARMOperand*)Operands[3])->getReg() !=
3933 ((ARMOperand*)Operands[5])->getReg()) &&
3934 (((ARMOperand*)Operands[3])->getReg() !=
3935 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003936 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003937 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003938 return false;
3939 }
3940 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3941 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003942 // If we have a three-operand form, make sure to set Rn to be the operand
3943 // that isn't the same as Rd.
3944 unsigned RegOp = 4;
3945 if (Operands.size() == 6 &&
3946 ((ARMOperand*)Operands[4])->getReg() ==
3947 ((ARMOperand*)Operands[3])->getReg())
3948 RegOp = 5;
3949 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3950 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003951 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3952
3953 return true;
3954}
Jim Grosbach623a4542011-08-10 22:42:16 +00003955
Jim Grosbach12431322011-10-24 22:16:58 +00003956bool ARMAsmParser::
3957cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3958 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3959 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003960 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003961 // Create a writeback register dummy placeholder.
3962 Inst.addOperand(MCOperand::CreateImm(0));
3963 // Vn
3964 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3965 // pred
3966 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3967 return true;
3968}
3969
3970bool ARMAsmParser::
3971cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3972 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3973 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003974 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003975 // Create a writeback register dummy placeholder.
3976 Inst.addOperand(MCOperand::CreateImm(0));
3977 // Vn
3978 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3979 // Vm
3980 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3981 // pred
3982 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3983 return true;
3984}
3985
Jim Grosbach4334e032011-10-31 21:50:31 +00003986bool ARMAsmParser::
3987cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3988 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3989 // Create a writeback register dummy placeholder.
3990 Inst.addOperand(MCOperand::CreateImm(0));
3991 // Vn
3992 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3993 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003994 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003995 // pred
3996 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3997 return true;
3998}
3999
4000bool ARMAsmParser::
4001cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4002 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4003 // Create a writeback register dummy placeholder.
4004 Inst.addOperand(MCOperand::CreateImm(0));
4005 // Vn
4006 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4007 // Vm
4008 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4009 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004010 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004011 // pred
4012 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4013 return true;
4014}
4015
Bill Wendlinge7176102010-11-06 22:36:58 +00004016/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004017/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004018bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004019parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004020 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004021 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004022 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004023 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004024 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004025
Sean Callanan18b83232010-01-19 21:44:56 +00004026 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004027 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004028 if (BaseRegNum == -1)
4029 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004030
Daniel Dunbar05710932011-01-18 05:34:17 +00004031 // The next token must either be a comma or a closing bracket.
4032 const AsmToken &Tok = Parser.getTok();
4033 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004034 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004035
Jim Grosbach7ce05792011-08-03 23:50:40 +00004036 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004037 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004038 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004039
Jim Grosbach7ce05792011-08-03 23:50:40 +00004040 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004041 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004042
Jim Grosbachfb12f352011-09-19 18:42:21 +00004043 // If there's a pre-indexing writeback marker, '!', just add it as a token
4044 // operand. It's rather odd, but syntactically valid.
4045 if (Parser.getTok().is(AsmToken::Exclaim)) {
4046 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4047 Parser.Lex(); // Eat the '!'.
4048 }
4049
Jim Grosbach7ce05792011-08-03 23:50:40 +00004050 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004051 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004052
Jim Grosbach7ce05792011-08-03 23:50:40 +00004053 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4054 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004055
Jim Grosbach57dcb852011-10-11 17:29:55 +00004056 // If we have a ':', it's an alignment specifier.
4057 if (Parser.getTok().is(AsmToken::Colon)) {
4058 Parser.Lex(); // Eat the ':'.
4059 E = Parser.getTok().getLoc();
4060
4061 const MCExpr *Expr;
4062 if (getParser().ParseExpression(Expr))
4063 return true;
4064
4065 // The expression has to be a constant. Memory references with relocations
4066 // don't come through here, as they use the <label> forms of the relevant
4067 // instructions.
4068 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4069 if (!CE)
4070 return Error (E, "constant expression expected");
4071
4072 unsigned Align = 0;
4073 switch (CE->getValue()) {
4074 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004075 return Error(E,
4076 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4077 case 16: Align = 2; break;
4078 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004079 case 64: Align = 8; break;
4080 case 128: Align = 16; break;
4081 case 256: Align = 32; break;
4082 }
4083
4084 // Now we should have the closing ']'
4085 E = Parser.getTok().getLoc();
4086 if (Parser.getTok().isNot(AsmToken::RBrac))
4087 return Error(E, "']' expected");
4088 Parser.Lex(); // Eat right bracket token.
4089
4090 // Don't worry about range checking the value here. That's handled by
4091 // the is*() predicates.
4092 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4093 ARM_AM::no_shift, 0, Align,
4094 false, S, E));
4095
4096 // If there's a pre-indexing writeback marker, '!', just add it as a token
4097 // operand.
4098 if (Parser.getTok().is(AsmToken::Exclaim)) {
4099 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4100 Parser.Lex(); // Eat the '!'.
4101 }
4102
4103 return false;
4104 }
4105
4106 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004107 // offset. Be friendly and also accept a plain integer (without a leading
4108 // hash) for gas compatibility.
4109 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004110 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004111 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004112 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004113 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004114 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004115
Owen Anderson0da10cf2011-08-29 19:36:44 +00004116 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004117 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004118 if (getParser().ParseExpression(Offset))
4119 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004120
4121 // The expression has to be a constant. Memory references with relocations
4122 // don't come through here, as they use the <label> forms of the relevant
4123 // instructions.
4124 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4125 if (!CE)
4126 return Error (E, "constant expression expected");
4127
Owen Anderson0da10cf2011-08-29 19:36:44 +00004128 // If the constant was #-0, represent it as INT32_MIN.
4129 int32_t Val = CE->getValue();
4130 if (isNegative && Val == 0)
4131 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4132
Jim Grosbach7ce05792011-08-03 23:50:40 +00004133 // Now we should have the closing ']'
4134 E = Parser.getTok().getLoc();
4135 if (Parser.getTok().isNot(AsmToken::RBrac))
4136 return Error(E, "']' expected");
4137 Parser.Lex(); // Eat right bracket token.
4138
4139 // Don't worry about range checking the value here. That's handled by
4140 // the is*() predicates.
4141 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004142 ARM_AM::no_shift, 0, 0,
4143 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004144
4145 // If there's a pre-indexing writeback marker, '!', just add it as a token
4146 // operand.
4147 if (Parser.getTok().is(AsmToken::Exclaim)) {
4148 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4149 Parser.Lex(); // Eat the '!'.
4150 }
4151
4152 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004153 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004154
4155 // The register offset is optionally preceded by a '+' or '-'
4156 bool isNegative = false;
4157 if (Parser.getTok().is(AsmToken::Minus)) {
4158 isNegative = true;
4159 Parser.Lex(); // Eat the '-'.
4160 } else if (Parser.getTok().is(AsmToken::Plus)) {
4161 // Nothing to do.
4162 Parser.Lex(); // Eat the '+'.
4163 }
4164
4165 E = Parser.getTok().getLoc();
4166 int OffsetRegNum = tryParseRegister();
4167 if (OffsetRegNum == -1)
4168 return Error(E, "register expected");
4169
4170 // If there's a shift operator, handle it.
4171 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004172 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004173 if (Parser.getTok().is(AsmToken::Comma)) {
4174 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004175 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176 return true;
4177 }
4178
4179 // Now we should have the closing ']'
4180 E = Parser.getTok().getLoc();
4181 if (Parser.getTok().isNot(AsmToken::RBrac))
4182 return Error(E, "']' expected");
4183 Parser.Lex(); // Eat right bracket token.
4184
4185 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004186 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004187 S, E));
4188
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004189 // If there's a pre-indexing writeback marker, '!', just add it as a token
4190 // operand.
4191 if (Parser.getTok().is(AsmToken::Exclaim)) {
4192 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4193 Parser.Lex(); // Eat the '!'.
4194 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004195
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004196 return false;
4197}
4198
Jim Grosbach7ce05792011-08-03 23:50:40 +00004199/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004200/// ( lsl | lsr | asr | ror ) , # shift_amount
4201/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004202/// return true if it parses a shift otherwise it returns false.
4203bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4204 unsigned &Amount) {
4205 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004206 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004207 if (Tok.isNot(AsmToken::Identifier))
4208 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004209 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004210 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4211 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004212 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004213 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004214 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004215 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004216 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004217 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004218 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004219 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004220 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004221 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004222 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004223 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004224
Jim Grosbach7ce05792011-08-03 23:50:40 +00004225 // rrx stands alone.
4226 Amount = 0;
4227 if (St != ARM_AM::rrx) {
4228 Loc = Parser.getTok().getLoc();
4229 // A '#' and a shift amount.
4230 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004231 if (HashTok.isNot(AsmToken::Hash) &&
4232 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004233 return Error(HashTok.getLoc(), "'#' expected");
4234 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004235
Jim Grosbach7ce05792011-08-03 23:50:40 +00004236 const MCExpr *Expr;
4237 if (getParser().ParseExpression(Expr))
4238 return true;
4239 // Range check the immediate.
4240 // lsl, ror: 0 <= imm <= 31
4241 // lsr, asr: 0 <= imm <= 32
4242 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4243 if (!CE)
4244 return Error(Loc, "shift amount must be an immediate");
4245 int64_t Imm = CE->getValue();
4246 if (Imm < 0 ||
4247 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4248 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4249 return Error(Loc, "immediate shift value out of range");
4250 Amount = Imm;
4251 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004252
4253 return false;
4254}
4255
Jim Grosbach9d390362011-10-03 23:38:36 +00004256/// parseFPImm - A floating point immediate expression operand.
4257ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4258parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004259 // Anything that can accept a floating point constant as an operand
4260 // needs to go through here, as the regular ParseExpression is
4261 // integer only.
4262 //
4263 // This routine still creates a generic Immediate operand, containing
4264 // a bitcast of the 64-bit floating point value. The various operands
4265 // that accept floats can check whether the value is valid for them
4266 // via the standard is*() predicates.
4267
Jim Grosbach9d390362011-10-03 23:38:36 +00004268 SMLoc S = Parser.getTok().getLoc();
4269
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004270 if (Parser.getTok().isNot(AsmToken::Hash) &&
4271 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004272 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004273
4274 // Disambiguate the VMOV forms that can accept an FP immediate.
4275 // vmov.f32 <sreg>, #imm
4276 // vmov.f64 <dreg>, #imm
4277 // vmov.f32 <dreg>, #imm @ vector f32x2
4278 // vmov.f32 <qreg>, #imm @ vector f32x4
4279 //
4280 // There are also the NEON VMOV instructions which expect an
4281 // integer constant. Make sure we don't try to parse an FPImm
4282 // for these:
4283 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4284 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4285 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4286 TyOp->getToken() != ".f64"))
4287 return MatchOperand_NoMatch;
4288
Jim Grosbach9d390362011-10-03 23:38:36 +00004289 Parser.Lex(); // Eat the '#'.
4290
4291 // Handle negation, as that still comes through as a separate token.
4292 bool isNegative = false;
4293 if (Parser.getTok().is(AsmToken::Minus)) {
4294 isNegative = true;
4295 Parser.Lex();
4296 }
4297 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004298 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004299 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004300 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004301 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4302 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004303 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004304 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004305 Operands.push_back(ARMOperand::CreateImm(
4306 MCConstantExpr::Create(IntVal, getContext()),
4307 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004308 return MatchOperand_Success;
4309 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004310 // Also handle plain integers. Instructions which allow floating point
4311 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004312 if (Tok.is(AsmToken::Integer)) {
4313 int64_t Val = Tok.getIntVal();
4314 Parser.Lex(); // Eat the token.
4315 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004316 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004317 return MatchOperand_ParseFail;
4318 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004319 double RealVal = ARM_AM::getFPImmFloat(Val);
4320 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4321 Operands.push_back(ARMOperand::CreateImm(
4322 MCConstantExpr::Create(Val, getContext()), S,
4323 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004324 return MatchOperand_Success;
4325 }
4326
Jim Grosbachae69f702012-01-19 02:47:30 +00004327 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004328 return MatchOperand_ParseFail;
4329}
Jim Grosbach51222d12012-01-20 18:09:51 +00004330
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004331/// Parse a arm instruction operand. For now this parses the operand regardless
4332/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004333bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004334 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004335 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004336
4337 // Check if the current operand has a custom associated parser, if so, try to
4338 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004339 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4340 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004341 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004342 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4343 // there was a match, but an error occurred, in which case, just return that
4344 // the operand parsing failed.
4345 if (ResTy == MatchOperand_ParseFail)
4346 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004347
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004348 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004349 default:
4350 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004351 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004352 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004353 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004354 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004355 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004356 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004357 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004358 else if (Res == -1) // irrecoverable error
4359 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004360 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004361 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4362 S = Parser.getTok().getLoc();
4363 Parser.Lex();
4364 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4365 return false;
4366 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004367
4368 // Fall though for the Identifier case that is not a register or a
4369 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004370 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004371 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004372 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004373 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004374 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004375 // This was not a register so parse other operands that start with an
4376 // identifier (like labels) as expressions and create them as immediates.
4377 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004378 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004379 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004380 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004381 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004382 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4383 return false;
4384 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004385 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004386 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004387 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004388 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004389 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004390 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004391 // #42 -> immediate.
4392 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004393 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004394 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004395 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004396 const MCExpr *ImmVal;
4397 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004398 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004399 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004400 if (CE) {
4401 int32_t Val = CE->getValue();
4402 if (isNegative && Val == 0)
4403 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004404 }
Sean Callanan76264762010-04-02 22:27:05 +00004405 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004406 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4407 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004408 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004409 case AsmToken::Colon: {
4410 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004411 // FIXME: Check it's an expression prefix,
4412 // e.g. (FOO - :lower16:BAR) isn't legal.
4413 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004414 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004415 return true;
4416
Evan Cheng75972122011-01-13 07:58:56 +00004417 const MCExpr *SubExprVal;
4418 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004419 return true;
4420
Evan Cheng75972122011-01-13 07:58:56 +00004421 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4422 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004423 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004424 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004425 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004426 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004427 }
4428}
4429
Jim Grosbach1355cf12011-07-26 17:10:22 +00004430// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004431// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004432bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004433 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004434
4435 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004436 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004437 Parser.Lex(); // Eat ':'
4438
4439 if (getLexer().isNot(AsmToken::Identifier)) {
4440 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4441 return true;
4442 }
4443
4444 StringRef IDVal = Parser.getTok().getIdentifier();
4445 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004446 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004447 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004448 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004449 } else {
4450 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4451 return true;
4452 }
4453 Parser.Lex();
4454
4455 if (getLexer().isNot(AsmToken::Colon)) {
4456 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4457 return true;
4458 }
4459 Parser.Lex(); // Eat the last ':'
4460 return false;
4461}
4462
Daniel Dunbar352e1482011-01-11 15:59:50 +00004463/// \brief Given a mnemonic, split out possible predication code and carry
4464/// setting letters to form a canonical mnemonic and flags.
4465//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004466// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004467// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004468StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004469 unsigned &PredicationCode,
4470 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004471 unsigned &ProcessorIMod,
4472 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004473 PredicationCode = ARMCC::AL;
4474 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004475 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004476
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004477 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004478 //
4479 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004480 if ((Mnemonic == "movs" && isThumb()) ||
4481 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4482 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4483 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4484 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4485 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4486 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004487 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4488 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004489 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004490
Jim Grosbach3f00e312011-07-11 17:09:57 +00004491 // First, split out any predication code. Ignore mnemonics we know aren't
4492 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004493 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004494 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004495 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004496 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004497 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4498 .Case("eq", ARMCC::EQ)
4499 .Case("ne", ARMCC::NE)
4500 .Case("hs", ARMCC::HS)
4501 .Case("cs", ARMCC::HS)
4502 .Case("lo", ARMCC::LO)
4503 .Case("cc", ARMCC::LO)
4504 .Case("mi", ARMCC::MI)
4505 .Case("pl", ARMCC::PL)
4506 .Case("vs", ARMCC::VS)
4507 .Case("vc", ARMCC::VC)
4508 .Case("hi", ARMCC::HI)
4509 .Case("ls", ARMCC::LS)
4510 .Case("ge", ARMCC::GE)
4511 .Case("lt", ARMCC::LT)
4512 .Case("gt", ARMCC::GT)
4513 .Case("le", ARMCC::LE)
4514 .Case("al", ARMCC::AL)
4515 .Default(~0U);
4516 if (CC != ~0U) {
4517 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4518 PredicationCode = CC;
4519 }
Bill Wendling52925b62010-10-29 23:50:21 +00004520 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004521
Daniel Dunbar352e1482011-01-11 15:59:50 +00004522 // Next, determine if we have a carry setting bit. We explicitly ignore all
4523 // the instructions we know end in 's'.
4524 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004525 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004526 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4527 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4528 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004529 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004530 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004531 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004532 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004533 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004534 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4535 CarrySetting = true;
4536 }
4537
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004538 // The "cps" instruction can have a interrupt mode operand which is glued into
4539 // the mnemonic. Check if this is the case, split it and parse the imod op
4540 if (Mnemonic.startswith("cps")) {
4541 // Split out any imod code.
4542 unsigned IMod =
4543 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4544 .Case("ie", ARM_PROC::IE)
4545 .Case("id", ARM_PROC::ID)
4546 .Default(~0U);
4547 if (IMod != ~0U) {
4548 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4549 ProcessorIMod = IMod;
4550 }
4551 }
4552
Jim Grosbach89df9962011-08-26 21:43:41 +00004553 // The "it" instruction has the condition mask on the end of the mnemonic.
4554 if (Mnemonic.startswith("it")) {
4555 ITMask = Mnemonic.slice(2, Mnemonic.size());
4556 Mnemonic = Mnemonic.slice(0, 2);
4557 }
4558
Daniel Dunbar352e1482011-01-11 15:59:50 +00004559 return Mnemonic;
4560}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004561
4562/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4563/// inclusion of carry set or predication code operands.
4564//
4565// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004566void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004567getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004568 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004569 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4570 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004571 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004572 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004573 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004574 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004575 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004576 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004577 Mnemonic == "mla" || Mnemonic == "smlal" ||
4578 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004579 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004580 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004581 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004582
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004583 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4584 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4585 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4586 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004587 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4588 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004589 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004590 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4591 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4592 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004593 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4594 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004595 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004596 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004597 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004598 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004599
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004600 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004601 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004602 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004603 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004604 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004605}
4606
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004607bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4608 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004609 // FIXME: This is all horribly hacky. We really need a better way to deal
4610 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004611
4612 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4613 // another does not. Specifically, the MOVW instruction does not. So we
4614 // special case it here and remove the defaulted (non-setting) cc_out
4615 // operand if that's the instruction we're trying to match.
4616 //
4617 // We do this as post-processing of the explicit operands rather than just
4618 // conditionally adding the cc_out in the first place because we need
4619 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004620 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004621 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4622 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4623 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4624 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004625
4626 // Register-register 'add' for thumb does not have a cc_out operand
4627 // when there are only two register operands.
4628 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4629 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4630 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4631 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4632 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004633 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004634 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4635 // have to check the immediate range here since Thumb2 has a variant
4636 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004637 if (((isThumb() && Mnemonic == "add") ||
4638 (isThumbTwo() && Mnemonic == "sub")) &&
4639 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004640 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4641 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4642 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004643 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4644 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4645 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004646 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004647 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4648 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004649 // selecting via the generic "add" mnemonic, so to know that we
4650 // should remove the cc_out operand, we have to explicitly check that
4651 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004652 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4653 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004654 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4655 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4656 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4657 // Nest conditions rather than one big 'if' statement for readability.
4658 //
4659 // If either register is a high reg, it's either one of the SP
4660 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004661 // check against T3. If the second register is the PC, this is an
4662 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004663 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4664 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004665 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004666 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4667 return false;
4668 // If both registers are low, we're in an IT block, and the immediate is
4669 // in range, we should use encoding T1 instead, which has a cc_out.
4670 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004671 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004672 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4673 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4674 return false;
4675
4676 // Otherwise, we use encoding T4, which does not have a cc_out
4677 // operand.
4678 return true;
4679 }
4680
Jim Grosbach64944f42011-09-14 21:00:40 +00004681 // The thumb2 multiply instruction doesn't have a CCOut register, so
4682 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4683 // use the 16-bit encoding or not.
4684 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4685 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4686 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4687 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4688 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4689 // If the registers aren't low regs, the destination reg isn't the
4690 // same as one of the source regs, or the cc_out operand is zero
4691 // outside of an IT block, we have to use the 32-bit encoding, so
4692 // remove the cc_out operand.
4693 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4694 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004695 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004696 !inITBlock() ||
4697 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4698 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4699 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4700 static_cast<ARMOperand*>(Operands[4])->getReg())))
4701 return true;
4702
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004703 // Also check the 'mul' syntax variant that doesn't specify an explicit
4704 // destination register.
4705 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4706 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4707 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4708 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4709 // If the registers aren't low regs or the cc_out operand is zero
4710 // outside of an IT block, we have to use the 32-bit encoding, so
4711 // remove the cc_out operand.
4712 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4713 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4714 !inITBlock()))
4715 return true;
4716
Jim Grosbach64944f42011-09-14 21:00:40 +00004717
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004718
Jim Grosbachf69c8042011-08-24 21:42:27 +00004719 // Register-register 'add/sub' for thumb does not have a cc_out operand
4720 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4721 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4722 // right, this will result in better diagnostics (which operand is off)
4723 // anyway.
4724 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4725 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004726 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4727 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4728 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4729 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004730
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004731 return false;
4732}
4733
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004734static bool isDataTypeToken(StringRef Tok) {
4735 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4736 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4737 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4738 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4739 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4740 Tok == ".f" || Tok == ".d";
4741}
4742
4743// FIXME: This bit should probably be handled via an explicit match class
4744// in the .td files that matches the suffix instead of having it be
4745// a literal string token the way it is now.
4746static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4747 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4748}
4749
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004750static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004751/// Parse an arm instruction mnemonic followed by its operands.
4752bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4753 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004754 // Apply mnemonic aliases before doing anything else, as the destination
4755 // mnemnonic may include suffices and we want to handle them normally.
4756 // The generic tblgen'erated code does this later, at the start of
4757 // MatchInstructionImpl(), but that's too late for aliases that include
4758 // any sort of suffix.
4759 unsigned AvailableFeatures = getAvailableFeatures();
4760 applyMnemonicAliases(Name, AvailableFeatures);
4761
Jim Grosbacha39cda72011-12-14 02:16:11 +00004762 // First check for the ARM-specific .req directive.
4763 if (Parser.getTok().is(AsmToken::Identifier) &&
4764 Parser.getTok().getIdentifier() == ".req") {
4765 parseDirectiveReq(Name, NameLoc);
4766 // We always return 'error' for this, as we're done with this
4767 // statement and don't need to match the 'instruction."
4768 return true;
4769 }
4770
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004771 // Create the leading tokens for the mnemonic, split by '.' characters.
4772 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004773 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004774
Daniel Dunbar352e1482011-01-11 15:59:50 +00004775 // Split out the predication code and carry setting flag from the mnemonic.
4776 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004777 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004778 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004779 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004780 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004781 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004782
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004783 // In Thumb1, only the branch (B) instruction can be predicated.
4784 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4785 Parser.EatToEndOfStatement();
4786 return Error(NameLoc, "conditional execution not supported in Thumb1");
4787 }
4788
Jim Grosbachffa32252011-07-19 19:13:28 +00004789 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4790
Jim Grosbach89df9962011-08-26 21:43:41 +00004791 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4792 // is the mask as it will be for the IT encoding if the conditional
4793 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4794 // where the conditional bit0 is zero, the instruction post-processing
4795 // will adjust the mask accordingly.
4796 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004797 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4798 if (ITMask.size() > 3) {
4799 Parser.EatToEndOfStatement();
4800 return Error(Loc, "too many conditions on IT instruction");
4801 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004802 unsigned Mask = 8;
4803 for (unsigned i = ITMask.size(); i != 0; --i) {
4804 char pos = ITMask[i - 1];
4805 if (pos != 't' && pos != 'e') {
4806 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004807 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004808 }
4809 Mask >>= 1;
4810 if (ITMask[i - 1] == 't')
4811 Mask |= 8;
4812 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004813 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004814 }
4815
Jim Grosbachffa32252011-07-19 19:13:28 +00004816 // FIXME: This is all a pretty gross hack. We should automatically handle
4817 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004818
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004819 // Next, add the CCOut and ConditionCode operands, if needed.
4820 //
4821 // For mnemonics which can ever incorporate a carry setting bit or predication
4822 // code, our matching model involves us always generating CCOut and
4823 // ConditionCode operands to match the mnemonic "as written" and then we let
4824 // the matcher deal with finding the right instruction or generating an
4825 // appropriate error.
4826 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004827 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004828
Jim Grosbach33c16a22011-07-14 22:04:21 +00004829 // If we had a carry-set on an instruction that can't do that, issue an
4830 // error.
4831 if (!CanAcceptCarrySet && CarrySetting) {
4832 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004833 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004834 "' can not set flags, but 's' suffix specified");
4835 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004836 // If we had a predication code on an instruction that can't do that, issue an
4837 // error.
4838 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4839 Parser.EatToEndOfStatement();
4840 return Error(NameLoc, "instruction '" + Mnemonic +
4841 "' is not predicable, but condition code specified");
4842 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004843
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004844 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004845 if (CanAcceptCarrySet) {
4846 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004847 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004848 Loc));
4849 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004850
4851 // Add the predication code operand, if necessary.
4852 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004853 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4854 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004855 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004856 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004857 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004858
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004859 // Add the processor imod operand, if necessary.
4860 if (ProcessorIMod) {
4861 Operands.push_back(ARMOperand::CreateImm(
4862 MCConstantExpr::Create(ProcessorIMod, getContext()),
4863 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004864 }
4865
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004866 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004867 while (Next != StringRef::npos) {
4868 Start = Next;
4869 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004870 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004871
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004872 // Some NEON instructions have an optional datatype suffix that is
4873 // completely ignored. Check for that.
4874 if (isDataTypeToken(ExtraToken) &&
4875 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4876 continue;
4877
Jim Grosbach81d2e392011-09-07 16:06:04 +00004878 if (ExtraToken != ".n") {
4879 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4880 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4881 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004882 }
4883
4884 // Read the remaining operands.
4885 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004886 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004887 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004888 Parser.EatToEndOfStatement();
4889 return true;
4890 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004891
4892 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004893 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004894
4895 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004896 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004897 Parser.EatToEndOfStatement();
4898 return true;
4899 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004900 }
4901 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004902
Chris Lattnercbf8a982010-09-11 16:18:25 +00004903 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004904 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004905 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004906 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004907 }
Bill Wendling146018f2010-11-06 21:42:12 +00004908
Chris Lattner34e53142010-09-08 05:10:46 +00004909 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004910
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004911 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4912 // do and don't have a cc_out optional-def operand. With some spot-checks
4913 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004914 // parse and adjust accordingly before actually matching. We shouldn't ever
4915 // try to remove a cc_out operand that was explicitly set on the the
4916 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4917 // table driven matcher doesn't fit well with the ARM instruction set.
4918 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004919 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4920 Operands.erase(Operands.begin() + 1);
4921 delete Op;
4922 }
4923
Jim Grosbachcf121c32011-07-28 21:57:55 +00004924 // ARM mode 'blx' need special handling, as the register operand version
4925 // is predicable, but the label operand version is not. So, we can't rely
4926 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004927 // a k_CondCode operand in the list. If we're trying to match the label
4928 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004929 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4930 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4931 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4932 Operands.erase(Operands.begin() + 1);
4933 delete Op;
4934 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004935
4936 // The vector-compare-to-zero instructions have a literal token "#0" at
4937 // the end that comes to here as an immediate operand. Convert it to a
4938 // token to play nicely with the matcher.
4939 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4940 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4941 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4942 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4943 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4944 if (CE && CE->getValue() == 0) {
4945 Operands.erase(Operands.begin() + 5);
4946 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4947 delete Op;
4948 }
4949 }
Jim Grosbach68259142011-10-03 22:30:24 +00004950 // VCMP{E} does the same thing, but with a different operand count.
4951 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4952 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4953 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4954 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4955 if (CE && CE->getValue() == 0) {
4956 Operands.erase(Operands.begin() + 4);
4957 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4958 delete Op;
4959 }
4960 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004961 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004962 // end. Convert it to a token here. Take care not to convert those
4963 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004964 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004965 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4966 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004967 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4968 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4969 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004970 if (CE && CE->getValue() == 0 &&
4971 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004972 // The cc_out operand matches the IT block.
4973 ((inITBlock() != CarrySetting) &&
4974 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004975 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004976 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004977 Operands.erase(Operands.begin() + 5);
4978 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4979 delete Op;
4980 }
4981 }
4982
Chris Lattner98986712010-01-14 22:21:20 +00004983 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004984}
4985
Jim Grosbach189610f2011-07-26 18:25:39 +00004986// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004987
4988// return 'true' if register list contains non-low GPR registers,
4989// 'false' otherwise. If Reg is in the register list or is HiReg, set
4990// 'containsReg' to true.
4991static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4992 unsigned HiReg, bool &containsReg) {
4993 containsReg = false;
4994 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4995 unsigned OpReg = Inst.getOperand(i).getReg();
4996 if (OpReg == Reg)
4997 containsReg = true;
4998 // Anything other than a low register isn't legal here.
4999 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5000 return true;
5001 }
5002 return false;
5003}
5004
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005005// Check if the specified regisgter is in the register list of the inst,
5006// starting at the indicated operand number.
5007static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5008 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5009 unsigned OpReg = Inst.getOperand(i).getReg();
5010 if (OpReg == Reg)
5011 return true;
5012 }
5013 return false;
5014}
5015
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005016// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5017// the ARMInsts array) instead. Getting that here requires awkward
5018// API changes, though. Better way?
5019namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005020extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005021}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005022static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005023 return ARMInsts[Opcode];
5024}
5025
Jim Grosbach189610f2011-07-26 18:25:39 +00005026// FIXME: We would really like to be able to tablegen'erate this.
5027bool ARMAsmParser::
5028validateInstruction(MCInst &Inst,
5029 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005030 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005031 SMLoc Loc = Operands[0]->getStartLoc();
5032 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005033 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5034 // being allowed in IT blocks, but not being predicable. It just always
5035 // executes.
5036 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005037 unsigned bit = 1;
5038 if (ITState.FirstCond)
5039 ITState.FirstCond = false;
5040 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005041 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005042 // The instruction must be predicable.
5043 if (!MCID.isPredicable())
5044 return Error(Loc, "instructions in IT block must be predicable");
5045 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5046 unsigned ITCond = bit ? ITState.Cond :
5047 ARMCC::getOppositeCondition(ITState.Cond);
5048 if (Cond != ITCond) {
5049 // Find the condition code Operand to get its SMLoc information.
5050 SMLoc CondLoc;
5051 for (unsigned i = 1; i < Operands.size(); ++i)
5052 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5053 CondLoc = Operands[i]->getStartLoc();
5054 return Error(CondLoc, "incorrect condition in IT block; got '" +
5055 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5056 "', but expected '" +
5057 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5058 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005059 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005060 } else if (isThumbTwo() && MCID.isPredicable() &&
5061 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005062 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5063 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005064 return Error(Loc, "predicated instructions must be in IT block");
5065
Jim Grosbach189610f2011-07-26 18:25:39 +00005066 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005067 case ARM::LDRD:
5068 case ARM::LDRD_PRE:
5069 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005070 case ARM::LDREXD: {
5071 // Rt2 must be Rt + 1.
5072 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5073 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5074 if (Rt2 != Rt + 1)
5075 return Error(Operands[3]->getStartLoc(),
5076 "destination operands must be sequential");
5077 return false;
5078 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005079 case ARM::STRD: {
5080 // Rt2 must be Rt + 1.
5081 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5082 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5083 if (Rt2 != Rt + 1)
5084 return Error(Operands[3]->getStartLoc(),
5085 "source operands must be sequential");
5086 return false;
5087 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005088 case ARM::STRD_PRE:
5089 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005090 case ARM::STREXD: {
5091 // Rt2 must be Rt + 1.
5092 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5093 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5094 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005095 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005096 "source operands must be sequential");
5097 return false;
5098 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005099 case ARM::SBFX:
5100 case ARM::UBFX: {
5101 // width must be in range [1, 32-lsb]
5102 unsigned lsb = Inst.getOperand(2).getImm();
5103 unsigned widthm1 = Inst.getOperand(3).getImm();
5104 if (widthm1 >= 32 - lsb)
5105 return Error(Operands[5]->getStartLoc(),
5106 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005107 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005108 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005109 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005110 // If we're parsing Thumb2, the .w variant is available and handles
5111 // most cases that are normally illegal for a Thumb1 LDM
5112 // instruction. We'll make the transformation in processInstruction()
5113 // if necessary.
5114 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005115 // Thumb LDM instructions are writeback iff the base register is not
5116 // in the register list.
5117 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005118 bool hasWritebackToken =
5119 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5120 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005121 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005122 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005123 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5124 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005125 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005126 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005127 return Error(Operands[2]->getStartLoc(),
5128 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005129 // If we should not have writeback, there must not be a '!'. This is
5130 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005131 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005132 return Error(Operands[3]->getStartLoc(),
5133 "writeback operator '!' not allowed when base register "
5134 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005135
5136 break;
5137 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005138 case ARM::t2LDMIA_UPD: {
5139 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5140 return Error(Operands[4]->getStartLoc(),
5141 "writeback operator '!' not allowed when base register "
5142 "in register list");
5143 break;
5144 }
Jim Grosbach54026372011-11-10 23:17:11 +00005145 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5146 // so only issue a diagnostic for thumb1. The instructions will be
5147 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005148 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005149 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005150 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5151 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005152 return Error(Operands[2]->getStartLoc(),
5153 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005154 break;
5155 }
5156 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005157 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005158 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5159 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005160 return Error(Operands[2]->getStartLoc(),
5161 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005162 break;
5163 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005164 case ARM::tSTMIA_UPD: {
5165 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005166 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005167 return Error(Operands[4]->getStartLoc(),
5168 "registers must be in range r0-r7");
5169 break;
5170 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005171 }
5172
5173 return false;
5174}
5175
Jim Grosbachd7433e22012-01-23 23:45:44 +00005176static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005177 switch(Opc) {
5178 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005179 // VST1LN
Jim Grosbach8b31f952012-01-23 19:39:08 +00005180 case ARM::VST1LNdWB_fixed_Asm_8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005181 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005182 return ARM::VST1LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005183 case ARM::VST1LNdWB_fixed_Asm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005184 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005185 return ARM::VST1LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005186 case ARM::VST1LNdWB_fixed_Asm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005187 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005188 return ARM::VST1LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005189 case ARM::VST1LNdWB_register_Asm_8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005190 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005191 return ARM::VST1LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005192 case ARM::VST1LNdWB_register_Asm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005193 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005194 return ARM::VST1LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005195 case ARM::VST1LNdWB_register_Asm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005196 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005197 return ARM::VST1LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005198 case ARM::VST1LNdAsm_8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005199 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005200 return ARM::VST1LNd8;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005201 case ARM::VST1LNdAsm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005202 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005203 return ARM::VST1LNd16;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005204 case ARM::VST1LNdAsm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005205 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005206 return ARM::VST1LNd32;
5207
5208 // VST2LN
Jim Grosbach8b31f952012-01-23 19:39:08 +00005209 case ARM::VST2LNdWB_fixed_Asm_8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005210 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005211 return ARM::VST2LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005212 case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005213 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005214 return ARM::VST2LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005215 case ARM::VST2LNdWB_fixed_Asm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005216 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005217 return ARM::VST2LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005218 case ARM::VST2LNqWB_fixed_Asm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005219 Spacing = 2;
5220 return ARM::VST2LNq16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005221 case ARM::VST2LNqWB_fixed_Asm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005222 Spacing = 2;
5223 return ARM::VST2LNq32_UPD;
5224
Jim Grosbach8b31f952012-01-23 19:39:08 +00005225 case ARM::VST2LNdWB_register_Asm_8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005226 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005227 return ARM::VST2LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005228 case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005229 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005230 return ARM::VST2LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005231 case ARM::VST2LNdWB_register_Asm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005232 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005233 return ARM::VST2LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005234 case ARM::VST2LNqWB_register_Asm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005235 Spacing = 2;
5236 return ARM::VST2LNq16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005237 case ARM::VST2LNqWB_register_Asm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005238 Spacing = 2;
5239 return ARM::VST2LNq32_UPD;
5240
Jim Grosbach8b31f952012-01-23 19:39:08 +00005241 case ARM::VST2LNdAsm_8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005242 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005243 return ARM::VST2LNd8;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005244 case ARM::VST2LNdAsm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005245 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005246 return ARM::VST2LNd16;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005247 case ARM::VST2LNdAsm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005248 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005249 return ARM::VST2LNd32;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005250 case ARM::VST2LNqAsm_16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005251 Spacing = 2;
5252 return ARM::VST2LNq16;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005253 case ARM::VST2LNqAsm_32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005254 Spacing = 2;
5255 return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005256
5257 // VST3
5258 case ARM::VST3dWB_fixed_Asm_8:
5259 Spacing = 1;
5260 return ARM::VST3d8_UPD;
5261 case ARM::VST3dWB_fixed_Asm_16:
5262 Spacing = 1;
5263 return ARM::VST3d16_UPD;
5264 case ARM::VST3dWB_fixed_Asm_32:
5265 Spacing = 1;
5266 return ARM::VST3d32_UPD;
5267 case ARM::VST3qWB_fixed_Asm_8:
5268 Spacing = 2;
5269 return ARM::VST3q8_UPD;
5270 case ARM::VST3qWB_fixed_Asm_16:
5271 Spacing = 2;
5272 return ARM::VST3q16_UPD;
5273 case ARM::VST3qWB_fixed_Asm_32:
5274 Spacing = 2;
5275 return ARM::VST3q32_UPD;
5276 case ARM::VST3dWB_register_Asm_8:
5277 Spacing = 1;
5278 return ARM::VST3d8_UPD;
5279 case ARM::VST3dWB_register_Asm_16:
5280 Spacing = 1;
5281 return ARM::VST3d16_UPD;
5282 case ARM::VST3dWB_register_Asm_32:
5283 Spacing = 1;
5284 return ARM::VST3d32_UPD;
5285 case ARM::VST3qWB_register_Asm_8:
5286 Spacing = 2;
5287 return ARM::VST3q8_UPD;
5288 case ARM::VST3qWB_register_Asm_16:
5289 Spacing = 2;
5290 return ARM::VST3q16_UPD;
5291 case ARM::VST3qWB_register_Asm_32:
5292 Spacing = 2;
5293 return ARM::VST3q32_UPD;
5294 case ARM::VST3dAsm_8:
5295 Spacing = 1;
5296 return ARM::VST3d8;
5297 case ARM::VST3dAsm_16:
5298 Spacing = 1;
5299 return ARM::VST3d16;
5300 case ARM::VST3dAsm_32:
5301 Spacing = 1;
5302 return ARM::VST3d32;
5303 case ARM::VST3qAsm_8:
5304 Spacing = 2;
5305 return ARM::VST3q8;
5306 case ARM::VST3qAsm_16:
5307 Spacing = 2;
5308 return ARM::VST3q16;
5309 case ARM::VST3qAsm_32:
5310 Spacing = 2;
5311 return ARM::VST3q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005312 }
5313}
5314
Jim Grosbachd7433e22012-01-23 23:45:44 +00005315static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005316 switch(Opc) {
5317 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005318 // VLD1LN
Jim Grosbach8b31f952012-01-23 19:39:08 +00005319 case ARM::VLD1LNdWB_fixed_Asm_8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005320 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005321 return ARM::VLD1LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005322 case ARM::VLD1LNdWB_fixed_Asm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005323 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005324 return ARM::VLD1LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005325 case ARM::VLD1LNdWB_fixed_Asm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005326 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005327 return ARM::VLD1LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005328 case ARM::VLD1LNdWB_register_Asm_8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005329 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005330 return ARM::VLD1LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005331 case ARM::VLD1LNdWB_register_Asm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005332 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005333 return ARM::VLD1LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005334 case ARM::VLD1LNdWB_register_Asm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005335 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005336 return ARM::VLD1LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005337 case ARM::VLD1LNdAsm_8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005338 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005339 return ARM::VLD1LNd8;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005340 case ARM::VLD1LNdAsm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005341 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005342 return ARM::VLD1LNd16;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005343 case ARM::VLD1LNdAsm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005344 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005345 return ARM::VLD1LNd32;
5346
5347 // VLD2LN
Jim Grosbach8b31f952012-01-23 19:39:08 +00005348 case ARM::VLD2LNdWB_fixed_Asm_8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005349 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005350 return ARM::VLD2LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005351 case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005352 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005353 return ARM::VLD2LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005354 case ARM::VLD2LNdWB_fixed_Asm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005355 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005356 return ARM::VLD2LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005357 case ARM::VLD2LNqWB_fixed_Asm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005358 Spacing = 1;
5359 return ARM::VLD2LNq16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005360 case ARM::VLD2LNqWB_fixed_Asm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005361 Spacing = 2;
5362 return ARM::VLD2LNq32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005363 case ARM::VLD2LNdWB_register_Asm_8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005364 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005365 return ARM::VLD2LNd8_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005366 case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005367 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005368 return ARM::VLD2LNd16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005369 case ARM::VLD2LNdWB_register_Asm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005370 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005371 return ARM::VLD2LNd32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005372 case ARM::VLD2LNqWB_register_Asm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005373 Spacing = 2;
5374 return ARM::VLD2LNq16_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005375 case ARM::VLD2LNqWB_register_Asm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005376 Spacing = 2;
5377 return ARM::VLD2LNq32_UPD;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005378 case ARM::VLD2LNdAsm_8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005379 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005380 return ARM::VLD2LNd8;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005381 case ARM::VLD2LNdAsm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005382 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005383 return ARM::VLD2LNd16;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005384 case ARM::VLD2LNdAsm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005385 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005386 return ARM::VLD2LNd32;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005387 case ARM::VLD2LNqAsm_16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005388 Spacing = 2;
5389 return ARM::VLD2LNq16;
Jim Grosbach8b31f952012-01-23 19:39:08 +00005390 case ARM::VLD2LNqAsm_32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005391 Spacing = 2;
5392 return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005393
5394 // VLD3LN
5395 case ARM::VLD3LNdWB_fixed_Asm_8:
5396 Spacing = 1;
5397 return ARM::VLD3LNd8_UPD;
5398 case ARM::VLD3LNdWB_fixed_Asm_16:
5399 Spacing = 1;
5400 return ARM::VLD3LNd16_UPD;
5401 case ARM::VLD3LNdWB_fixed_Asm_32:
5402 Spacing = 1;
5403 return ARM::VLD3LNd32_UPD;
5404 case ARM::VLD3LNqWB_fixed_Asm_16:
5405 Spacing = 1;
5406 return ARM::VLD3LNq16_UPD;
5407 case ARM::VLD3LNqWB_fixed_Asm_32:
5408 Spacing = 2;
5409 return ARM::VLD3LNq32_UPD;
5410 case ARM::VLD3LNdWB_register_Asm_8:
5411 Spacing = 1;
5412 return ARM::VLD3LNd8_UPD;
5413 case ARM::VLD3LNdWB_register_Asm_16:
5414 Spacing = 1;
5415 return ARM::VLD3LNd16_UPD;
5416 case ARM::VLD3LNdWB_register_Asm_32:
5417 Spacing = 1;
5418 return ARM::VLD3LNd32_UPD;
5419 case ARM::VLD3LNqWB_register_Asm_16:
5420 Spacing = 2;
5421 return ARM::VLD3LNq16_UPD;
5422 case ARM::VLD3LNqWB_register_Asm_32:
5423 Spacing = 2;
5424 return ARM::VLD3LNq32_UPD;
5425 case ARM::VLD3LNdAsm_8:
5426 Spacing = 1;
5427 return ARM::VLD3LNd8;
5428 case ARM::VLD3LNdAsm_16:
5429 Spacing = 1;
5430 return ARM::VLD3LNd16;
5431 case ARM::VLD3LNdAsm_32:
5432 Spacing = 1;
5433 return ARM::VLD3LNd32;
5434 case ARM::VLD3LNqAsm_16:
5435 Spacing = 2;
5436 return ARM::VLD3LNq16;
5437 case ARM::VLD3LNqAsm_32:
5438 Spacing = 2;
5439 return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005440
5441 // VLD3
5442 case ARM::VLD3dWB_fixed_Asm_8:
5443 Spacing = 1;
5444 return ARM::VLD3d8_UPD;
5445 case ARM::VLD3dWB_fixed_Asm_16:
5446 Spacing = 1;
5447 return ARM::VLD3d16_UPD;
5448 case ARM::VLD3dWB_fixed_Asm_32:
5449 Spacing = 1;
5450 return ARM::VLD3d32_UPD;
5451 case ARM::VLD3qWB_fixed_Asm_8:
5452 Spacing = 2;
5453 return ARM::VLD3q8_UPD;
5454 case ARM::VLD3qWB_fixed_Asm_16:
5455 Spacing = 2;
5456 return ARM::VLD3q16_UPD;
5457 case ARM::VLD3qWB_fixed_Asm_32:
5458 Spacing = 2;
5459 return ARM::VLD3q32_UPD;
5460 case ARM::VLD3dWB_register_Asm_8:
5461 Spacing = 1;
5462 return ARM::VLD3d8_UPD;
5463 case ARM::VLD3dWB_register_Asm_16:
5464 Spacing = 1;
5465 return ARM::VLD3d16_UPD;
5466 case ARM::VLD3dWB_register_Asm_32:
5467 Spacing = 1;
5468 return ARM::VLD3d32_UPD;
5469 case ARM::VLD3qWB_register_Asm_8:
5470 Spacing = 2;
5471 return ARM::VLD3q8_UPD;
5472 case ARM::VLD3qWB_register_Asm_16:
5473 Spacing = 2;
5474 return ARM::VLD3q16_UPD;
5475 case ARM::VLD3qWB_register_Asm_32:
5476 Spacing = 2;
5477 return ARM::VLD3q32_UPD;
5478 case ARM::VLD3dAsm_8:
5479 Spacing = 1;
5480 return ARM::VLD3d8;
5481 case ARM::VLD3dAsm_16:
5482 Spacing = 1;
5483 return ARM::VLD3d16;
5484 case ARM::VLD3dAsm_32:
5485 Spacing = 1;
5486 return ARM::VLD3d32;
5487 case ARM::VLD3qAsm_8:
5488 Spacing = 2;
5489 return ARM::VLD3q8;
5490 case ARM::VLD3qAsm_16:
5491 Spacing = 2;
5492 return ARM::VLD3q16;
5493 case ARM::VLD3qAsm_32:
5494 Spacing = 2;
5495 return ARM::VLD3q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005496 }
5497}
5498
Jim Grosbach83ec8772011-11-10 23:42:14 +00005499bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005500processInstruction(MCInst &Inst,
5501 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5502 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005503 // Aliases for alternate PC+imm syntax of LDR instructions.
5504 case ARM::t2LDRpcrel:
5505 Inst.setOpcode(ARM::t2LDRpci);
5506 return true;
5507 case ARM::t2LDRBpcrel:
5508 Inst.setOpcode(ARM::t2LDRBpci);
5509 return true;
5510 case ARM::t2LDRHpcrel:
5511 Inst.setOpcode(ARM::t2LDRHpci);
5512 return true;
5513 case ARM::t2LDRSBpcrel:
5514 Inst.setOpcode(ARM::t2LDRSBpci);
5515 return true;
5516 case ARM::t2LDRSHpcrel:
5517 Inst.setOpcode(ARM::t2LDRSHpci);
5518 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005519 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005520 case ARM::VST1LNdWB_register_Asm_8:
5521 case ARM::VST1LNdWB_register_Asm_16:
5522 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005523 MCInst TmpInst;
5524 // Shuffle the operands around so the lane index operand is in the
5525 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005526 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005527 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005528 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5529 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5530 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5531 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5532 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5533 TmpInst.addOperand(Inst.getOperand(1)); // lane
5534 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5535 TmpInst.addOperand(Inst.getOperand(6));
5536 Inst = TmpInst;
5537 return true;
5538 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005539
Jim Grosbach8b31f952012-01-23 19:39:08 +00005540 case ARM::VST2LNdWB_register_Asm_8:
5541 case ARM::VST2LNdWB_register_Asm_16:
5542 case ARM::VST2LNdWB_register_Asm_32:
5543 case ARM::VST2LNqWB_register_Asm_16:
5544 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005545 MCInst TmpInst;
5546 // Shuffle the operands around so the lane index operand is in the
5547 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005548 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005549 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005550 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5551 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5552 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5553 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5554 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005555 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5556 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005557 TmpInst.addOperand(Inst.getOperand(1)); // lane
5558 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5559 TmpInst.addOperand(Inst.getOperand(6));
5560 Inst = TmpInst;
5561 return true;
5562 }
Jim Grosbach8b31f952012-01-23 19:39:08 +00005563 case ARM::VST1LNdWB_fixed_Asm_8:
5564 case ARM::VST1LNdWB_fixed_Asm_16:
5565 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005566 MCInst TmpInst;
5567 // Shuffle the operands around so the lane index operand is in the
5568 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005569 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005570 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005571 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5572 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5573 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5574 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5575 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5576 TmpInst.addOperand(Inst.getOperand(1)); // lane
5577 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5578 TmpInst.addOperand(Inst.getOperand(5));
5579 Inst = TmpInst;
5580 return true;
5581 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005582
Jim Grosbach8b31f952012-01-23 19:39:08 +00005583 case ARM::VST2LNdWB_fixed_Asm_8:
5584 case ARM::VST2LNdWB_fixed_Asm_16:
5585 case ARM::VST2LNdWB_fixed_Asm_32:
5586 case ARM::VST2LNqWB_fixed_Asm_16:
5587 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005588 MCInst TmpInst;
5589 // Shuffle the operands around so the lane index operand is in the
5590 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005591 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005592 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005593 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5594 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5595 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5596 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5597 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005598 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5599 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005600 TmpInst.addOperand(Inst.getOperand(1)); // lane
5601 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5602 TmpInst.addOperand(Inst.getOperand(5));
5603 Inst = TmpInst;
5604 return true;
5605 }
Jim Grosbach8b31f952012-01-23 19:39:08 +00005606 case ARM::VST1LNdAsm_8:
5607 case ARM::VST1LNdAsm_16:
5608 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005609 MCInst TmpInst;
5610 // Shuffle the operands around so the lane index operand is in the
5611 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005612 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005613 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005614 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5615 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5616 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5617 TmpInst.addOperand(Inst.getOperand(1)); // lane
5618 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5619 TmpInst.addOperand(Inst.getOperand(5));
5620 Inst = TmpInst;
5621 return true;
5622 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005623
Jim Grosbach8b31f952012-01-23 19:39:08 +00005624 case ARM::VST2LNdAsm_8:
5625 case ARM::VST2LNdAsm_16:
5626 case ARM::VST2LNdAsm_32:
5627 case ARM::VST2LNqAsm_16:
5628 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005629 MCInst TmpInst;
5630 // Shuffle the operands around so the lane index operand is in the
5631 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005632 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005633 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005634 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5635 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5636 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005637 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5638 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005639 TmpInst.addOperand(Inst.getOperand(1)); // lane
5640 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5641 TmpInst.addOperand(Inst.getOperand(5));
5642 Inst = TmpInst;
5643 return true;
5644 }
5645 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005646 case ARM::VLD1LNdWB_register_Asm_8:
5647 case ARM::VLD1LNdWB_register_Asm_16:
5648 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005649 MCInst TmpInst;
5650 // Shuffle the operands around so the lane index operand is in the
5651 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005652 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005653 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005654 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5655 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5656 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5657 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5658 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5659 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5660 TmpInst.addOperand(Inst.getOperand(1)); // lane
5661 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5662 TmpInst.addOperand(Inst.getOperand(6));
5663 Inst = TmpInst;
5664 return true;
5665 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005666
Jim Grosbach8b31f952012-01-23 19:39:08 +00005667 case ARM::VLD2LNdWB_register_Asm_8:
5668 case ARM::VLD2LNdWB_register_Asm_16:
5669 case ARM::VLD2LNdWB_register_Asm_32:
5670 case ARM::VLD2LNqWB_register_Asm_16:
5671 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005672 MCInst TmpInst;
5673 // Shuffle the operands around so the lane index operand is in the
5674 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005675 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005676 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005677 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005678 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5679 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005680 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5681 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5682 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5683 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5684 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005685 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5686 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005687 TmpInst.addOperand(Inst.getOperand(1)); // lane
5688 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5689 TmpInst.addOperand(Inst.getOperand(6));
5690 Inst = TmpInst;
5691 return true;
5692 }
5693
Jim Grosbach3a678af2012-01-23 21:53:26 +00005694 case ARM::VLD3LNdWB_register_Asm_8:
5695 case ARM::VLD3LNdWB_register_Asm_16:
5696 case ARM::VLD3LNdWB_register_Asm_32:
5697 case ARM::VLD3LNqWB_register_Asm_16:
5698 case ARM::VLD3LNqWB_register_Asm_32: {
5699 MCInst TmpInst;
5700 // Shuffle the operands around so the lane index operand is in the
5701 // right place.
5702 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005703 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005704 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5705 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5706 Spacing));
5707 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005708 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005709 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5710 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5711 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5712 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5713 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5714 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5715 Spacing));
5716 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005717 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005718 TmpInst.addOperand(Inst.getOperand(1)); // lane
5719 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5720 TmpInst.addOperand(Inst.getOperand(6));
5721 Inst = TmpInst;
5722 return true;
5723 }
5724
Jim Grosbach8b31f952012-01-23 19:39:08 +00005725 case ARM::VLD1LNdWB_fixed_Asm_8:
5726 case ARM::VLD1LNdWB_fixed_Asm_16:
5727 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005728 MCInst TmpInst;
5729 // Shuffle the operands around so the lane index operand is in the
5730 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005731 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005732 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005733 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5734 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5735 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5736 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5737 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5738 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5739 TmpInst.addOperand(Inst.getOperand(1)); // lane
5740 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5741 TmpInst.addOperand(Inst.getOperand(5));
5742 Inst = TmpInst;
5743 return true;
5744 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005745
Jim Grosbach8b31f952012-01-23 19:39:08 +00005746 case ARM::VLD2LNdWB_fixed_Asm_8:
5747 case ARM::VLD2LNdWB_fixed_Asm_16:
5748 case ARM::VLD2LNdWB_fixed_Asm_32:
5749 case ARM::VLD2LNqWB_fixed_Asm_16:
5750 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005751 MCInst TmpInst;
5752 // Shuffle the operands around so the lane index operand is in the
5753 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005754 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005755 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005756 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005757 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5758 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005759 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5760 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5761 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5762 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5763 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005764 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5765 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005766 TmpInst.addOperand(Inst.getOperand(1)); // lane
5767 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5768 TmpInst.addOperand(Inst.getOperand(5));
5769 Inst = TmpInst;
5770 return true;
5771 }
5772
Jim Grosbach3a678af2012-01-23 21:53:26 +00005773 case ARM::VLD3LNdWB_fixed_Asm_8:
5774 case ARM::VLD3LNdWB_fixed_Asm_16:
5775 case ARM::VLD3LNdWB_fixed_Asm_32:
5776 case ARM::VLD3LNqWB_fixed_Asm_16:
5777 case ARM::VLD3LNqWB_fixed_Asm_32: {
5778 MCInst TmpInst;
5779 // Shuffle the operands around so the lane index operand is in the
5780 // right place.
5781 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005782 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005783 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5784 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5785 Spacing));
5786 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005787 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005788 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5789 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5790 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5791 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5792 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5793 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5794 Spacing));
5795 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005796 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005797 TmpInst.addOperand(Inst.getOperand(1)); // lane
5798 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5799 TmpInst.addOperand(Inst.getOperand(5));
5800 Inst = TmpInst;
5801 return true;
5802 }
5803
Jim Grosbach8b31f952012-01-23 19:39:08 +00005804 case ARM::VLD1LNdAsm_8:
5805 case ARM::VLD1LNdAsm_16:
5806 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005807 MCInst TmpInst;
5808 // Shuffle the operands around so the lane index operand is in the
5809 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005810 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005811 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005812 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5813 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5814 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5815 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5816 TmpInst.addOperand(Inst.getOperand(1)); // lane
5817 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5818 TmpInst.addOperand(Inst.getOperand(5));
5819 Inst = TmpInst;
5820 return true;
5821 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005822
Jim Grosbach8b31f952012-01-23 19:39:08 +00005823 case ARM::VLD2LNdAsm_8:
5824 case ARM::VLD2LNdAsm_16:
5825 case ARM::VLD2LNdAsm_32:
5826 case ARM::VLD2LNqAsm_16:
5827 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005828 MCInst TmpInst;
5829 // Shuffle the operands around so the lane index operand is in the
5830 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005831 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005832 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005833 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005834 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5835 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005836 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5837 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5838 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005839 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5840 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005841 TmpInst.addOperand(Inst.getOperand(1)); // lane
5842 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5843 TmpInst.addOperand(Inst.getOperand(5));
5844 Inst = TmpInst;
5845 return true;
5846 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00005847
5848 case ARM::VLD3LNdAsm_8:
5849 case ARM::VLD3LNdAsm_16:
5850 case ARM::VLD3LNdAsm_32:
5851 case ARM::VLD3LNqAsm_16:
5852 case ARM::VLD3LNqAsm_32: {
5853 MCInst TmpInst;
5854 // Shuffle the operands around so the lane index operand is in the
5855 // right place.
5856 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005857 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005858 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5859 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5860 Spacing));
5861 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005862 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005863 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5864 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5865 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5866 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5867 Spacing));
5868 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005869 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005870 TmpInst.addOperand(Inst.getOperand(1)); // lane
5871 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5872 TmpInst.addOperand(Inst.getOperand(5));
5873 Inst = TmpInst;
5874 return true;
5875 }
5876
Jim Grosbachc387fc62012-01-23 23:20:46 +00005877 // VLD3 multiple 3-element structure instructions.
5878 case ARM::VLD3dAsm_8:
5879 case ARM::VLD3dAsm_16:
5880 case ARM::VLD3dAsm_32:
5881 case ARM::VLD3qAsm_8:
5882 case ARM::VLD3qAsm_16:
5883 case ARM::VLD3qAsm_32: {
5884 MCInst TmpInst;
5885 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005886 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005887 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5888 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5889 Spacing));
5890 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5891 Spacing * 2));
5892 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5893 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5894 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5895 TmpInst.addOperand(Inst.getOperand(4));
5896 Inst = TmpInst;
5897 return true;
5898 }
5899
5900 case ARM::VLD3dWB_fixed_Asm_8:
5901 case ARM::VLD3dWB_fixed_Asm_16:
5902 case ARM::VLD3dWB_fixed_Asm_32:
5903 case ARM::VLD3qWB_fixed_Asm_8:
5904 case ARM::VLD3qWB_fixed_Asm_16:
5905 case ARM::VLD3qWB_fixed_Asm_32: {
5906 MCInst TmpInst;
5907 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005908 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005909 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5910 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5911 Spacing));
5912 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5913 Spacing * 2));
5914 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5915 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5916 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5917 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5918 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5919 TmpInst.addOperand(Inst.getOperand(4));
5920 Inst = TmpInst;
5921 return true;
5922 }
5923
5924 case ARM::VLD3dWB_register_Asm_8:
5925 case ARM::VLD3dWB_register_Asm_16:
5926 case ARM::VLD3dWB_register_Asm_32:
5927 case ARM::VLD3qWB_register_Asm_8:
5928 case ARM::VLD3qWB_register_Asm_16:
5929 case ARM::VLD3qWB_register_Asm_32: {
5930 MCInst TmpInst;
5931 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005932 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005933 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5934 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5935 Spacing));
5936 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5937 Spacing * 2));
5938 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5939 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5940 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5941 TmpInst.addOperand(Inst.getOperand(3)); // Rm
5942 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5943 TmpInst.addOperand(Inst.getOperand(5));
5944 Inst = TmpInst;
5945 return true;
5946 }
5947
Jim Grosbachd7433e22012-01-23 23:45:44 +00005948 // VST3 multiple 3-element structure instructions.
5949 case ARM::VST3dAsm_8:
5950 case ARM::VST3dAsm_16:
5951 case ARM::VST3dAsm_32:
5952 case ARM::VST3qAsm_8:
5953 case ARM::VST3qAsm_16:
5954 case ARM::VST3qAsm_32: {
5955 MCInst TmpInst;
5956 unsigned Spacing;
5957 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5958 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5959 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5960 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5961 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5962 Spacing));
5963 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5964 Spacing * 2));
5965 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5966 TmpInst.addOperand(Inst.getOperand(4));
5967 Inst = TmpInst;
5968 return true;
5969 }
5970
5971 case ARM::VST3dWB_fixed_Asm_8:
5972 case ARM::VST3dWB_fixed_Asm_16:
5973 case ARM::VST3dWB_fixed_Asm_32:
5974 case ARM::VST3qWB_fixed_Asm_8:
5975 case ARM::VST3qWB_fixed_Asm_16:
5976 case ARM::VST3qWB_fixed_Asm_32: {
5977 MCInst TmpInst;
5978 unsigned Spacing;
5979 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5980 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5981 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
5982 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5983 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5984 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5985 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5986 Spacing));
5987 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5988 Spacing * 2));
5989 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5990 TmpInst.addOperand(Inst.getOperand(4));
5991 Inst = TmpInst;
5992 return true;
5993 }
5994
5995 case ARM::VST3dWB_register_Asm_8:
5996 case ARM::VST3dWB_register_Asm_16:
5997 case ARM::VST3dWB_register_Asm_32:
5998 case ARM::VST3qWB_register_Asm_8:
5999 case ARM::VST3qWB_register_Asm_16:
6000 case ARM::VST3qWB_register_Asm_32: {
6001 MCInst TmpInst;
6002 unsigned Spacing;
6003 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6004 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6005 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6006 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6007 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6008 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6009 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6010 Spacing));
6011 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6012 Spacing * 2));
6013 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6014 TmpInst.addOperand(Inst.getOperand(5));
6015 Inst = TmpInst;
6016 return true;
6017 }
6018
Jim Grosbach863d2af2011-12-13 22:45:11 +00006019 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006020 case ARM::t2MOVsr:
6021 case ARM::t2MOVSsr: {
6022 // Which instruction to expand to depends on the CCOut operand and
6023 // whether we're in an IT block if the register operands are low
6024 // registers.
6025 bool isNarrow = false;
6026 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6027 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6028 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6029 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6030 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6031 isNarrow = true;
6032 MCInst TmpInst;
6033 unsigned newOpc;
6034 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6035 default: llvm_unreachable("unexpected opcode!");
6036 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6037 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6038 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6039 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6040 }
6041 TmpInst.setOpcode(newOpc);
6042 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6043 if (isNarrow)
6044 TmpInst.addOperand(MCOperand::CreateReg(
6045 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6046 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6047 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6048 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6049 TmpInst.addOperand(Inst.getOperand(5));
6050 if (!isNarrow)
6051 TmpInst.addOperand(MCOperand::CreateReg(
6052 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6053 Inst = TmpInst;
6054 return true;
6055 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006056 case ARM::t2MOVsi:
6057 case ARM::t2MOVSsi: {
6058 // Which instruction to expand to depends on the CCOut operand and
6059 // whether we're in an IT block if the register operands are low
6060 // registers.
6061 bool isNarrow = false;
6062 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6063 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6064 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6065 isNarrow = true;
6066 MCInst TmpInst;
6067 unsigned newOpc;
6068 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6069 default: llvm_unreachable("unexpected opcode!");
6070 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6071 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6072 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6073 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006074 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006075 }
6076 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6077 if (Ammount == 32) Ammount = 0;
6078 TmpInst.setOpcode(newOpc);
6079 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6080 if (isNarrow)
6081 TmpInst.addOperand(MCOperand::CreateReg(
6082 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6083 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006084 if (newOpc != ARM::t2RRX)
6085 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006086 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6087 TmpInst.addOperand(Inst.getOperand(4));
6088 if (!isNarrow)
6089 TmpInst.addOperand(MCOperand::CreateReg(
6090 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6091 Inst = TmpInst;
6092 return true;
6093 }
6094 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006095 case ARM::ASRr:
6096 case ARM::LSRr:
6097 case ARM::LSLr:
6098 case ARM::RORr: {
6099 ARM_AM::ShiftOpc ShiftTy;
6100 switch(Inst.getOpcode()) {
6101 default: llvm_unreachable("unexpected opcode!");
6102 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6103 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6104 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6105 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6106 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006107 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6108 MCInst TmpInst;
6109 TmpInst.setOpcode(ARM::MOVsr);
6110 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6111 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6112 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6113 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6114 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6115 TmpInst.addOperand(Inst.getOperand(4));
6116 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6117 Inst = TmpInst;
6118 return true;
6119 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006120 case ARM::ASRi:
6121 case ARM::LSRi:
6122 case ARM::LSLi:
6123 case ARM::RORi: {
6124 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006125 switch(Inst.getOpcode()) {
6126 default: llvm_unreachable("unexpected opcode!");
6127 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6128 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6129 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6130 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6131 }
6132 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006133 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006134 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6135 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006136 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006137 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006138 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6139 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006140 if (Opc == ARM::MOVsi)
6141 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006142 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6143 TmpInst.addOperand(Inst.getOperand(4));
6144 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6145 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006146 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006147 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006148 case ARM::RRXi: {
6149 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6150 MCInst TmpInst;
6151 TmpInst.setOpcode(ARM::MOVsi);
6152 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6153 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6154 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6155 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6156 TmpInst.addOperand(Inst.getOperand(3));
6157 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6158 Inst = TmpInst;
6159 return true;
6160 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006161 case ARM::t2LDMIA_UPD: {
6162 // If this is a load of a single register, then we should use
6163 // a post-indexed LDR instruction instead, per the ARM ARM.
6164 if (Inst.getNumOperands() != 5)
6165 return false;
6166 MCInst TmpInst;
6167 TmpInst.setOpcode(ARM::t2LDR_POST);
6168 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6169 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6170 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6171 TmpInst.addOperand(MCOperand::CreateImm(4));
6172 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6173 TmpInst.addOperand(Inst.getOperand(3));
6174 Inst = TmpInst;
6175 return true;
6176 }
6177 case ARM::t2STMDB_UPD: {
6178 // If this is a store of a single register, then we should use
6179 // a pre-indexed STR instruction instead, per the ARM ARM.
6180 if (Inst.getNumOperands() != 5)
6181 return false;
6182 MCInst TmpInst;
6183 TmpInst.setOpcode(ARM::t2STR_PRE);
6184 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6185 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6186 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6187 TmpInst.addOperand(MCOperand::CreateImm(-4));
6188 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6189 TmpInst.addOperand(Inst.getOperand(3));
6190 Inst = TmpInst;
6191 return true;
6192 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006193 case ARM::LDMIA_UPD:
6194 // If this is a load of a single register via a 'pop', then we should use
6195 // a post-indexed LDR instruction instead, per the ARM ARM.
6196 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6197 Inst.getNumOperands() == 5) {
6198 MCInst TmpInst;
6199 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6200 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6201 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6202 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6203 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6204 TmpInst.addOperand(MCOperand::CreateImm(4));
6205 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6206 TmpInst.addOperand(Inst.getOperand(3));
6207 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006208 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006209 }
6210 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006211 case ARM::STMDB_UPD:
6212 // If this is a store of a single register via a 'push', then we should use
6213 // a pre-indexed STR instruction instead, per the ARM ARM.
6214 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6215 Inst.getNumOperands() == 5) {
6216 MCInst TmpInst;
6217 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6218 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6219 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6220 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6221 TmpInst.addOperand(MCOperand::CreateImm(-4));
6222 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6223 TmpInst.addOperand(Inst.getOperand(3));
6224 Inst = TmpInst;
6225 }
6226 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006227 case ARM::t2ADDri12:
6228 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6229 // mnemonic was used (not "addw"), encoding T3 is preferred.
6230 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6231 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6232 break;
6233 Inst.setOpcode(ARM::t2ADDri);
6234 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6235 break;
6236 case ARM::t2SUBri12:
6237 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6238 // mnemonic was used (not "subw"), encoding T3 is preferred.
6239 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6240 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6241 break;
6242 Inst.setOpcode(ARM::t2SUBri);
6243 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6244 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006245 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006246 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6247 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6248 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6249 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006250 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006251 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006252 return true;
6253 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006254 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006255 case ARM::tSUBi8:
6256 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6257 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6258 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6259 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006260 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006261 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006262 return true;
6263 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006264 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006265 case ARM::t2ADDrr: {
6266 // If the destination and first source operand are the same, and
6267 // there's no setting of the flags, use encoding T2 instead of T3.
6268 // Note that this is only for ADD, not SUB. This mirrors the system
6269 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6270 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6271 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006272 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6273 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006274 break;
6275 MCInst TmpInst;
6276 TmpInst.setOpcode(ARM::tADDhirr);
6277 TmpInst.addOperand(Inst.getOperand(0));
6278 TmpInst.addOperand(Inst.getOperand(0));
6279 TmpInst.addOperand(Inst.getOperand(2));
6280 TmpInst.addOperand(Inst.getOperand(3));
6281 TmpInst.addOperand(Inst.getOperand(4));
6282 Inst = TmpInst;
6283 return true;
6284 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006285 case ARM::tB:
6286 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006287 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006288 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006289 return true;
6290 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006291 break;
6292 case ARM::t2B:
6293 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006294 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006295 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006296 return true;
6297 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006298 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006299 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006300 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006301 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006302 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006303 return true;
6304 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006305 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006306 case ARM::tBcc:
6307 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006308 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006309 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006310 return true;
6311 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006312 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006313 case ARM::tLDMIA: {
6314 // If the register list contains any high registers, or if the writeback
6315 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6316 // instead if we're in Thumb2. Otherwise, this should have generated
6317 // an error in validateInstruction().
6318 unsigned Rn = Inst.getOperand(0).getReg();
6319 bool hasWritebackToken =
6320 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6321 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6322 bool listContainsBase;
6323 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6324 (!listContainsBase && !hasWritebackToken) ||
6325 (listContainsBase && hasWritebackToken)) {
6326 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6327 assert (isThumbTwo());
6328 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6329 // If we're switching to the updating version, we need to insert
6330 // the writeback tied operand.
6331 if (hasWritebackToken)
6332 Inst.insert(Inst.begin(),
6333 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006334 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006335 }
6336 break;
6337 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006338 case ARM::tSTMIA_UPD: {
6339 // If the register list contains any high registers, we need to use
6340 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6341 // should have generated an error in validateInstruction().
6342 unsigned Rn = Inst.getOperand(0).getReg();
6343 bool listContainsBase;
6344 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6345 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6346 assert (isThumbTwo());
6347 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006348 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006349 }
6350 break;
6351 }
Jim Grosbach54026372011-11-10 23:17:11 +00006352 case ARM::tPOP: {
6353 bool listContainsBase;
6354 // If the register list contains any high registers, we need to use
6355 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6356 // should have generated an error in validateInstruction().
6357 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006358 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006359 assert (isThumbTwo());
6360 Inst.setOpcode(ARM::t2LDMIA_UPD);
6361 // Add the base register and writeback operands.
6362 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6363 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006364 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006365 }
6366 case ARM::tPUSH: {
6367 bool listContainsBase;
6368 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006369 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006370 assert (isThumbTwo());
6371 Inst.setOpcode(ARM::t2STMDB_UPD);
6372 // Add the base register and writeback operands.
6373 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6374 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006375 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006376 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006377 case ARM::t2MOVi: {
6378 // If we can use the 16-bit encoding and the user didn't explicitly
6379 // request the 32-bit variant, transform it here.
6380 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6381 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006382 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6383 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6384 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006385 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6386 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6387 // The operands aren't in the same order for tMOVi8...
6388 MCInst TmpInst;
6389 TmpInst.setOpcode(ARM::tMOVi8);
6390 TmpInst.addOperand(Inst.getOperand(0));
6391 TmpInst.addOperand(Inst.getOperand(4));
6392 TmpInst.addOperand(Inst.getOperand(1));
6393 TmpInst.addOperand(Inst.getOperand(2));
6394 TmpInst.addOperand(Inst.getOperand(3));
6395 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006396 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006397 }
6398 break;
6399 }
6400 case ARM::t2MOVr: {
6401 // If we can use the 16-bit encoding and the user didn't explicitly
6402 // request the 32-bit variant, transform it here.
6403 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6404 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6405 Inst.getOperand(2).getImm() == ARMCC::AL &&
6406 Inst.getOperand(4).getReg() == ARM::CPSR &&
6407 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6408 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6409 // The operands aren't the same for tMOV[S]r... (no cc_out)
6410 MCInst TmpInst;
6411 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6412 TmpInst.addOperand(Inst.getOperand(0));
6413 TmpInst.addOperand(Inst.getOperand(1));
6414 TmpInst.addOperand(Inst.getOperand(2));
6415 TmpInst.addOperand(Inst.getOperand(3));
6416 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006417 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006418 }
6419 break;
6420 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006421 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006422 case ARM::t2SXTB:
6423 case ARM::t2UXTH:
6424 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006425 // If we can use the 16-bit encoding and the user didn't explicitly
6426 // request the 32-bit variant, transform it here.
6427 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6428 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6429 Inst.getOperand(2).getImm() == 0 &&
6430 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6431 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006432 unsigned NewOpc;
6433 switch (Inst.getOpcode()) {
6434 default: llvm_unreachable("Illegal opcode!");
6435 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6436 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6437 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6438 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6439 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006440 // The operands aren't the same for thumb1 (no rotate operand).
6441 MCInst TmpInst;
6442 TmpInst.setOpcode(NewOpc);
6443 TmpInst.addOperand(Inst.getOperand(0));
6444 TmpInst.addOperand(Inst.getOperand(1));
6445 TmpInst.addOperand(Inst.getOperand(3));
6446 TmpInst.addOperand(Inst.getOperand(4));
6447 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006448 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006449 }
6450 break;
6451 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006452 case ARM::MOVsi: {
6453 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6454 if (SOpc == ARM_AM::rrx) return false;
6455 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6456 // Shifting by zero is accepted as a vanilla 'MOVr'
6457 MCInst TmpInst;
6458 TmpInst.setOpcode(ARM::MOVr);
6459 TmpInst.addOperand(Inst.getOperand(0));
6460 TmpInst.addOperand(Inst.getOperand(1));
6461 TmpInst.addOperand(Inst.getOperand(3));
6462 TmpInst.addOperand(Inst.getOperand(4));
6463 TmpInst.addOperand(Inst.getOperand(5));
6464 Inst = TmpInst;
6465 return true;
6466 }
6467 return false;
6468 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006469 case ARM::ANDrsi:
6470 case ARM::ORRrsi:
6471 case ARM::EORrsi:
6472 case ARM::BICrsi:
6473 case ARM::SUBrsi:
6474 case ARM::ADDrsi: {
6475 unsigned newOpc;
6476 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6477 if (SOpc == ARM_AM::rrx) return false;
6478 switch (Inst.getOpcode()) {
Matt Beaumont-Gay19055cc2012-01-03 19:03:59 +00006479 default: assert(0 && "unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006480 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6481 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6482 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6483 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6484 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6485 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6486 }
6487 // If the shift is by zero, use the non-shifted instruction definition.
6488 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6489 MCInst TmpInst;
6490 TmpInst.setOpcode(newOpc);
6491 TmpInst.addOperand(Inst.getOperand(0));
6492 TmpInst.addOperand(Inst.getOperand(1));
6493 TmpInst.addOperand(Inst.getOperand(2));
6494 TmpInst.addOperand(Inst.getOperand(4));
6495 TmpInst.addOperand(Inst.getOperand(5));
6496 TmpInst.addOperand(Inst.getOperand(6));
6497 Inst = TmpInst;
6498 return true;
6499 }
6500 return false;
6501 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006502 case ARM::t2IT: {
6503 // The mask bits for all but the first condition are represented as
6504 // the low bit of the condition code value implies 't'. We currently
6505 // always have 1 implies 't', so XOR toggle the bits if the low bit
6506 // of the condition code is zero. The encoding also expects the low
6507 // bit of the condition to be encoded as bit 4 of the mask operand,
6508 // so mask that in if needed
6509 MCOperand &MO = Inst.getOperand(1);
6510 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006511 unsigned OrigMask = Mask;
6512 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006513 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006514 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6515 for (unsigned i = 3; i != TZ; --i)
6516 Mask ^= 1 << i;
6517 } else
6518 Mask |= 0x10;
6519 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006520
6521 // Set up the IT block state according to the IT instruction we just
6522 // matched.
6523 assert(!inITBlock() && "nested IT blocks?!");
6524 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6525 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6526 ITState.CurPosition = 0;
6527 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006528 break;
6529 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006530 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006531 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006532}
6533
Jim Grosbach47a0d522011-08-16 20:45:50 +00006534unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6535 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6536 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006537 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006538 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006539 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6540 assert(MCID.hasOptionalDef() &&
6541 "optionally flag setting instruction missing optional def operand");
6542 assert(MCID.NumOperands == Inst.getNumOperands() &&
6543 "operand count mismatch!");
6544 // Find the optional-def operand (cc_out).
6545 unsigned OpNo;
6546 for (OpNo = 0;
6547 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6548 ++OpNo)
6549 ;
6550 // If we're parsing Thumb1, reject it completely.
6551 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6552 return Match_MnemonicFail;
6553 // If we're parsing Thumb2, which form is legal depends on whether we're
6554 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006555 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6556 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006557 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006558 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6559 inITBlock())
6560 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006561 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006562 // Some high-register supporting Thumb1 encodings only allow both registers
6563 // to be from r0-r7 when in Thumb2.
6564 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6565 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6566 isARMLowRegister(Inst.getOperand(2).getReg()))
6567 return Match_RequiresThumb2;
6568 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006569 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006570 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6571 isARMLowRegister(Inst.getOperand(1).getReg()))
6572 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006573 return Match_Success;
6574}
6575
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006576bool ARMAsmParser::
6577MatchAndEmitInstruction(SMLoc IDLoc,
6578 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6579 MCStreamer &Out) {
6580 MCInst Inst;
6581 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006582 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006583 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006584 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006585 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006586 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006587 // Context sensitive operand constraints aren't handled by the matcher,
6588 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006589 if (validateInstruction(Inst, Operands)) {
6590 // Still progress the IT block, otherwise one wrong condition causes
6591 // nasty cascading errors.
6592 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006593 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006594 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006595
Jim Grosbachf8fce712011-08-11 17:35:48 +00006596 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006597 // encoding is selected. Loop on it while changes happen so the
6598 // individual transformations can chain off each other. E.g.,
6599 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6600 while (processInstruction(Inst, Operands))
6601 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006602
Jim Grosbacha1109882011-09-02 23:22:08 +00006603 // Only move forward at the very end so that everything in validate
6604 // and process gets a consistent answer about whether we're in an IT
6605 // block.
6606 forwardITPosition();
6607
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006608 Out.EmitInstruction(Inst);
6609 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006610 case Match_MissingFeature:
6611 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6612 return true;
6613 case Match_InvalidOperand: {
6614 SMLoc ErrorLoc = IDLoc;
6615 if (ErrorInfo != ~0U) {
6616 if (ErrorInfo >= Operands.size())
6617 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006618
Chris Lattnere73d4f82010-10-28 21:41:58 +00006619 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6620 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6621 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006622
Chris Lattnere73d4f82010-10-28 21:41:58 +00006623 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006624 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006625 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006626 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006627 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006628 // The converter function will have already emited a diagnostic.
6629 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006630 case Match_RequiresNotITBlock:
6631 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006632 case Match_RequiresITBlock:
6633 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006634 case Match_RequiresV6:
6635 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6636 case Match_RequiresThumb2:
6637 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006638 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006639
Eric Christopherc223e2b2010-10-29 09:26:59 +00006640 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006641}
6642
Jim Grosbach1355cf12011-07-26 17:10:22 +00006643/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006644bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6645 StringRef IDVal = DirectiveID.getIdentifier();
6646 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006647 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006648 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006649 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006650 else if (IDVal == ".arm")
6651 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006652 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006653 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006654 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006655 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006656 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006657 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006658 else if (IDVal == ".unreq")
6659 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006660 else if (IDVal == ".arch")
6661 return parseDirectiveArch(DirectiveID.getLoc());
6662 else if (IDVal == ".eabi_attribute")
6663 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006664 return true;
6665}
6666
Jim Grosbach1355cf12011-07-26 17:10:22 +00006667/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006668/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006669bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6671 for (;;) {
6672 const MCExpr *Value;
6673 if (getParser().ParseExpression(Value))
6674 return true;
6675
Chris Lattneraaec2052010-01-19 19:46:13 +00006676 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006677
6678 if (getLexer().is(AsmToken::EndOfStatement))
6679 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006680
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006681 // FIXME: Improve diagnostic.
6682 if (getLexer().isNot(AsmToken::Comma))
6683 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006684 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006685 }
6686 }
6687
Sean Callananb9a25b72010-01-19 20:27:46 +00006688 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006689 return false;
6690}
6691
Jim Grosbach1355cf12011-07-26 17:10:22 +00006692/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006693/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006694bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006695 if (getLexer().isNot(AsmToken::EndOfStatement))
6696 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006697 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006698
Jim Grosbach9a70df92011-12-07 18:04:19 +00006699 if (!isThumb())
6700 SwitchMode();
6701 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6702 return false;
6703}
6704
6705/// parseDirectiveARM
6706/// ::= .arm
6707bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6708 if (getLexer().isNot(AsmToken::EndOfStatement))
6709 return Error(L, "unexpected token in directive");
6710 Parser.Lex();
6711
6712 if (isThumb())
6713 SwitchMode();
6714 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006715 return false;
6716}
6717
Jim Grosbach1355cf12011-07-26 17:10:22 +00006718/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006719/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006720bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006721 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6722 bool isMachO = MAI.hasSubsectionsViaSymbols();
6723 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006724 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006725
Jim Grosbachde4d8392011-12-21 22:30:16 +00006726 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006727 // ELF doesn't
6728 if (isMachO) {
6729 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006730 if (Tok.isNot(AsmToken::EndOfStatement)) {
6731 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6732 return Error(L, "unexpected token in .thumb_func directive");
6733 Name = Tok.getIdentifier();
6734 Parser.Lex(); // Consume the identifier token.
6735 needFuncName = false;
6736 }
Rafael Espindola64695402011-05-16 16:17:21 +00006737 }
6738
Jim Grosbachde4d8392011-12-21 22:30:16 +00006739 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006740 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006741
6742 // Eat the end of statement and any blank lines that follow.
6743 while (getLexer().is(AsmToken::EndOfStatement))
6744 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006745
Rafael Espindola64695402011-05-16 16:17:21 +00006746 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006747 // We really should be checking the next symbol definition even if there's
6748 // stuff in between.
6749 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006750 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006751 }
6752
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006753 // Mark symbol as a thumb symbol.
6754 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6755 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006756 return false;
6757}
6758
Jim Grosbach1355cf12011-07-26 17:10:22 +00006759/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006760/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006761bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006762 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006763 if (Tok.isNot(AsmToken::Identifier))
6764 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006765 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006766 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006767 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006768 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006769 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006770 else
6771 return Error(L, "unrecognized syntax mode in .syntax directive");
6772
6773 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006774 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006775 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006776
6777 // TODO tell the MC streamer the mode
6778 // getParser().getStreamer().Emit???();
6779 return false;
6780}
6781
Jim Grosbach1355cf12011-07-26 17:10:22 +00006782/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006783/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006784bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006785 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006786 if (Tok.isNot(AsmToken::Integer))
6787 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006788 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006789 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006790 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006791 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006792 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006793 else
6794 return Error(L, "invalid operand to .code directive");
6795
6796 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006797 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006798 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006799
Evan Cheng32869202011-07-08 22:36:29 +00006800 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006801 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006802 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006803 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006804 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006805 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006806 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006807 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006808 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006809
Kevin Enderby515d5092009-10-15 20:48:48 +00006810 return false;
6811}
6812
Jim Grosbacha39cda72011-12-14 02:16:11 +00006813/// parseDirectiveReq
6814/// ::= name .req registername
6815bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6816 Parser.Lex(); // Eat the '.req' token.
6817 unsigned Reg;
6818 SMLoc SRegLoc, ERegLoc;
6819 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6820 Parser.EatToEndOfStatement();
6821 return Error(SRegLoc, "register name expected");
6822 }
6823
6824 // Shouldn't be anything else.
6825 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6826 Parser.EatToEndOfStatement();
6827 return Error(Parser.getTok().getLoc(),
6828 "unexpected input in .req directive.");
6829 }
6830
6831 Parser.Lex(); // Consume the EndOfStatement
6832
6833 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6834 return Error(SRegLoc, "redefinition of '" + Name +
6835 "' does not match original.");
6836
6837 return false;
6838}
6839
6840/// parseDirectiveUneq
6841/// ::= .unreq registername
6842bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6843 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6844 Parser.EatToEndOfStatement();
6845 return Error(L, "unexpected input in .unreq directive.");
6846 }
6847 RegisterReqs.erase(Parser.getTok().getIdentifier());
6848 Parser.Lex(); // Eat the identifier.
6849 return false;
6850}
6851
Jason W Kimd7c9e082011-12-20 17:38:12 +00006852/// parseDirectiveArch
6853/// ::= .arch token
6854bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6855 return true;
6856}
6857
6858/// parseDirectiveEabiAttr
6859/// ::= .eabi_attribute int, int
6860bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6861 return true;
6862}
6863
Sean Callanan90b70972010-04-07 20:29:34 +00006864extern "C" void LLVMInitializeARMAsmLexer();
6865
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006866/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006867extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006868 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6869 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006870 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006871}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006872
Chris Lattner0692ee62010-09-06 19:11:01 +00006873#define GET_REGISTER_MATCHER
6874#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006875#include "ARMGenAsmMatcher.inc"