blob: 75e273a3441f1a3fd8e64a7b3d07e8d0c5c0a91e [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan76264762010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbach862019c2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendling8155e5b2010-11-06 22:19:43 +0000344 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000351
Jim Grosbach9d390362011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000400
Bill Wendling146018f2010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan76264762010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000425 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan76264762010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000479
Sean Callanan76264762010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Daniel Dunbar8462b302010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503 }
504
Bill Wendling5fa22a12010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000509 }
510
Kevin Enderbycfe07242009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000512 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbach9d390362011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbach460a9052011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000550 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
557 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000558 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
565 }
566 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
573 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000574 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 256;
581 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000582 bool isImm0_1() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 2;
589 }
590 bool isImm0_3() const {
591 if (Kind != k_Immediate)
592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 4;
597 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000598 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000600 return false;
601 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 Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 16;
613 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000614 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 32;
621 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 bool isImm0_63() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value >= 0 && Value < 64;
629 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000630 bool isImm8() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value == 16;
645 }
646 bool isImm32() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value == 32;
653 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000654 bool isShrImm8() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 8;
661 }
662 bool isShrImm16() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value <= 16;
669 }
670 bool isShrImm32() const {
671 if (Kind != k_Immediate)
672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value <= 32;
677 }
678 bool isShrImm64() const {
679 if (Kind != k_Immediate)
680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value > 0 && Value <= 64;
685 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000686 bool isImm1_7() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 8;
693 }
694 bool isImm1_15() const {
695 if (Kind != k_Immediate)
696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value > 0 && Value < 16;
701 }
702 bool isImm1_31() const {
703 if (Kind != k_Immediate)
704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value < 32;
709 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000710 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000712 return false;
713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 17;
717 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000718 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000720 return false;
721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
722 if (!CE) return false;
723 int64_t Value = CE->getValue();
724 return Value > 0 && Value < 33;
725 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000726 bool isImm0_32() const {
727 if (Kind != k_Immediate)
728 return false;
729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 33;
733 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000734 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 if (!CE) return false;
739 int64_t Value = CE->getValue();
740 return Value >= 0 && Value < 65536;
741 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000742 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000743 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000744 return false;
745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
746 // If it's not a constant expression, it'll generate a fixup and be
747 // handled later.
748 if (!CE) return true;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 65536;
751 }
Jim Grosbached838482011-07-26 16:24:27 +0000752 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return Value >= 0 && Value <= 0xffffff;
759 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000760 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return Value > 0 && Value < 33;
767 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000768 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value >= 0 && Value < 32;
775 }
776 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return Value > 0 && Value <= 32;
783 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000784 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000785 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getSOImmVal(Value) != -1;
791 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000792 bool isARMSOImmNot() const {
793 if (Kind != k_Immediate)
794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return ARM_AM::getSOImmVal(~Value) != -1;
799 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000800 bool isARMSOImmNeg() const {
801 if (Kind != k_Immediate)
802 return false;
803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getSOImmVal(-Value) != -1;
807 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000808 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000809 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000810 return false;
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 int64_t Value = CE->getValue();
814 return ARM_AM::getT2SOImmVal(Value) != -1;
815 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000816 bool isT2SOImmNot() const {
817 if (Kind != k_Immediate)
818 return false;
819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
820 if (!CE) return false;
821 int64_t Value = CE->getValue();
822 return ARM_AM::getT2SOImmVal(~Value) != -1;
823 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000824 bool isT2SOImmNeg() const {
825 if (Kind != k_Immediate)
826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return ARM_AM::getT2SOImmVal(-Value) != -1;
831 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000832 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000833 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000834 return false;
835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
838 return Value == 1 || Value == 0;
839 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000840 bool isReg() const { return Kind == k_Register; }
841 bool isRegList() const { return Kind == k_RegisterList; }
842 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
843 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
844 bool isToken() const { return Kind == k_Token; }
845 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
846 bool isMemory() const { return Kind == k_Memory; }
847 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
848 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
849 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
850 bool isRotImm() const { return Kind == k_RotateImmediate; }
851 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
852 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000853 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000854 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000855 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000857 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000858 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
861 (alignOK || Memory.Alignment == 0);
862 }
863 bool isAlignedMemory() const {
864 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000867 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000869 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000873 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000874 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000875 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000876 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000877 return false;
878 // Immediate offset in range [-4095, 4095].
879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
880 if (!CE) return false;
881 int64_t Val = CE->getValue();
882 return Val > -4096 && Val < 4096;
883 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000884 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000885 // If we have an immediate that's not a constant, treat it as a label
886 // reference needing a fixup. If it is a constant, it's something else
887 // and we reject it.
888 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
889 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000893 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000894 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000895 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000896 if (!Memory.OffsetImm) return true;
897 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000898 return Val > -256 && Val < 256;
899 }
900 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000901 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000902 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000903 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000904 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
905 // Immediate offset in range [-255, 255].
906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000909 // Special case, #-0 is INT32_MIN.
910 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000911 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
917 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000918 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000919 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000920 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000924 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000925 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000926 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000927 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000929 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000930 return false;
931 return true;
932 }
933 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000935 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
936 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000937 return false;
938 return true;
939 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000942 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000943 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000944 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000945 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
947 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000948 return false;
949 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000950 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000951 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000953 return false;
954 return true;
955 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000956 bool isMemThumbRR() const {
957 // Thumb reg+reg addressing is simple. Just two registers, a base and
958 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000959 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000960 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000961 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 return isARMLowRegister(Memory.BaseRegNum) &&
963 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000964 }
965 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000966 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000967 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000968 return false;
969 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000970 if (!Memory.OffsetImm) return true;
971 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000972 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
973 }
Jim Grosbach38466302011-08-19 18:55:51 +0000974 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000976 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000977 return false;
978 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000979 if (!Memory.OffsetImm) return true;
980 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000981 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
982 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000983 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000985 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000986 return false;
987 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000988 if (!Memory.OffsetImm) return true;
989 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000990 return Val >= 0 && Val <= 31;
991 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000992 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000993 if (!isMemory() || Memory.OffsetRegNum != 0 ||
994 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000995 return false;
996 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000999 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001000 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001001 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001002 // If we have an immediate that's not a constant, treat it as a label
1003 // reference needing a fixup. If it is a constant, it's something else
1004 // and we reject it.
1005 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
1006 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001007 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001008 return false;
1009 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001010 if (!Memory.OffsetImm) return true;
1011 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001012 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1013 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001014 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001015 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001016 return false;
1017 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001018 if (!Memory.OffsetImm) return true;
1019 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001020 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1021 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001022 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001023 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001024 return false;
1025 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001026 if (!Memory.OffsetImm) return true;
1027 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001028 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001029 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001030 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001032 return false;
1033 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001036 return Val >= 0 && Val < 256;
1037 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001038 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001040 return false;
1041 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001042 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001044 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001045 }
1046 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001048 return false;
1049 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001050 if (!Memory.OffsetImm) return true;
1051 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001052 return (Val >= 0 && Val < 4096);
1053 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001054 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001055 // If we have an immediate that's not a constant, treat it as a label
1056 // reference needing a fixup. If it is a constant, it's something else
1057 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001058 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001059 return true;
1060
Jim Grosbach57dcb852011-10-11 17:29:55 +00001061 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001062 return false;
1063 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001064 if (!Memory.OffsetImm) return true;
1065 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001066 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001067 }
1068 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001070 return false;
1071 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1072 if (!CE) return false;
1073 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001074 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001075 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001076 bool isPostIdxImm8s4() const {
1077 if (Kind != k_Immediate)
1078 return false;
1079 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1080 if (!CE) return false;
1081 int64_t Val = CE->getValue();
1082 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1083 (Val == INT32_MIN);
1084 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001085
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001086 bool isMSRMask() const { return Kind == k_MSRMask; }
1087 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001088
Jim Grosbach0e387b22011-10-17 22:26:03 +00001089 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 bool isSingleSpacedVectorList() const {
1091 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1092 }
1093 bool isDoubleSpacedVectorList() const {
1094 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1095 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001096 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001098 return VectorList.Count == 1;
1099 }
1100
Jim Grosbach280dfad2011-10-21 18:54:25 +00001101 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001103 return VectorList.Count == 2;
1104 }
1105
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001106 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001107 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001108 return VectorList.Count == 3;
1109 }
1110
Jim Grosbachb6310312011-10-21 20:35:01 +00001111 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001112 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001113 return VectorList.Count == 4;
1114 }
1115
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001116 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001117 if (!isDoubleSpacedVectorList()) return false;
1118 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001119 }
1120
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001121 bool isSingleSpacedVectorAllLanes() const {
1122 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1123 }
1124 bool isDoubleSpacedVectorAllLanes() const {
1125 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1126 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001127 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001128 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001129 return VectorList.Count == 1;
1130 }
1131
Jim Grosbach13af2222011-11-30 18:21:25 +00001132 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001133 if (!isSingleSpacedVectorAllLanes()) return false;
1134 return VectorList.Count == 2;
1135 }
1136
1137 bool isVecListTwoQAllLanes() const {
1138 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001139 return VectorList.Count == 2;
1140 }
1141
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001142 bool isSingleSpacedVectorIndexed() const {
1143 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1144 }
1145 bool isDoubleSpacedVectorIndexed() const {
1146 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1147 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001148 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001149 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001150 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1151 }
1152
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001153 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001154 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001155 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1156 }
1157
1158 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001159 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001160 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1161 }
1162
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001163 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001164 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001165 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1166 }
1167
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001168 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001169 if (!isSingleSpacedVectorIndexed()) return false;
1170 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1171 }
1172
1173 bool isVecListTwoQWordIndexed() const {
1174 if (!isDoubleSpacedVectorIndexed()) return false;
1175 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1176 }
1177
1178 bool isVecListTwoQHWordIndexed() const {
1179 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001180 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1181 }
1182
1183 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001184 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001185 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1186 }
1187
Jim Grosbach460a9052011-10-07 23:56:00 +00001188 bool isVectorIndex8() const {
1189 if (Kind != k_VectorIndex) return false;
1190 return VectorIndex.Val < 8;
1191 }
1192 bool isVectorIndex16() const {
1193 if (Kind != k_VectorIndex) return false;
1194 return VectorIndex.Val < 4;
1195 }
1196 bool isVectorIndex32() const {
1197 if (Kind != k_VectorIndex) return false;
1198 return VectorIndex.Val < 2;
1199 }
1200
Jim Grosbach0e387b22011-10-17 22:26:03 +00001201 bool isNEONi8splat() const {
1202 if (Kind != k_Immediate)
1203 return false;
1204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1205 // Must be a constant.
1206 if (!CE) return false;
1207 int64_t Value = CE->getValue();
1208 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1209 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001210 return Value >= 0 && Value < 256;
1211 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001212
Jim Grosbachea461102011-10-17 23:09:09 +00001213 bool isNEONi16splat() const {
1214 if (Kind != k_Immediate)
1215 return false;
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 // Must be a constant.
1218 if (!CE) return false;
1219 int64_t Value = CE->getValue();
1220 // i16 value in the range [0,255] or [0x0100, 0xff00]
1221 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1222 }
1223
Jim Grosbach6248a542011-10-18 00:22:00 +00001224 bool isNEONi32splat() const {
1225 if (Kind != k_Immediate)
1226 return false;
1227 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1228 // Must be a constant.
1229 if (!CE) return false;
1230 int64_t Value = CE->getValue();
1231 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1232 return (Value >= 0 && Value < 256) ||
1233 (Value >= 0x0100 && Value <= 0xff00) ||
1234 (Value >= 0x010000 && Value <= 0xff0000) ||
1235 (Value >= 0x01000000 && Value <= 0xff000000);
1236 }
1237
1238 bool isNEONi32vmov() const {
1239 if (Kind != k_Immediate)
1240 return false;
1241 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1242 // Must be a constant.
1243 if (!CE) return false;
1244 int64_t Value = CE->getValue();
1245 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1246 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1247 return (Value >= 0 && Value < 256) ||
1248 (Value >= 0x0100 && Value <= 0xff00) ||
1249 (Value >= 0x010000 && Value <= 0xff0000) ||
1250 (Value >= 0x01000000 && Value <= 0xff000000) ||
1251 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1252 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1253 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001254 bool isNEONi32vmovNeg() const {
1255 if (Kind != k_Immediate)
1256 return false;
1257 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1258 // Must be a constant.
1259 if (!CE) return false;
1260 int64_t Value = ~CE->getValue();
1261 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1262 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1263 return (Value >= 0 && Value < 256) ||
1264 (Value >= 0x0100 && Value <= 0xff00) ||
1265 (Value >= 0x010000 && Value <= 0xff0000) ||
1266 (Value >= 0x01000000 && Value <= 0xff000000) ||
1267 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1268 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1269 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001270
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001271 bool isNEONi64splat() const {
1272 if (Kind != k_Immediate)
1273 return false;
1274 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1275 // Must be a constant.
1276 if (!CE) return false;
1277 uint64_t Value = CE->getValue();
1278 // i64 value with each byte being either 0 or 0xff.
1279 for (unsigned i = 0; i < 8; ++i)
1280 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1281 return true;
1282 }
1283
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001284 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001285 // Add as immediates when possible. Null MCExpr = 0.
1286 if (Expr == 0)
1287 Inst.addOperand(MCOperand::CreateImm(0));
1288 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001289 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1290 else
1291 Inst.addOperand(MCOperand::CreateExpr(Expr));
1292 }
1293
Daniel Dunbar8462b302010-08-11 06:36:53 +00001294 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001295 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001296 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001297 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1298 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001299 }
1300
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001301 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1302 assert(N == 1 && "Invalid number of operands!");
1303 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1304 }
1305
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001306 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
1308 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1309 }
1310
1311 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1312 assert(N == 1 && "Invalid number of operands!");
1313 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1314 }
1315
Jim Grosbach89df9962011-08-26 21:43:41 +00001316 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
1318 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1319 }
1320
1321 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
1323 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1324 }
1325
Jim Grosbachd67641b2010-12-06 18:21:12 +00001326 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1327 assert(N == 1 && "Invalid number of operands!");
1328 Inst.addOperand(MCOperand::CreateReg(getReg()));
1329 }
1330
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001331 void addRegOperands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
1333 Inst.addOperand(MCOperand::CreateReg(getReg()));
1334 }
1335
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001336 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001337 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001338 assert(isRegShiftedReg() &&
1339 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001340 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1341 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001342 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001343 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001344 }
1345
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001346 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001347 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001348 assert(isRegShiftedImm() &&
1349 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001350 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001351 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001352 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001353 }
1354
Jim Grosbach580f4a92011-07-25 22:20:28 +00001355 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001356 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001357 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1358 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001359 }
1360
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001361 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001362 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001363 const SmallVectorImpl<unsigned> &RegList = getRegList();
1364 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001365 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1366 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001367 }
1368
Bill Wendling0f630752010-11-17 04:32:08 +00001369 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1370 addRegListOperands(Inst, N);
1371 }
1372
1373 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1374 addRegListOperands(Inst, N);
1375 }
1376
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001377 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1380 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1381 }
1382
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001383 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 // Munge the lsb/width into a bitfield mask.
1386 unsigned lsb = Bitfield.LSB;
1387 unsigned width = Bitfield.Width;
1388 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1389 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1390 (32 - (lsb + width)));
1391 Inst.addOperand(MCOperand::CreateImm(Mask));
1392 }
1393
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001394 void addImmOperands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
1396 addExpr(Inst, getImm());
1397 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001398
Jim Grosbach9d390362011-10-03 23:38:36 +00001399 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1402 }
1403
Jim Grosbacha77295d2011-09-08 22:07:06 +00001404 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 // FIXME: We really want to scale the value here, but the LDRD/STRD
1407 // instruction don't encode operands that way yet.
1408 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1409 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1410 }
1411
Jim Grosbach72f39f82011-08-24 21:22:15 +00001412 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
1414 // The immediate is scaled by four in the encoding and is stored
1415 // in the MCInst as such. Lop off the low two bits here.
1416 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1417 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1418 }
1419
1420 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
1422 // The immediate is scaled by four in the encoding and is stored
1423 // in the MCInst as such. Lop off the low two bits here.
1424 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1425 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1426 }
1427
Jim Grosbachf4943352011-07-25 23:09:14 +00001428 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
1430 // The constant encodes as the immediate-1, and we store in the instruction
1431 // the bits as encoded, so subtract off one here.
1432 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1433 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1434 }
1435
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001436 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 // The constant encodes as the immediate-1, and we store in the instruction
1439 // the bits as encoded, so subtract off one here.
1440 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1441 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1442 }
1443
Jim Grosbach70939ee2011-08-17 21:51:27 +00001444 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 // The constant encodes as the immediate, except for 32, which encodes as
1447 // zero.
1448 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1449 unsigned Imm = CE->getValue();
1450 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1451 }
1452
Jim Grosbachf6c05252011-07-21 17:23:04 +00001453 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1456 // the instruction as well.
1457 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1458 int Val = CE->getValue();
1459 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1460 }
1461
Jim Grosbach89a63372011-10-28 22:36:30 +00001462 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
1464 // The operand is actually a t2_so_imm, but we have its bitwise
1465 // negation in the assembly source, so twiddle it here.
1466 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1467 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1468 }
1469
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001470 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
1472 // The operand is actually a t2_so_imm, but we have its
1473 // negation in the assembly source, so twiddle it here.
1474 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1475 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1476 }
1477
Jim Grosbache70ec842011-10-28 22:50:54 +00001478 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 // The operand is actually a so_imm, but we have its bitwise
1481 // negation in the assembly source, so twiddle it here.
1482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1484 }
1485
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001486 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 // The operand is actually a so_imm, but we have its
1489 // negation in the assembly source, so twiddle it here.
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1492 }
1493
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001494 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1497 }
1498
Jim Grosbach7ce05792011-08-03 23:50:40 +00001499 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001501 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001502 }
1503
Jim Grosbach57dcb852011-10-11 17:29:55 +00001504 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
1506 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1507 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1508 }
1509
Jim Grosbach7ce05792011-08-03 23:50:40 +00001510 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001512 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1513 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001514 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1515 // Special case for #-0
1516 if (Val == INT32_MIN) Val = 0;
1517 if (Val < 0) Val = -Val;
1518 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1519 } else {
1520 // For register offset, we encode the shift type and negation flag
1521 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001522 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1523 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001524 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001525 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1526 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001527 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001528 }
1529
Jim Grosbach039c2e12011-08-04 23:01:30 +00001530 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
1532 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1533 assert(CE && "non-constant AM2OffsetImm operand!");
1534 int32_t Val = CE->getValue();
1535 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1536 // Special case for #-0
1537 if (Val == INT32_MIN) Val = 0;
1538 if (Val < 0) Val = -Val;
1539 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1540 Inst.addOperand(MCOperand::CreateReg(0));
1541 Inst.addOperand(MCOperand::CreateImm(Val));
1542 }
1543
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001544 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1545 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001546 // If we have an immediate that's not a constant, treat it as a label
1547 // reference needing a fixup. If it is a constant, it's something else
1548 // and we reject it.
1549 if (isImm()) {
1550 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1551 Inst.addOperand(MCOperand::CreateReg(0));
1552 Inst.addOperand(MCOperand::CreateImm(0));
1553 return;
1554 }
1555
Jim Grosbache53c87b2011-10-11 15:59:20 +00001556 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1557 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001558 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1559 // Special case for #-0
1560 if (Val == INT32_MIN) Val = 0;
1561 if (Val < 0) Val = -Val;
1562 Val = ARM_AM::getAM3Opc(AddSub, Val);
1563 } else {
1564 // For register offset, we encode the shift type and negation flag
1565 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001566 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001567 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001568 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1569 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001570 Inst.addOperand(MCOperand::CreateImm(Val));
1571 }
1572
1573 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001575 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001576 int32_t Val =
1577 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1578 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1579 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001580 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001581 }
1582
1583 // Constant offset.
1584 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1585 int32_t Val = CE->getValue();
1586 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1587 // Special case for #-0
1588 if (Val == INT32_MIN) Val = 0;
1589 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001590 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001591 Inst.addOperand(MCOperand::CreateReg(0));
1592 Inst.addOperand(MCOperand::CreateImm(Val));
1593 }
1594
Jim Grosbach7ce05792011-08-03 23:50:40 +00001595 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1596 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001597 // If we have an immediate that's not a constant, treat it as a label
1598 // reference needing a fixup. If it is a constant, it's something else
1599 // and we reject it.
1600 if (isImm()) {
1601 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1602 Inst.addOperand(MCOperand::CreateImm(0));
1603 return;
1604 }
1605
Jim Grosbach7ce05792011-08-03 23:50:40 +00001606 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001607 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001608 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1609 // Special case for #-0
1610 if (Val == INT32_MIN) Val = 0;
1611 if (Val < 0) Val = -Val;
1612 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001613 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001614 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001615 }
1616
Jim Grosbacha77295d2011-09-08 22:07:06 +00001617 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1618 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001619 // If we have an immediate that's not a constant, treat it as a label
1620 // reference needing a fixup. If it is a constant, it's something else
1621 // and we reject it.
1622 if (isImm()) {
1623 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1624 Inst.addOperand(MCOperand::CreateImm(0));
1625 return;
1626 }
1627
Jim Grosbache53c87b2011-10-11 15:59:20 +00001628 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001630 Inst.addOperand(MCOperand::CreateImm(Val));
1631 }
1632
Jim Grosbachb6aed502011-09-09 18:37:27 +00001633 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1634 assert(N == 2 && "Invalid number of operands!");
1635 // 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;
1637 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001638 Inst.addOperand(MCOperand::CreateImm(Val));
1639 }
1640
Jim Grosbach7ce05792011-08-03 23:50:40 +00001641 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1642 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001643 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1644 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001645 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001646 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001647
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001648 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1649 addMemImm8OffsetOperands(Inst, N);
1650 }
1651
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001652 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001653 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001654 }
1655
1656 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1657 assert(N == 2 && "Invalid number of operands!");
1658 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001659 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001660 addExpr(Inst, getImm());
1661 Inst.addOperand(MCOperand::CreateImm(0));
1662 return;
1663 }
1664
1665 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001666 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1667 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001668 Inst.addOperand(MCOperand::CreateImm(Val));
1669 }
1670
Jim Grosbach7ce05792011-08-03 23:50:40 +00001671 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1672 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001673 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001674 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001675 addExpr(Inst, getImm());
1676 Inst.addOperand(MCOperand::CreateImm(0));
1677 return;
1678 }
1679
1680 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001681 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1682 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001683 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001684 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001685
Jim Grosbach7f739be2011-09-19 22:21:13 +00001686 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1687 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001688 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1689 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001690 }
1691
1692 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001694 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1695 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001696 }
1697
Jim Grosbach7ce05792011-08-03 23:50:40 +00001698 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1699 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001700 unsigned Val =
1701 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1702 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001703 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1704 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001705 Inst.addOperand(MCOperand::CreateImm(Val));
1706 }
1707
Jim Grosbachab899c12011-09-07 23:10:15 +00001708 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1709 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001710 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1711 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1712 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001713 }
1714
Jim Grosbach7ce05792011-08-03 23:50:40 +00001715 void addMemThumbRROperands(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 Grosbach7ce05792011-08-03 23:50:40 +00001719 }
1720
Jim Grosbach60f91a32011-08-19 17:55:24 +00001721 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1722 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001723 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1724 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001725 Inst.addOperand(MCOperand::CreateImm(Val));
1726 }
1727
Jim Grosbach38466302011-08-19 18:55:51 +00001728 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1729 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001730 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1731 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001732 Inst.addOperand(MCOperand::CreateImm(Val));
1733 }
1734
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001735 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1736 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001737 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1738 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001739 Inst.addOperand(MCOperand::CreateImm(Val));
1740 }
1741
Jim Grosbachecd85892011-08-19 18:13:48 +00001742 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1743 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001744 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1745 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001746 Inst.addOperand(MCOperand::CreateImm(Val));
1747 }
1748
Jim Grosbach7ce05792011-08-03 23:50:40 +00001749 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1752 assert(CE && "non-constant post-idx-imm8 operand!");
1753 int Imm = CE->getValue();
1754 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001755 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001756 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1757 Inst.addOperand(MCOperand::CreateImm(Imm));
1758 }
1759
Jim Grosbach2bd01182011-10-11 21:55:36 +00001760 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1761 assert(N == 1 && "Invalid number of operands!");
1762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1763 assert(CE && "non-constant post-idx-imm8s4 operand!");
1764 int Imm = CE->getValue();
1765 bool isAdd = Imm >= 0;
1766 if (Imm == INT32_MIN) Imm = 0;
1767 // Immediate is scaled by 4.
1768 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1769 Inst.addOperand(MCOperand::CreateImm(Imm));
1770 }
1771
Jim Grosbach7ce05792011-08-03 23:50:40 +00001772 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1773 assert(N == 2 && "Invalid number of operands!");
1774 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001775 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1776 }
1777
1778 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1779 assert(N == 2 && "Invalid number of operands!");
1780 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1781 // The sign, shift type, and shift amount are encoded in a single operand
1782 // using the AM2 encoding helpers.
1783 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1784 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1785 PostIdxReg.ShiftTy);
1786 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001787 }
1788
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001789 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1790 assert(N == 1 && "Invalid number of operands!");
1791 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1792 }
1793
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001794 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 1 && "Invalid number of operands!");
1796 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1797 }
1798
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001799 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001800 assert(N == 1 && "Invalid number of operands!");
1801 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1802 }
1803
Jim Grosbach7636bf62011-12-02 00:35:16 +00001804 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1805 assert(N == 2 && "Invalid number of operands!");
1806 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1807 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1808 }
1809
Jim Grosbach460a9052011-10-07 23:56:00 +00001810 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1811 assert(N == 1 && "Invalid number of operands!");
1812 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1813 }
1814
1815 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1816 assert(N == 1 && "Invalid number of operands!");
1817 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1818 }
1819
1820 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1821 assert(N == 1 && "Invalid number of operands!");
1822 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1823 }
1824
Jim Grosbach0e387b22011-10-17 22:26:03 +00001825 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1826 assert(N == 1 && "Invalid number of operands!");
1827 // The immediate encodes the type of constant as well as the value.
1828 // Mask in that this is an i8 splat.
1829 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1830 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1831 }
1832
Jim Grosbachea461102011-10-17 23:09:09 +00001833 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1834 assert(N == 1 && "Invalid number of operands!");
1835 // The immediate encodes the type of constant as well as the value.
1836 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1837 unsigned Value = CE->getValue();
1838 if (Value >= 256)
1839 Value = (Value >> 8) | 0xa00;
1840 else
1841 Value |= 0x800;
1842 Inst.addOperand(MCOperand::CreateImm(Value));
1843 }
1844
Jim Grosbach6248a542011-10-18 00:22:00 +00001845 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1846 assert(N == 1 && "Invalid number of operands!");
1847 // The immediate encodes the type of constant as well as the value.
1848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1849 unsigned Value = CE->getValue();
1850 if (Value >= 256 && Value <= 0xff00)
1851 Value = (Value >> 8) | 0x200;
1852 else if (Value > 0xffff && Value <= 0xff0000)
1853 Value = (Value >> 16) | 0x400;
1854 else if (Value > 0xffffff)
1855 Value = (Value >> 24) | 0x600;
1856 Inst.addOperand(MCOperand::CreateImm(Value));
1857 }
1858
1859 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1860 assert(N == 1 && "Invalid number of operands!");
1861 // The immediate encodes the type of constant as well as the value.
1862 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1863 unsigned Value = CE->getValue();
1864 if (Value >= 256 && Value <= 0xffff)
1865 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1866 else if (Value > 0xffff && Value <= 0xffffff)
1867 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1868 else if (Value > 0xffffff)
1869 Value = (Value >> 24) | 0x600;
1870 Inst.addOperand(MCOperand::CreateImm(Value));
1871 }
1872
Jim Grosbach9b087852011-12-19 23:51:07 +00001873 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1874 assert(N == 1 && "Invalid number of operands!");
1875 // The immediate encodes the type of constant as well as the value.
1876 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1877 unsigned Value = ~CE->getValue();
1878 if (Value >= 256 && Value <= 0xffff)
1879 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1880 else if (Value > 0xffff && Value <= 0xffffff)
1881 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1882 else if (Value > 0xffffff)
1883 Value = (Value >> 24) | 0x600;
1884 Inst.addOperand(MCOperand::CreateImm(Value));
1885 }
1886
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001887 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1888 assert(N == 1 && "Invalid number of operands!");
1889 // The immediate encodes the type of constant as well as the value.
1890 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1891 uint64_t Value = CE->getValue();
1892 unsigned Imm = 0;
1893 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1894 Imm |= (Value & 1) << i;
1895 }
1896 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1897 }
1898
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001899 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001900
Jim Grosbach89df9962011-08-26 21:43:41 +00001901 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001902 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001903 Op->ITMask.Mask = Mask;
1904 Op->StartLoc = S;
1905 Op->EndLoc = S;
1906 return Op;
1907 }
1908
Chris Lattner3a697562010-10-28 17:20:03 +00001909 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001911 Op->CC.Val = CC;
1912 Op->StartLoc = S;
1913 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001914 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001915 }
1916
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001917 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001919 Op->Cop.Val = CopVal;
1920 Op->StartLoc = S;
1921 Op->EndLoc = S;
1922 return Op;
1923 }
1924
1925 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001927 Op->Cop.Val = CopVal;
1928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
1932
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001933 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1934 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1935 Op->Cop.Val = Val;
1936 Op->StartLoc = S;
1937 Op->EndLoc = E;
1938 return Op;
1939 }
1940
Jim Grosbachd67641b2010-12-06 18:21:12 +00001941 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001942 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001943 Op->Reg.RegNum = RegNum;
1944 Op->StartLoc = S;
1945 Op->EndLoc = S;
1946 return Op;
1947 }
1948
Chris Lattner3a697562010-10-28 17:20:03 +00001949 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001950 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001951 Op->Tok.Data = Str.data();
1952 Op->Tok.Length = Str.size();
1953 Op->StartLoc = S;
1954 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001955 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001956 }
1957
Bill Wendling50d0f582010-11-18 23:43:05 +00001958 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001960 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001961 Op->StartLoc = S;
1962 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001963 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001964 }
1965
Jim Grosbache8606dc2011-07-13 17:50:29 +00001966 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1967 unsigned SrcReg,
1968 unsigned ShiftReg,
1969 unsigned ShiftImm,
1970 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001971 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001972 Op->RegShiftedReg.ShiftTy = ShTy;
1973 Op->RegShiftedReg.SrcReg = SrcReg;
1974 Op->RegShiftedReg.ShiftReg = ShiftReg;
1975 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001976 Op->StartLoc = S;
1977 Op->EndLoc = E;
1978 return Op;
1979 }
1980
Owen Anderson92a20222011-07-21 18:54:16 +00001981 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1982 unsigned SrcReg,
1983 unsigned ShiftImm,
1984 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001986 Op->RegShiftedImm.ShiftTy = ShTy;
1987 Op->RegShiftedImm.SrcReg = SrcReg;
1988 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001989 Op->StartLoc = S;
1990 Op->EndLoc = E;
1991 return Op;
1992 }
1993
Jim Grosbach580f4a92011-07-25 22:20:28 +00001994 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001995 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001996 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001997 Op->ShifterImm.isASR = isASR;
1998 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001999 Op->StartLoc = S;
2000 Op->EndLoc = E;
2001 return Op;
2002 }
2003
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002004 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002005 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002006 Op->RotImm.Imm = Imm;
2007 Op->StartLoc = S;
2008 Op->EndLoc = E;
2009 return Op;
2010 }
2011
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002012 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2013 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002014 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002015 Op->Bitfield.LSB = LSB;
2016 Op->Bitfield.Width = Width;
2017 Op->StartLoc = S;
2018 Op->EndLoc = E;
2019 return Op;
2020 }
2021
Bill Wendling7729e062010-11-09 22:44:22 +00002022 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002023 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002024 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002025 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002026
Jim Grosbachd300b942011-09-13 22:56:44 +00002027 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002028 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002029 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002030 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002031 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002032
2033 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002034 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002035 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002036 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002037 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002038 Op->StartLoc = StartLoc;
2039 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002040 return Op;
2041 }
2042
Jim Grosbach862019c2011-10-18 23:02:30 +00002043 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002044 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002045 ARMOperand *Op = new ARMOperand(k_VectorList);
2046 Op->VectorList.RegNum = RegNum;
2047 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002048 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002049 Op->StartLoc = S;
2050 Op->EndLoc = E;
2051 return Op;
2052 }
2053
Jim Grosbach98b05a52011-11-30 01:09:44 +00002054 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002055 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002056 SMLoc S, SMLoc E) {
2057 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2058 Op->VectorList.RegNum = RegNum;
2059 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002060 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002061 Op->StartLoc = S;
2062 Op->EndLoc = E;
2063 return Op;
2064 }
2065
Jim Grosbach7636bf62011-12-02 00:35:16 +00002066 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002067 unsigned Index,
2068 bool isDoubleSpaced,
2069 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002070 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2071 Op->VectorList.RegNum = RegNum;
2072 Op->VectorList.Count = Count;
2073 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002074 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002075 Op->StartLoc = S;
2076 Op->EndLoc = E;
2077 return Op;
2078 }
2079
Jim Grosbach460a9052011-10-07 23:56:00 +00002080 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2081 MCContext &Ctx) {
2082 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2083 Op->VectorIndex.Val = Idx;
2084 Op->StartLoc = S;
2085 Op->EndLoc = E;
2086 return Op;
2087 }
2088
Chris Lattner3a697562010-10-28 17:20:03 +00002089 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002090 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002091 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002092 Op->StartLoc = S;
2093 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002094 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002095 }
2096
Jim Grosbach9d390362011-10-03 23:38:36 +00002097 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002098 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002099 Op->FPImm.Val = Val;
2100 Op->StartLoc = S;
2101 Op->EndLoc = S;
2102 return Op;
2103 }
2104
Jim Grosbach7ce05792011-08-03 23:50:40 +00002105 static ARMOperand *CreateMem(unsigned BaseRegNum,
2106 const MCConstantExpr *OffsetImm,
2107 unsigned OffsetRegNum,
2108 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002109 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002110 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002111 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002112 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002113 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002114 Op->Memory.BaseRegNum = BaseRegNum;
2115 Op->Memory.OffsetImm = OffsetImm;
2116 Op->Memory.OffsetRegNum = OffsetRegNum;
2117 Op->Memory.ShiftType = ShiftType;
2118 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002119 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002120 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002121 Op->StartLoc = S;
2122 Op->EndLoc = E;
2123 return Op;
2124 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002125
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002126 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2127 ARM_AM::ShiftOpc ShiftTy,
2128 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002129 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002130 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002131 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002132 Op->PostIdxReg.isAdd = isAdd;
2133 Op->PostIdxReg.ShiftTy = ShiftTy;
2134 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002135 Op->StartLoc = S;
2136 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002137 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002138 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002139
2140 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002141 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002142 Op->MBOpt.Val = Opt;
2143 Op->StartLoc = S;
2144 Op->EndLoc = S;
2145 return Op;
2146 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002147
2148 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002149 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002150 Op->IFlags.Val = IFlags;
2151 Op->StartLoc = S;
2152 Op->EndLoc = S;
2153 return Op;
2154 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002155
2156 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002157 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002158 Op->MMask.Val = MMask;
2159 Op->StartLoc = S;
2160 Op->EndLoc = S;
2161 return Op;
2162 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002163};
2164
2165} // end anonymous namespace.
2166
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002167void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002168 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002169 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002170 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2171 << ") >";
2172 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002173 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002174 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002175 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002176 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002177 OS << "<ccout " << getReg() << ">";
2178 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002179 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002180 static const char *MaskStr[] = {
2181 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2182 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2183 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002184 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2185 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2186 break;
2187 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002188 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002189 OS << "<coprocessor number: " << getCoproc() << ">";
2190 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002191 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002192 OS << "<coprocessor register: " << getCoproc() << ">";
2193 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002194 case k_CoprocOption:
2195 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2196 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002197 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002198 OS << "<mask: " << getMSRMask() << ">";
2199 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002200 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002201 getImm()->print(OS);
2202 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002203 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002204 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2205 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002206 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002207 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002208 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002209 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002210 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002211 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002212 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2213 << PostIdxReg.RegNum;
2214 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2215 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2216 << PostIdxReg.ShiftImm;
2217 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002218 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002219 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002220 OS << "<ARM_PROC::";
2221 unsigned IFlags = getProcIFlags();
2222 for (int i=2; i >= 0; --i)
2223 if (IFlags & (1 << i))
2224 OS << ARM_PROC::IFlagsToString(1 << i);
2225 OS << ">";
2226 break;
2227 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002229 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002230 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002231 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002232 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2233 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002234 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002235 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002236 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002237 << RegShiftedReg.SrcReg << " "
2238 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2239 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002240 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002241 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002242 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002243 << RegShiftedImm.SrcReg << " "
2244 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2245 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002246 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002247 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002248 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2249 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002250 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002251 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2252 << ", width: " << Bitfield.Width << ">";
2253 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002254 case k_RegisterList:
2255 case k_DPRRegisterList:
2256 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002257 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002258
Bill Wendling5fa22a12010-11-09 23:28:44 +00002259 const SmallVectorImpl<unsigned> &RegList = getRegList();
2260 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002261 I = RegList.begin(), E = RegList.end(); I != E; ) {
2262 OS << *I;
2263 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002264 }
2265
2266 OS << ">";
2267 break;
2268 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002269 case k_VectorList:
2270 OS << "<vector_list " << VectorList.Count << " * "
2271 << VectorList.RegNum << ">";
2272 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002273 case k_VectorListAllLanes:
2274 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2275 << VectorList.RegNum << ">";
2276 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002277 case k_VectorListIndexed:
2278 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2279 << VectorList.Count << " * " << VectorList.RegNum << ">";
2280 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002281 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002282 OS << "'" << getToken() << "'";
2283 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002284 case k_VectorIndex:
2285 OS << "<vectorindex " << getVectorIndex() << ">";
2286 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002287 }
2288}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002289
2290/// @name Auto-generated Match Functions
2291/// {
2292
2293static unsigned MatchRegisterName(StringRef Name);
2294
2295/// }
2296
Bob Wilson69df7232011-02-03 21:46:10 +00002297bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2298 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002299 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002300 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002301 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002302
2303 return (RegNo == (unsigned)-1);
2304}
2305
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002306/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002307/// and if it is a register name the token is eaten and the register number is
2308/// returned. Otherwise return -1.
2309///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002310int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002311 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002312 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002313
Benjamin Kramer59085362011-11-06 20:37:06 +00002314 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002315 unsigned RegNum = MatchRegisterName(lowerCase);
2316 if (!RegNum) {
2317 RegNum = StringSwitch<unsigned>(lowerCase)
2318 .Case("r13", ARM::SP)
2319 .Case("r14", ARM::LR)
2320 .Case("r15", ARM::PC)
2321 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002322 // Additional register name aliases for 'gas' compatibility.
2323 .Case("a1", ARM::R0)
2324 .Case("a2", ARM::R1)
2325 .Case("a3", ARM::R2)
2326 .Case("a4", ARM::R3)
2327 .Case("v1", ARM::R4)
2328 .Case("v2", ARM::R5)
2329 .Case("v3", ARM::R6)
2330 .Case("v4", ARM::R7)
2331 .Case("v5", ARM::R8)
2332 .Case("v6", ARM::R9)
2333 .Case("v7", ARM::R10)
2334 .Case("v8", ARM::R11)
2335 .Case("sb", ARM::R9)
2336 .Case("sl", ARM::R10)
2337 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002338 .Default(0);
2339 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002340 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002341 // Check for aliases registered via .req. Canonicalize to lower case.
2342 // That's more consistent since register names are case insensitive, and
2343 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2344 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002345 // If no match, return failure.
2346 if (Entry == RegisterReqs.end())
2347 return -1;
2348 Parser.Lex(); // Eat identifier token.
2349 return Entry->getValue();
2350 }
Bob Wilson69df7232011-02-03 21:46:10 +00002351
Chris Lattnere5658fa2010-10-30 04:09:10 +00002352 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002353
Chris Lattnere5658fa2010-10-30 04:09:10 +00002354 return RegNum;
2355}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002356
Jim Grosbach19906722011-07-13 18:49:30 +00002357// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2358// If a recoverable error occurs, return 1. If an irrecoverable error
2359// occurs, return -1. An irrecoverable error is one where tokens have been
2360// consumed in the process of trying to parse the shifter (i.e., when it is
2361// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002362int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002363 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2364 SMLoc S = Parser.getTok().getLoc();
2365 const AsmToken &Tok = Parser.getTok();
2366 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2367
Benjamin Kramer59085362011-11-06 20:37:06 +00002368 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002369 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002370 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002371 .Case("lsl", ARM_AM::lsl)
2372 .Case("lsr", ARM_AM::lsr)
2373 .Case("asr", ARM_AM::asr)
2374 .Case("ror", ARM_AM::ror)
2375 .Case("rrx", ARM_AM::rrx)
2376 .Default(ARM_AM::no_shift);
2377
2378 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002379 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002380
Jim Grosbache8606dc2011-07-13 17:50:29 +00002381 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002382
Jim Grosbache8606dc2011-07-13 17:50:29 +00002383 // The source register for the shift has already been added to the
2384 // operand list, so we need to pop it off and combine it into the shifted
2385 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002386 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002387 if (!PrevOp->isReg())
2388 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2389 int SrcReg = PrevOp->getReg();
2390 int64_t Imm = 0;
2391 int ShiftReg = 0;
2392 if (ShiftTy == ARM_AM::rrx) {
2393 // RRX Doesn't have an explicit shift amount. The encoder expects
2394 // the shift register to be the same as the source register. Seems odd,
2395 // but OK.
2396 ShiftReg = SrcReg;
2397 } else {
2398 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002399 if (Parser.getTok().is(AsmToken::Hash) ||
2400 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002401 Parser.Lex(); // Eat hash.
2402 SMLoc ImmLoc = Parser.getTok().getLoc();
2403 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002404 if (getParser().ParseExpression(ShiftExpr)) {
2405 Error(ImmLoc, "invalid immediate shift value");
2406 return -1;
2407 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002408 // The expression must be evaluatable as an immediate.
2409 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002410 if (!CE) {
2411 Error(ImmLoc, "invalid immediate shift value");
2412 return -1;
2413 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002414 // Range check the immediate.
2415 // lsl, ror: 0 <= imm <= 31
2416 // lsr, asr: 0 <= imm <= 32
2417 Imm = CE->getValue();
2418 if (Imm < 0 ||
2419 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2420 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002421 Error(ImmLoc, "immediate shift value out of range");
2422 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002423 }
2424 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002425 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002426 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002427 if (ShiftReg == -1) {
2428 Error (L, "expected immediate or register in shift operand");
2429 return -1;
2430 }
2431 } else {
2432 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002433 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002434 return -1;
2435 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002436 }
2437
Owen Anderson92a20222011-07-21 18:54:16 +00002438 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2439 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002440 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002441 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002442 else
2443 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2444 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002445
Jim Grosbach19906722011-07-13 18:49:30 +00002446 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002447}
2448
2449
Bill Wendling50d0f582010-11-18 23:43:05 +00002450/// Try to parse a register name. The token must be an Identifier when called.
2451/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2452/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002453///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002454/// TODO this is likely to change to allow different register types and or to
2455/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002456bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002457tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002458 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002459 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002460 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002461 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002462
Bill Wendling50d0f582010-11-18 23:43:05 +00002463 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002464
Chris Lattnere5658fa2010-10-30 04:09:10 +00002465 const AsmToken &ExclaimTok = Parser.getTok();
2466 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002467 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2468 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002469 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002470 return false;
2471 }
2472
2473 // Also check for an index operand. This is only legal for vector registers,
2474 // but that'll get caught OK in operand matching, so we don't need to
2475 // explicitly filter everything else out here.
2476 if (Parser.getTok().is(AsmToken::LBrac)) {
2477 SMLoc SIdx = Parser.getTok().getLoc();
2478 Parser.Lex(); // Eat left bracket token.
2479
2480 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002481 if (getParser().ParseExpression(ImmVal))
2482 return MatchOperand_ParseFail;
2483 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2484 if (!MCE) {
2485 TokError("immediate value expected for vector index");
2486 return MatchOperand_ParseFail;
2487 }
2488
2489 SMLoc E = Parser.getTok().getLoc();
2490 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2491 Error(E, "']' expected");
2492 return MatchOperand_ParseFail;
2493 }
2494
2495 Parser.Lex(); // Eat right bracket token.
2496
2497 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2498 SIdx, E,
2499 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002500 }
2501
Bill Wendling50d0f582010-11-18 23:43:05 +00002502 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002503}
2504
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002505/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2506/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2507/// "c5", ...
2508static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002509 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2510 // but efficient.
2511 switch (Name.size()) {
2512 default: break;
2513 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002514 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002515 return -1;
2516 switch (Name[1]) {
2517 default: return -1;
2518 case '0': return 0;
2519 case '1': return 1;
2520 case '2': return 2;
2521 case '3': return 3;
2522 case '4': return 4;
2523 case '5': return 5;
2524 case '6': return 6;
2525 case '7': return 7;
2526 case '8': return 8;
2527 case '9': return 9;
2528 }
2529 break;
2530 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002531 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002532 return -1;
2533 switch (Name[2]) {
2534 default: return -1;
2535 case '0': return 10;
2536 case '1': return 11;
2537 case '2': return 12;
2538 case '3': return 13;
2539 case '4': return 14;
2540 case '5': return 15;
2541 }
2542 break;
2543 }
2544
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002545 return -1;
2546}
2547
Jim Grosbach89df9962011-08-26 21:43:41 +00002548/// parseITCondCode - Try to parse a condition code for an IT instruction.
2549ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2550parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2551 SMLoc S = Parser.getTok().getLoc();
2552 const AsmToken &Tok = Parser.getTok();
2553 if (!Tok.is(AsmToken::Identifier))
2554 return MatchOperand_NoMatch;
2555 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2556 .Case("eq", ARMCC::EQ)
2557 .Case("ne", ARMCC::NE)
2558 .Case("hs", ARMCC::HS)
2559 .Case("cs", ARMCC::HS)
2560 .Case("lo", ARMCC::LO)
2561 .Case("cc", ARMCC::LO)
2562 .Case("mi", ARMCC::MI)
2563 .Case("pl", ARMCC::PL)
2564 .Case("vs", ARMCC::VS)
2565 .Case("vc", ARMCC::VC)
2566 .Case("hi", ARMCC::HI)
2567 .Case("ls", ARMCC::LS)
2568 .Case("ge", ARMCC::GE)
2569 .Case("lt", ARMCC::LT)
2570 .Case("gt", ARMCC::GT)
2571 .Case("le", ARMCC::LE)
2572 .Case("al", ARMCC::AL)
2573 .Default(~0U);
2574 if (CC == ~0U)
2575 return MatchOperand_NoMatch;
2576 Parser.Lex(); // Eat the token.
2577
2578 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2579
2580 return MatchOperand_Success;
2581}
2582
Jim Grosbach43904292011-07-25 20:14:50 +00002583/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002584/// token must be an Identifier when called, and if it is a coprocessor
2585/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002586ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002587parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002588 SMLoc S = Parser.getTok().getLoc();
2589 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002590 if (Tok.isNot(AsmToken::Identifier))
2591 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002592
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002593 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002594 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002595 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002596
2597 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002598 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002599 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002600}
2601
Jim Grosbach43904292011-07-25 20:14:50 +00002602/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002603/// token must be an Identifier when called, and if it is a coprocessor
2604/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002605ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002606parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002607 SMLoc S = Parser.getTok().getLoc();
2608 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002609 if (Tok.isNot(AsmToken::Identifier))
2610 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002611
2612 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2613 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002614 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002615
2616 Parser.Lex(); // Eat identifier token.
2617 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002618 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002619}
2620
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002621/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2622/// coproc_option : '{' imm0_255 '}'
2623ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2624parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2625 SMLoc S = Parser.getTok().getLoc();
2626
2627 // If this isn't a '{', this isn't a coprocessor immediate operand.
2628 if (Parser.getTok().isNot(AsmToken::LCurly))
2629 return MatchOperand_NoMatch;
2630 Parser.Lex(); // Eat the '{'
2631
2632 const MCExpr *Expr;
2633 SMLoc Loc = Parser.getTok().getLoc();
2634 if (getParser().ParseExpression(Expr)) {
2635 Error(Loc, "illegal expression");
2636 return MatchOperand_ParseFail;
2637 }
2638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2639 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2640 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2641 return MatchOperand_ParseFail;
2642 }
2643 int Val = CE->getValue();
2644
2645 // Check for and consume the closing '}'
2646 if (Parser.getTok().isNot(AsmToken::RCurly))
2647 return MatchOperand_ParseFail;
2648 SMLoc E = Parser.getTok().getLoc();
2649 Parser.Lex(); // Eat the '}'
2650
2651 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2652 return MatchOperand_Success;
2653}
2654
Jim Grosbachd0588e22011-09-14 18:08:35 +00002655// For register list parsing, we need to map from raw GPR register numbering
2656// to the enumeration values. The enumeration values aren't sorted by
2657// register number due to our using "sp", "lr" and "pc" as canonical names.
2658static unsigned getNextRegister(unsigned Reg) {
2659 // If this is a GPR, we need to do it manually, otherwise we can rely
2660 // on the sort ordering of the enumeration since the other reg-classes
2661 // are sane.
2662 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2663 return Reg + 1;
2664 switch(Reg) {
2665 default: assert(0 && "Invalid GPR number!");
2666 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2667 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2668 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2669 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2670 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2671 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2672 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2673 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2674 }
2675}
2676
Jim Grosbachce485e72011-11-11 21:27:40 +00002677// Return the low-subreg of a given Q register.
2678static unsigned getDRegFromQReg(unsigned QReg) {
2679 switch (QReg) {
2680 default: llvm_unreachable("expected a Q register!");
2681 case ARM::Q0: return ARM::D0;
2682 case ARM::Q1: return ARM::D2;
2683 case ARM::Q2: return ARM::D4;
2684 case ARM::Q3: return ARM::D6;
2685 case ARM::Q4: return ARM::D8;
2686 case ARM::Q5: return ARM::D10;
2687 case ARM::Q6: return ARM::D12;
2688 case ARM::Q7: return ARM::D14;
2689 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002690 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002691 case ARM::Q10: return ARM::D20;
2692 case ARM::Q11: return ARM::D22;
2693 case ARM::Q12: return ARM::D24;
2694 case ARM::Q13: return ARM::D26;
2695 case ARM::Q14: return ARM::D28;
2696 case ARM::Q15: return ARM::D30;
2697 }
2698}
2699
Jim Grosbachd0588e22011-09-14 18:08:35 +00002700/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002701bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002702parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002703 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002704 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002705 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002706 Parser.Lex(); // Eat '{' token.
2707 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002708
Jim Grosbachd0588e22011-09-14 18:08:35 +00002709 // Check the first register in the list to see what register class
2710 // this is a list of.
2711 int Reg = tryParseRegister();
2712 if (Reg == -1)
2713 return Error(RegLoc, "register expected");
2714
Jim Grosbachce485e72011-11-11 21:27:40 +00002715 // The reglist instructions have at most 16 registers, so reserve
2716 // space for that many.
2717 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2718
2719 // Allow Q regs and just interpret them as the two D sub-registers.
2720 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2721 Reg = getDRegFromQReg(Reg);
2722 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2723 ++Reg;
2724 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002725 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002726 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2727 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2728 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2729 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2730 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2731 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2732 else
2733 return Error(RegLoc, "invalid register in register list");
2734
Jim Grosbachce485e72011-11-11 21:27:40 +00002735 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002736 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002737
Jim Grosbachd0588e22011-09-14 18:08:35 +00002738 // This starts immediately after the first register token in the list,
2739 // so we can see either a comma or a minus (range separator) as a legal
2740 // next token.
2741 while (Parser.getTok().is(AsmToken::Comma) ||
2742 Parser.getTok().is(AsmToken::Minus)) {
2743 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002744 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002745 SMLoc EndLoc = Parser.getTok().getLoc();
2746 int EndReg = tryParseRegister();
2747 if (EndReg == -1)
2748 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002749 // Allow Q regs and just interpret them as the two D sub-registers.
2750 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2751 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002752 // If the register is the same as the start reg, there's nothing
2753 // more to do.
2754 if (Reg == EndReg)
2755 continue;
2756 // The register must be in the same register class as the first.
2757 if (!RC->contains(EndReg))
2758 return Error(EndLoc, "invalid register in register list");
2759 // Ranges must go from low to high.
2760 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2761 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002762
Jim Grosbachd0588e22011-09-14 18:08:35 +00002763 // Add all the registers in the range to the register list.
2764 while (Reg != EndReg) {
2765 Reg = getNextRegister(Reg);
2766 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2767 }
2768 continue;
2769 }
2770 Parser.Lex(); // Eat the comma.
2771 RegLoc = Parser.getTok().getLoc();
2772 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002773 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002774 Reg = tryParseRegister();
2775 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002776 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002777 // Allow Q regs and just interpret them as the two D sub-registers.
2778 bool isQReg = false;
2779 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2780 Reg = getDRegFromQReg(Reg);
2781 isQReg = true;
2782 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002783 // The register must be in the same register class as the first.
2784 if (!RC->contains(Reg))
2785 return Error(RegLoc, "invalid register in register list");
2786 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002787 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002788 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002789 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2790 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2791 ") in register list");
2792 continue;
2793 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002794 // VFP register lists must also be contiguous.
2795 // It's OK to use the enumeration values directly here rather, as the
2796 // VFP register classes have the enum sorted properly.
2797 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2798 Reg != OldReg + 1)
2799 return Error(RegLoc, "non-contiguous register range");
2800 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002801 if (isQReg)
2802 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002803 }
2804
Jim Grosbachd0588e22011-09-14 18:08:35 +00002805 SMLoc E = Parser.getTok().getLoc();
2806 if (Parser.getTok().isNot(AsmToken::RCurly))
2807 return Error(E, "'}' expected");
2808 Parser.Lex(); // Eat '}' token.
2809
Jim Grosbach27debd62011-12-13 21:48:29 +00002810 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002811 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002812
2813 // The ARM system instruction variants for LDM/STM have a '^' token here.
2814 if (Parser.getTok().is(AsmToken::Caret)) {
2815 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2816 Parser.Lex(); // Eat '^' token.
2817 }
2818
Bill Wendling50d0f582010-11-18 23:43:05 +00002819 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002820}
2821
Jim Grosbach98b05a52011-11-30 01:09:44 +00002822// Helper function to parse the lane index for vector lists.
2823ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002824parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2825 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002826 if (Parser.getTok().is(AsmToken::LBrac)) {
2827 Parser.Lex(); // Eat the '['.
2828 if (Parser.getTok().is(AsmToken::RBrac)) {
2829 // "Dn[]" is the 'all lanes' syntax.
2830 LaneKind = AllLanes;
2831 Parser.Lex(); // Eat the ']'.
2832 return MatchOperand_Success;
2833 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002834 if (Parser.getTok().is(AsmToken::Integer)) {
2835 int64_t Val = Parser.getTok().getIntVal();
2836 // Make this range check context sensitive for .8, .16, .32.
2837 if (Val < 0 && Val > 7)
2838 Error(Parser.getTok().getLoc(), "lane index out of range");
2839 Index = Val;
2840 LaneKind = IndexedLane;
2841 Parser.Lex(); // Eat the token;
2842 if (Parser.getTok().isNot(AsmToken::RBrac))
2843 Error(Parser.getTok().getLoc(), "']' expected");
2844 Parser.Lex(); // Eat the ']'.
2845 return MatchOperand_Success;
2846 }
2847 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002848 return MatchOperand_ParseFail;
2849 }
2850 LaneKind = NoLanes;
2851 return MatchOperand_Success;
2852}
2853
Jim Grosbach862019c2011-10-18 23:02:30 +00002854// parse a vector register list
2855ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2856parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002857 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002858 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002859 SMLoc S = Parser.getTok().getLoc();
2860 // As an extension (to match gas), support a plain D register or Q register
2861 // (without encosing curly braces) as a single or double entry list,
2862 // respectively.
2863 if (Parser.getTok().is(AsmToken::Identifier)) {
2864 int Reg = tryParseRegister();
2865 if (Reg == -1)
2866 return MatchOperand_NoMatch;
2867 SMLoc E = Parser.getTok().getLoc();
2868 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002869 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002870 if (Res != MatchOperand_Success)
2871 return Res;
2872 switch (LaneKind) {
2873 default:
2874 assert(0 && "unexpected lane kind!");
2875 case NoLanes:
2876 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002877 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002878 break;
2879 case AllLanes:
2880 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002881 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2882 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002883 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002884 case IndexedLane:
2885 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002886 LaneIndex,
2887 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002888 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002889 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002890 return MatchOperand_Success;
2891 }
2892 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2893 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002894 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002895 if (Res != MatchOperand_Success)
2896 return Res;
2897 switch (LaneKind) {
2898 default:
2899 assert(0 && "unexpected lane kind!");
2900 case NoLanes:
2901 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002902 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002903 break;
2904 case AllLanes:
2905 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002906 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2907 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002908 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002909 case IndexedLane:
2910 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002911 LaneIndex,
2912 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002913 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002914 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002915 return MatchOperand_Success;
2916 }
2917 Error(S, "vector register expected");
2918 return MatchOperand_ParseFail;
2919 }
2920
2921 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002922 return MatchOperand_NoMatch;
2923
Jim Grosbach862019c2011-10-18 23:02:30 +00002924 Parser.Lex(); // Eat '{' token.
2925 SMLoc RegLoc = Parser.getTok().getLoc();
2926
2927 int Reg = tryParseRegister();
2928 if (Reg == -1) {
2929 Error(RegLoc, "register expected");
2930 return MatchOperand_ParseFail;
2931 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002932 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002933 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002934 unsigned FirstReg = Reg;
2935 // The list is of D registers, but we also allow Q regs and just interpret
2936 // them as the two D sub-registers.
2937 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2938 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002939 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2940 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002941 ++Reg;
2942 ++Count;
2943 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002944 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002945 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002946
Jim Grosbache43862b2011-11-15 23:19:15 +00002947 while (Parser.getTok().is(AsmToken::Comma) ||
2948 Parser.getTok().is(AsmToken::Minus)) {
2949 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002950 if (!Spacing)
2951 Spacing = 1; // Register range implies a single spaced list.
2952 else if (Spacing == 2) {
2953 Error(Parser.getTok().getLoc(),
2954 "sequential registers in double spaced list");
2955 return MatchOperand_ParseFail;
2956 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002957 Parser.Lex(); // Eat the minus.
2958 SMLoc EndLoc = Parser.getTok().getLoc();
2959 int EndReg = tryParseRegister();
2960 if (EndReg == -1) {
2961 Error(EndLoc, "register expected");
2962 return MatchOperand_ParseFail;
2963 }
2964 // Allow Q regs and just interpret them as the two D sub-registers.
2965 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2966 EndReg = getDRegFromQReg(EndReg) + 1;
2967 // If the register is the same as the start reg, there's nothing
2968 // more to do.
2969 if (Reg == EndReg)
2970 continue;
2971 // The register must be in the same register class as the first.
2972 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2973 Error(EndLoc, "invalid register in register list");
2974 return MatchOperand_ParseFail;
2975 }
2976 // Ranges must go from low to high.
2977 if (Reg > EndReg) {
2978 Error(EndLoc, "bad range in register list");
2979 return MatchOperand_ParseFail;
2980 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002981 // Parse the lane specifier if present.
2982 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002983 unsigned NextLaneIndex;
2984 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002985 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002986 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002987 Error(EndLoc, "mismatched lane index in register list");
2988 return MatchOperand_ParseFail;
2989 }
2990 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002991
2992 // Add all the registers in the range to the register list.
2993 Count += EndReg - Reg;
2994 Reg = EndReg;
2995 continue;
2996 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002997 Parser.Lex(); // Eat the comma.
2998 RegLoc = Parser.getTok().getLoc();
2999 int OldReg = Reg;
3000 Reg = tryParseRegister();
3001 if (Reg == -1) {
3002 Error(RegLoc, "register expected");
3003 return MatchOperand_ParseFail;
3004 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003005 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003006 // It's OK to use the enumeration values directly here rather, as the
3007 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003008 //
3009 // The list is of D registers, but we also allow Q regs and just interpret
3010 // them as the two D sub-registers.
3011 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003012 if (!Spacing)
3013 Spacing = 1; // Register range implies a single spaced list.
3014 else if (Spacing == 2) {
3015 Error(RegLoc,
3016 "invalid register in double-spaced list (must be 'D' register')");
3017 return MatchOperand_ParseFail;
3018 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003019 Reg = getDRegFromQReg(Reg);
3020 if (Reg != OldReg + 1) {
3021 Error(RegLoc, "non-contiguous register range");
3022 return MatchOperand_ParseFail;
3023 }
3024 ++Reg;
3025 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003026 // Parse the lane specifier if present.
3027 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003028 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003029 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003030 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003031 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003032 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003033 Error(EndLoc, "mismatched lane index in register list");
3034 return MatchOperand_ParseFail;
3035 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003036 continue;
3037 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003038 // Normal D register.
3039 // Figure out the register spacing (single or double) of the list if
3040 // we don't know it already.
3041 if (!Spacing)
3042 Spacing = 1 + (Reg == OldReg + 2);
3043
3044 // Just check that it's contiguous and keep going.
3045 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003046 Error(RegLoc, "non-contiguous register range");
3047 return MatchOperand_ParseFail;
3048 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003049 ++Count;
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 Grosbach862019c2011-10-18 23:02:30 +00003060 }
3061
3062 SMLoc E = Parser.getTok().getLoc();
3063 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3064 Error(E, "'}' expected");
3065 return MatchOperand_ParseFail;
3066 }
3067 Parser.Lex(); // Eat '}' token.
3068
Jim Grosbach98b05a52011-11-30 01:09:44 +00003069 switch (LaneKind) {
3070 default:
3071 assert(0 && "unexpected lane kind in register list.");
3072 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003073 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3074 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003075 break;
3076 case AllLanes:
3077 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003078 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003079 S, E));
3080 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003081 case IndexedLane:
3082 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003083 LaneIndex,
3084 (Spacing == 2),
3085 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003086 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003087 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003088 return MatchOperand_Success;
3089}
3090
Jim Grosbach43904292011-07-25 20:14:50 +00003091/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003092ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003093parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003094 SMLoc S = Parser.getTok().getLoc();
3095 const AsmToken &Tok = Parser.getTok();
3096 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3097 StringRef OptStr = Tok.getString();
3098
3099 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3100 .Case("sy", ARM_MB::SY)
3101 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003102 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003103 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003104 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003105 .Case("ishst", ARM_MB::ISHST)
3106 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003107 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003108 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003109 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003110 .Case("osh", ARM_MB::OSH)
3111 .Case("oshst", ARM_MB::OSHST)
3112 .Default(~0U);
3113
3114 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003115 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003116
3117 Parser.Lex(); // Eat identifier token.
3118 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003119 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003120}
3121
Jim Grosbach43904292011-07-25 20:14:50 +00003122/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003123ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003124parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003125 SMLoc S = Parser.getTok().getLoc();
3126 const AsmToken &Tok = Parser.getTok();
3127 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3128 StringRef IFlagsStr = Tok.getString();
3129
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003130 // An iflags string of "none" is interpreted to mean that none of the AIF
3131 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003132 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003133 if (IFlagsStr != "none") {
3134 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3135 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3136 .Case("a", ARM_PROC::A)
3137 .Case("i", ARM_PROC::I)
3138 .Case("f", ARM_PROC::F)
3139 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003140
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003141 // If some specific iflag is already set, it means that some letter is
3142 // present more than once, this is not acceptable.
3143 if (Flag == ~0U || (IFlags & Flag))
3144 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003145
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003146 IFlags |= Flag;
3147 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003148 }
3149
3150 Parser.Lex(); // Eat identifier token.
3151 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3152 return MatchOperand_Success;
3153}
3154
Jim Grosbach43904292011-07-25 20:14:50 +00003155/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003156ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003157parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003158 SMLoc S = Parser.getTok().getLoc();
3159 const AsmToken &Tok = Parser.getTok();
3160 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3161 StringRef Mask = Tok.getString();
3162
James Molloyacad68d2011-09-28 14:21:38 +00003163 if (isMClass()) {
3164 // See ARMv6-M 10.1.1
3165 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3166 .Case("apsr", 0)
3167 .Case("iapsr", 1)
3168 .Case("eapsr", 2)
3169 .Case("xpsr", 3)
3170 .Case("ipsr", 5)
3171 .Case("epsr", 6)
3172 .Case("iepsr", 7)
3173 .Case("msp", 8)
3174 .Case("psp", 9)
3175 .Case("primask", 16)
3176 .Case("basepri", 17)
3177 .Case("basepri_max", 18)
3178 .Case("faultmask", 19)
3179 .Case("control", 20)
3180 .Default(~0U);
3181
3182 if (FlagsVal == ~0U)
3183 return MatchOperand_NoMatch;
3184
3185 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3186 // basepri, basepri_max and faultmask only valid for V7m.
3187 return MatchOperand_NoMatch;
3188
3189 Parser.Lex(); // Eat identifier token.
3190 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3191 return MatchOperand_Success;
3192 }
3193
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003194 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3195 size_t Start = 0, Next = Mask.find('_');
3196 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003197 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003198 if (Next != StringRef::npos)
3199 Flags = Mask.slice(Next+1, Mask.size());
3200
3201 // FlagsVal contains the complete mask:
3202 // 3-0: Mask
3203 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3204 unsigned FlagsVal = 0;
3205
3206 if (SpecReg == "apsr") {
3207 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003208 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003209 .Case("g", 0x4) // same as CPSR_s
3210 .Case("nzcvqg", 0xc) // same as CPSR_fs
3211 .Default(~0U);
3212
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003213 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003214 if (!Flags.empty())
3215 return MatchOperand_NoMatch;
3216 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003217 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003218 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003219 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003220 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3221 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003222 for (int i = 0, e = Flags.size(); i != e; ++i) {
3223 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3224 .Case("c", 1)
3225 .Case("x", 2)
3226 .Case("s", 4)
3227 .Case("f", 8)
3228 .Default(~0U);
3229
3230 // If some specific flag is already set, it means that some letter is
3231 // present more than once, this is not acceptable.
3232 if (FlagsVal == ~0U || (FlagsVal & Flag))
3233 return MatchOperand_NoMatch;
3234 FlagsVal |= Flag;
3235 }
3236 } else // No match for special register.
3237 return MatchOperand_NoMatch;
3238
Owen Anderson7784f1d2011-10-21 18:43:28 +00003239 // Special register without flags is NOT equivalent to "fc" flags.
3240 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3241 // two lines would enable gas compatibility at the expense of breaking
3242 // round-tripping.
3243 //
3244 // if (!FlagsVal)
3245 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003246
3247 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3248 if (SpecReg == "spsr")
3249 FlagsVal |= 16;
3250
3251 Parser.Lex(); // Eat identifier token.
3252 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3253 return MatchOperand_Success;
3254}
3255
Jim Grosbachf6c05252011-07-21 17:23:04 +00003256ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3257parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3258 int Low, int High) {
3259 const AsmToken &Tok = Parser.getTok();
3260 if (Tok.isNot(AsmToken::Identifier)) {
3261 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3262 return MatchOperand_ParseFail;
3263 }
3264 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003265 std::string LowerOp = Op.lower();
3266 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003267 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3268 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3269 return MatchOperand_ParseFail;
3270 }
3271 Parser.Lex(); // Eat shift type token.
3272
3273 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003274 if (Parser.getTok().isNot(AsmToken::Hash) &&
3275 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003276 Error(Parser.getTok().getLoc(), "'#' expected");
3277 return MatchOperand_ParseFail;
3278 }
3279 Parser.Lex(); // Eat hash token.
3280
3281 const MCExpr *ShiftAmount;
3282 SMLoc Loc = Parser.getTok().getLoc();
3283 if (getParser().ParseExpression(ShiftAmount)) {
3284 Error(Loc, "illegal expression");
3285 return MatchOperand_ParseFail;
3286 }
3287 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3288 if (!CE) {
3289 Error(Loc, "constant expression expected");
3290 return MatchOperand_ParseFail;
3291 }
3292 int Val = CE->getValue();
3293 if (Val < Low || Val > High) {
3294 Error(Loc, "immediate value out of range");
3295 return MatchOperand_ParseFail;
3296 }
3297
3298 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3299
3300 return MatchOperand_Success;
3301}
3302
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003303ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3304parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3305 const AsmToken &Tok = Parser.getTok();
3306 SMLoc S = Tok.getLoc();
3307 if (Tok.isNot(AsmToken::Identifier)) {
3308 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3309 return MatchOperand_ParseFail;
3310 }
3311 int Val = StringSwitch<int>(Tok.getString())
3312 .Case("be", 1)
3313 .Case("le", 0)
3314 .Default(-1);
3315 Parser.Lex(); // Eat the token.
3316
3317 if (Val == -1) {
3318 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3319 return MatchOperand_ParseFail;
3320 }
3321 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3322 getContext()),
3323 S, Parser.getTok().getLoc()));
3324 return MatchOperand_Success;
3325}
3326
Jim Grosbach580f4a92011-07-25 22:20:28 +00003327/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3328/// instructions. Legal values are:
3329/// lsl #n 'n' in [0,31]
3330/// asr #n 'n' in [1,32]
3331/// n == 32 encoded as n == 0.
3332ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3333parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3334 const AsmToken &Tok = Parser.getTok();
3335 SMLoc S = Tok.getLoc();
3336 if (Tok.isNot(AsmToken::Identifier)) {
3337 Error(S, "shift operator 'asr' or 'lsl' expected");
3338 return MatchOperand_ParseFail;
3339 }
3340 StringRef ShiftName = Tok.getString();
3341 bool isASR;
3342 if (ShiftName == "lsl" || ShiftName == "LSL")
3343 isASR = false;
3344 else if (ShiftName == "asr" || ShiftName == "ASR")
3345 isASR = true;
3346 else {
3347 Error(S, "shift operator 'asr' or 'lsl' expected");
3348 return MatchOperand_ParseFail;
3349 }
3350 Parser.Lex(); // Eat the operator.
3351
3352 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003353 if (Parser.getTok().isNot(AsmToken::Hash) &&
3354 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003355 Error(Parser.getTok().getLoc(), "'#' expected");
3356 return MatchOperand_ParseFail;
3357 }
3358 Parser.Lex(); // Eat hash token.
3359
3360 const MCExpr *ShiftAmount;
3361 SMLoc E = Parser.getTok().getLoc();
3362 if (getParser().ParseExpression(ShiftAmount)) {
3363 Error(E, "malformed shift expression");
3364 return MatchOperand_ParseFail;
3365 }
3366 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3367 if (!CE) {
3368 Error(E, "shift amount must be an immediate");
3369 return MatchOperand_ParseFail;
3370 }
3371
3372 int64_t Val = CE->getValue();
3373 if (isASR) {
3374 // Shift amount must be in [1,32]
3375 if (Val < 1 || Val > 32) {
3376 Error(E, "'asr' shift amount must be in range [1,32]");
3377 return MatchOperand_ParseFail;
3378 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003379 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3380 if (isThumb() && Val == 32) {
3381 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3382 return MatchOperand_ParseFail;
3383 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003384 if (Val == 32) Val = 0;
3385 } else {
3386 // Shift amount must be in [1,32]
3387 if (Val < 0 || Val > 31) {
3388 Error(E, "'lsr' shift amount must be in range [0,31]");
3389 return MatchOperand_ParseFail;
3390 }
3391 }
3392
3393 E = Parser.getTok().getLoc();
3394 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3395
3396 return MatchOperand_Success;
3397}
3398
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003399/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3400/// of instructions. Legal values are:
3401/// ror #n 'n' in {0, 8, 16, 24}
3402ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3403parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3404 const AsmToken &Tok = Parser.getTok();
3405 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003406 if (Tok.isNot(AsmToken::Identifier))
3407 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003408 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003409 if (ShiftName != "ror" && ShiftName != "ROR")
3410 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003411 Parser.Lex(); // Eat the operator.
3412
3413 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003414 if (Parser.getTok().isNot(AsmToken::Hash) &&
3415 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003416 Error(Parser.getTok().getLoc(), "'#' expected");
3417 return MatchOperand_ParseFail;
3418 }
3419 Parser.Lex(); // Eat hash token.
3420
3421 const MCExpr *ShiftAmount;
3422 SMLoc E = Parser.getTok().getLoc();
3423 if (getParser().ParseExpression(ShiftAmount)) {
3424 Error(E, "malformed rotate expression");
3425 return MatchOperand_ParseFail;
3426 }
3427 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3428 if (!CE) {
3429 Error(E, "rotate amount must be an immediate");
3430 return MatchOperand_ParseFail;
3431 }
3432
3433 int64_t Val = CE->getValue();
3434 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3435 // normally, zero is represented in asm by omitting the rotate operand
3436 // entirely.
3437 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3438 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3439 return MatchOperand_ParseFail;
3440 }
3441
3442 E = Parser.getTok().getLoc();
3443 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3444
3445 return MatchOperand_Success;
3446}
3447
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003448ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3449parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3450 SMLoc S = Parser.getTok().getLoc();
3451 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003452 if (Parser.getTok().isNot(AsmToken::Hash) &&
3453 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003454 Error(Parser.getTok().getLoc(), "'#' expected");
3455 return MatchOperand_ParseFail;
3456 }
3457 Parser.Lex(); // Eat hash token.
3458
3459 const MCExpr *LSBExpr;
3460 SMLoc E = Parser.getTok().getLoc();
3461 if (getParser().ParseExpression(LSBExpr)) {
3462 Error(E, "malformed immediate expression");
3463 return MatchOperand_ParseFail;
3464 }
3465 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3466 if (!CE) {
3467 Error(E, "'lsb' operand must be an immediate");
3468 return MatchOperand_ParseFail;
3469 }
3470
3471 int64_t LSB = CE->getValue();
3472 // The LSB must be in the range [0,31]
3473 if (LSB < 0 || LSB > 31) {
3474 Error(E, "'lsb' operand must be in the range [0,31]");
3475 return MatchOperand_ParseFail;
3476 }
3477 E = Parser.getTok().getLoc();
3478
3479 // Expect another immediate operand.
3480 if (Parser.getTok().isNot(AsmToken::Comma)) {
3481 Error(Parser.getTok().getLoc(), "too few operands");
3482 return MatchOperand_ParseFail;
3483 }
3484 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003485 if (Parser.getTok().isNot(AsmToken::Hash) &&
3486 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003487 Error(Parser.getTok().getLoc(), "'#' expected");
3488 return MatchOperand_ParseFail;
3489 }
3490 Parser.Lex(); // Eat hash token.
3491
3492 const MCExpr *WidthExpr;
3493 if (getParser().ParseExpression(WidthExpr)) {
3494 Error(E, "malformed immediate expression");
3495 return MatchOperand_ParseFail;
3496 }
3497 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3498 if (!CE) {
3499 Error(E, "'width' operand must be an immediate");
3500 return MatchOperand_ParseFail;
3501 }
3502
3503 int64_t Width = CE->getValue();
3504 // The LSB must be in the range [1,32-lsb]
3505 if (Width < 1 || Width > 32 - LSB) {
3506 Error(E, "'width' operand must be in the range [1,32-lsb]");
3507 return MatchOperand_ParseFail;
3508 }
3509 E = Parser.getTok().getLoc();
3510
3511 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3512
3513 return MatchOperand_Success;
3514}
3515
Jim Grosbach7ce05792011-08-03 23:50:40 +00003516ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3517parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3518 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003519 // postidx_reg := '+' register {, shift}
3520 // | '-' register {, shift}
3521 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003522
3523 // This method must return MatchOperand_NoMatch without consuming any tokens
3524 // in the case where there is no match, as other alternatives take other
3525 // parse methods.
3526 AsmToken Tok = Parser.getTok();
3527 SMLoc S = Tok.getLoc();
3528 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003529 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003530 int Reg = -1;
3531 if (Tok.is(AsmToken::Plus)) {
3532 Parser.Lex(); // Eat the '+' token.
3533 haveEaten = true;
3534 } else if (Tok.is(AsmToken::Minus)) {
3535 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003536 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003537 haveEaten = true;
3538 }
3539 if (Parser.getTok().is(AsmToken::Identifier))
3540 Reg = tryParseRegister();
3541 if (Reg == -1) {
3542 if (!haveEaten)
3543 return MatchOperand_NoMatch;
3544 Error(Parser.getTok().getLoc(), "register expected");
3545 return MatchOperand_ParseFail;
3546 }
3547 SMLoc E = Parser.getTok().getLoc();
3548
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003549 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3550 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003551 if (Parser.getTok().is(AsmToken::Comma)) {
3552 Parser.Lex(); // Eat the ','.
3553 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3554 return MatchOperand_ParseFail;
3555 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003556
3557 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3558 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003559
3560 return MatchOperand_Success;
3561}
3562
Jim Grosbach251bf252011-08-10 21:56:18 +00003563ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3564parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3565 // Check for a post-index addressing register operand. Specifically:
3566 // am3offset := '+' register
3567 // | '-' register
3568 // | register
3569 // | # imm
3570 // | # + imm
3571 // | # - imm
3572
3573 // This method must return MatchOperand_NoMatch without consuming any tokens
3574 // in the case where there is no match, as other alternatives take other
3575 // parse methods.
3576 AsmToken Tok = Parser.getTok();
3577 SMLoc S = Tok.getLoc();
3578
3579 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003580 if (Parser.getTok().is(AsmToken::Hash) ||
3581 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003582 Parser.Lex(); // Eat the '#'.
3583 // Explicitly look for a '-', as we need to encode negative zero
3584 // differently.
3585 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3586 const MCExpr *Offset;
3587 if (getParser().ParseExpression(Offset))
3588 return MatchOperand_ParseFail;
3589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3590 if (!CE) {
3591 Error(S, "constant expression expected");
3592 return MatchOperand_ParseFail;
3593 }
3594 SMLoc E = Tok.getLoc();
3595 // Negative zero is encoded as the flag value INT32_MIN.
3596 int32_t Val = CE->getValue();
3597 if (isNegative && Val == 0)
3598 Val = INT32_MIN;
3599
3600 Operands.push_back(
3601 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3602
3603 return MatchOperand_Success;
3604 }
3605
3606
3607 bool haveEaten = false;
3608 bool isAdd = true;
3609 int Reg = -1;
3610 if (Tok.is(AsmToken::Plus)) {
3611 Parser.Lex(); // Eat the '+' token.
3612 haveEaten = true;
3613 } else if (Tok.is(AsmToken::Minus)) {
3614 Parser.Lex(); // Eat the '-' token.
3615 isAdd = false;
3616 haveEaten = true;
3617 }
3618 if (Parser.getTok().is(AsmToken::Identifier))
3619 Reg = tryParseRegister();
3620 if (Reg == -1) {
3621 if (!haveEaten)
3622 return MatchOperand_NoMatch;
3623 Error(Parser.getTok().getLoc(), "register expected");
3624 return MatchOperand_ParseFail;
3625 }
3626 SMLoc E = Parser.getTok().getLoc();
3627
3628 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3629 0, S, E));
3630
3631 return MatchOperand_Success;
3632}
3633
Jim Grosbacha77295d2011-09-08 22:07:06 +00003634/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3635/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3636/// when they refer multiple MIOperands inside a single one.
3637bool ARMAsmParser::
3638cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3639 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3640 // Rt, Rt2
3641 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3642 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3643 // Create a writeback register dummy placeholder.
3644 Inst.addOperand(MCOperand::CreateReg(0));
3645 // addr
3646 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3647 // pred
3648 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3649 return true;
3650}
3651
3652/// cvtT2StrdPre - Convert parsed operands to MCInst.
3653/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3654/// when they refer multiple MIOperands inside a single one.
3655bool ARMAsmParser::
3656cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3657 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3658 // Create a writeback register dummy placeholder.
3659 Inst.addOperand(MCOperand::CreateReg(0));
3660 // Rt, Rt2
3661 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3662 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3663 // addr
3664 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3665 // pred
3666 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3667 return true;
3668}
3669
Jim Grosbacheeec0252011-09-08 00:39:19 +00003670/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3671/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3672/// when they refer multiple MIOperands inside a single one.
3673bool ARMAsmParser::
3674cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3675 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3676 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3677
3678 // Create a writeback register dummy placeholder.
3679 Inst.addOperand(MCOperand::CreateImm(0));
3680
3681 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3682 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3683 return true;
3684}
3685
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003686/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3687/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3688/// when they refer multiple MIOperands inside a single one.
3689bool ARMAsmParser::
3690cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3691 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3692 // Create a writeback register dummy placeholder.
3693 Inst.addOperand(MCOperand::CreateImm(0));
3694 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3695 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3696 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3697 return true;
3698}
3699
Jim Grosbach1355cf12011-07-26 17:10:22 +00003700/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003701/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3702/// when they refer multiple MIOperands inside a single one.
3703bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003704cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003705 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3706 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3707
3708 // Create a writeback register dummy placeholder.
3709 Inst.addOperand(MCOperand::CreateImm(0));
3710
Jim Grosbach7ce05792011-08-03 23:50:40 +00003711 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003712 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3713 return true;
3714}
3715
Owen Anderson9ab0f252011-08-26 20:43:14 +00003716/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3717/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3718/// when they refer multiple MIOperands inside a single one.
3719bool ARMAsmParser::
3720cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3721 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3722 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3723
3724 // Create a writeback register dummy placeholder.
3725 Inst.addOperand(MCOperand::CreateImm(0));
3726
3727 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3728 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3729 return true;
3730}
3731
3732
Jim Grosbach548340c2011-08-11 19:22:40 +00003733/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3734/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3735/// when they refer multiple MIOperands inside a single one.
3736bool ARMAsmParser::
3737cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3738 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3739 // Create a writeback register dummy placeholder.
3740 Inst.addOperand(MCOperand::CreateImm(0));
3741 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3742 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3743 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3744 return true;
3745}
3746
Jim Grosbach1355cf12011-07-26 17:10:22 +00003747/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003748/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3749/// when they refer multiple MIOperands inside a single one.
3750bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003751cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003752 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3753 // Create a writeback register dummy placeholder.
3754 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003755 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3756 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3757 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003758 return true;
3759}
3760
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003761/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3762/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3763/// when they refer multiple MIOperands inside a single one.
3764bool ARMAsmParser::
3765cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3766 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3767 // Create a writeback register dummy placeholder.
3768 Inst.addOperand(MCOperand::CreateImm(0));
3769 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3770 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3771 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3772 return true;
3773}
3774
Jim Grosbach7ce05792011-08-03 23:50:40 +00003775/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3776/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3777/// when they refer multiple MIOperands inside a single one.
3778bool ARMAsmParser::
3779cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3780 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3781 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003782 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003783 // Create a writeback register dummy placeholder.
3784 Inst.addOperand(MCOperand::CreateImm(0));
3785 // addr
3786 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3787 // offset
3788 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3789 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003790 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3791 return true;
3792}
3793
Jim Grosbach7ce05792011-08-03 23:50:40 +00003794/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003795/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3796/// when they refer multiple MIOperands inside a single one.
3797bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003798cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3799 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3800 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003801 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003802 // Create a writeback register dummy placeholder.
3803 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003804 // addr
3805 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3806 // offset
3807 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3808 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003809 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3810 return true;
3811}
3812
Jim Grosbach7ce05792011-08-03 23:50:40 +00003813/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003814/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3815/// when they refer multiple MIOperands inside a single one.
3816bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003817cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3818 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003819 // Create a writeback register dummy placeholder.
3820 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003821 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003822 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003823 // addr
3824 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3825 // offset
3826 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3827 // pred
3828 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3829 return true;
3830}
3831
3832/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3833/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3834/// when they refer multiple MIOperands inside a single one.
3835bool ARMAsmParser::
3836cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3837 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3838 // Create a writeback register dummy placeholder.
3839 Inst.addOperand(MCOperand::CreateImm(0));
3840 // Rt
3841 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3842 // addr
3843 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3844 // offset
3845 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3846 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003847 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3848 return true;
3849}
3850
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003851/// cvtLdrdPre - Convert parsed operands to MCInst.
3852/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3853/// when they refer multiple MIOperands inside a single one.
3854bool ARMAsmParser::
3855cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3856 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3857 // Rt, Rt2
3858 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3859 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3860 // Create a writeback register dummy placeholder.
3861 Inst.addOperand(MCOperand::CreateImm(0));
3862 // addr
3863 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3864 // pred
3865 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3866 return true;
3867}
3868
Jim Grosbach14605d12011-08-11 20:28:23 +00003869/// cvtStrdPre - Convert parsed operands to MCInst.
3870/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3871/// when they refer multiple MIOperands inside a single one.
3872bool ARMAsmParser::
3873cvtStrdPre(MCInst &Inst, unsigned Opcode,
3874 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3875 // Create a writeback register dummy placeholder.
3876 Inst.addOperand(MCOperand::CreateImm(0));
3877 // Rt, Rt2
3878 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3879 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3880 // addr
3881 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3882 // pred
3883 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3884 return true;
3885}
3886
Jim Grosbach623a4542011-08-10 22:42:16 +00003887/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3888/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3889/// when they refer multiple MIOperands inside a single one.
3890bool ARMAsmParser::
3891cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3892 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3893 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3894 // Create a writeback register dummy placeholder.
3895 Inst.addOperand(MCOperand::CreateImm(0));
3896 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3897 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3898 return true;
3899}
3900
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003901/// cvtThumbMultiple- Convert parsed operands to MCInst.
3902/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3903/// when they refer multiple MIOperands inside a single one.
3904bool ARMAsmParser::
3905cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3906 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3907 // The second source operand must be the same register as the destination
3908 // operand.
3909 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003910 (((ARMOperand*)Operands[3])->getReg() !=
3911 ((ARMOperand*)Operands[5])->getReg()) &&
3912 (((ARMOperand*)Operands[3])->getReg() !=
3913 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003914 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003915 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003916 return false;
3917 }
3918 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3919 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003920 // If we have a three-operand form, make sure to set Rn to be the operand
3921 // that isn't the same as Rd.
3922 unsigned RegOp = 4;
3923 if (Operands.size() == 6 &&
3924 ((ARMOperand*)Operands[4])->getReg() ==
3925 ((ARMOperand*)Operands[3])->getReg())
3926 RegOp = 5;
3927 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3928 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003929 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3930
3931 return true;
3932}
Jim Grosbach623a4542011-08-10 22:42:16 +00003933
Jim Grosbach12431322011-10-24 22:16:58 +00003934bool ARMAsmParser::
3935cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3936 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3937 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003938 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003939 // Create a writeback register dummy placeholder.
3940 Inst.addOperand(MCOperand::CreateImm(0));
3941 // Vn
3942 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3943 // pred
3944 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3945 return true;
3946}
3947
3948bool ARMAsmParser::
3949cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3950 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3951 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003952 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003953 // Create a writeback register dummy placeholder.
3954 Inst.addOperand(MCOperand::CreateImm(0));
3955 // Vn
3956 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3957 // Vm
3958 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3959 // pred
3960 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3961 return true;
3962}
3963
Jim Grosbach4334e032011-10-31 21:50:31 +00003964bool ARMAsmParser::
3965cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3966 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3967 // Create a writeback register dummy placeholder.
3968 Inst.addOperand(MCOperand::CreateImm(0));
3969 // Vn
3970 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3971 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003972 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003973 // pred
3974 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3975 return true;
3976}
3977
3978bool ARMAsmParser::
3979cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3980 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3981 // Create a writeback register dummy placeholder.
3982 Inst.addOperand(MCOperand::CreateImm(0));
3983 // Vn
3984 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3985 // Vm
3986 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3987 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003988 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003989 // pred
3990 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3991 return true;
3992}
3993
Bill Wendlinge7176102010-11-06 22:36:58 +00003994/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003995/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003996bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003997parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003998 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003999 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004000 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004001 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004002 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004003
Sean Callanan18b83232010-01-19 21:44:56 +00004004 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004005 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004006 if (BaseRegNum == -1)
4007 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004008
Daniel Dunbar05710932011-01-18 05:34:17 +00004009 // The next token must either be a comma or a closing bracket.
4010 const AsmToken &Tok = Parser.getTok();
4011 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004012 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004013
Jim Grosbach7ce05792011-08-03 23:50:40 +00004014 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004015 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004016 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004017
Jim Grosbach7ce05792011-08-03 23:50:40 +00004018 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004019 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004020
Jim Grosbachfb12f352011-09-19 18:42:21 +00004021 // If there's a pre-indexing writeback marker, '!', just add it as a token
4022 // operand. It's rather odd, but syntactically valid.
4023 if (Parser.getTok().is(AsmToken::Exclaim)) {
4024 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4025 Parser.Lex(); // Eat the '!'.
4026 }
4027
Jim Grosbach7ce05792011-08-03 23:50:40 +00004028 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004029 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004030
Jim Grosbach7ce05792011-08-03 23:50:40 +00004031 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4032 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004033
Jim Grosbach57dcb852011-10-11 17:29:55 +00004034 // If we have a ':', it's an alignment specifier.
4035 if (Parser.getTok().is(AsmToken::Colon)) {
4036 Parser.Lex(); // Eat the ':'.
4037 E = Parser.getTok().getLoc();
4038
4039 const MCExpr *Expr;
4040 if (getParser().ParseExpression(Expr))
4041 return true;
4042
4043 // The expression has to be a constant. Memory references with relocations
4044 // don't come through here, as they use the <label> forms of the relevant
4045 // instructions.
4046 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4047 if (!CE)
4048 return Error (E, "constant expression expected");
4049
4050 unsigned Align = 0;
4051 switch (CE->getValue()) {
4052 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004053 return Error(E,
4054 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4055 case 16: Align = 2; break;
4056 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004057 case 64: Align = 8; break;
4058 case 128: Align = 16; break;
4059 case 256: Align = 32; break;
4060 }
4061
4062 // Now we should have the closing ']'
4063 E = Parser.getTok().getLoc();
4064 if (Parser.getTok().isNot(AsmToken::RBrac))
4065 return Error(E, "']' expected");
4066 Parser.Lex(); // Eat right bracket token.
4067
4068 // Don't worry about range checking the value here. That's handled by
4069 // the is*() predicates.
4070 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4071 ARM_AM::no_shift, 0, Align,
4072 false, S, E));
4073
4074 // If there's a pre-indexing writeback marker, '!', just add it as a token
4075 // operand.
4076 if (Parser.getTok().is(AsmToken::Exclaim)) {
4077 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4078 Parser.Lex(); // Eat the '!'.
4079 }
4080
4081 return false;
4082 }
4083
4084 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004085 // offset. Be friendly and also accept a plain integer (without a leading
4086 // hash) for gas compatibility.
4087 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004088 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004089 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004090 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004091 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004092 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004093
Owen Anderson0da10cf2011-08-29 19:36:44 +00004094 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004095 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004096 if (getParser().ParseExpression(Offset))
4097 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004098
4099 // The expression has to be a constant. Memory references with relocations
4100 // don't come through here, as they use the <label> forms of the relevant
4101 // instructions.
4102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4103 if (!CE)
4104 return Error (E, "constant expression expected");
4105
Owen Anderson0da10cf2011-08-29 19:36:44 +00004106 // If the constant was #-0, represent it as INT32_MIN.
4107 int32_t Val = CE->getValue();
4108 if (isNegative && Val == 0)
4109 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4110
Jim Grosbach7ce05792011-08-03 23:50:40 +00004111 // Now we should have the closing ']'
4112 E = Parser.getTok().getLoc();
4113 if (Parser.getTok().isNot(AsmToken::RBrac))
4114 return Error(E, "']' expected");
4115 Parser.Lex(); // Eat right bracket token.
4116
4117 // Don't worry about range checking the value here. That's handled by
4118 // the is*() predicates.
4119 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004120 ARM_AM::no_shift, 0, 0,
4121 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004122
4123 // If there's a pre-indexing writeback marker, '!', just add it as a token
4124 // operand.
4125 if (Parser.getTok().is(AsmToken::Exclaim)) {
4126 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4127 Parser.Lex(); // Eat the '!'.
4128 }
4129
4130 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004131 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004132
4133 // The register offset is optionally preceded by a '+' or '-'
4134 bool isNegative = false;
4135 if (Parser.getTok().is(AsmToken::Minus)) {
4136 isNegative = true;
4137 Parser.Lex(); // Eat the '-'.
4138 } else if (Parser.getTok().is(AsmToken::Plus)) {
4139 // Nothing to do.
4140 Parser.Lex(); // Eat the '+'.
4141 }
4142
4143 E = Parser.getTok().getLoc();
4144 int OffsetRegNum = tryParseRegister();
4145 if (OffsetRegNum == -1)
4146 return Error(E, "register expected");
4147
4148 // If there's a shift operator, handle it.
4149 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004150 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004151 if (Parser.getTok().is(AsmToken::Comma)) {
4152 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004153 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004154 return true;
4155 }
4156
4157 // Now we should have the closing ']'
4158 E = Parser.getTok().getLoc();
4159 if (Parser.getTok().isNot(AsmToken::RBrac))
4160 return Error(E, "']' expected");
4161 Parser.Lex(); // Eat right bracket token.
4162
4163 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004164 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004165 S, E));
4166
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004167 // If there's a pre-indexing writeback marker, '!', just add it as a token
4168 // operand.
4169 if (Parser.getTok().is(AsmToken::Exclaim)) {
4170 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4171 Parser.Lex(); // Eat the '!'.
4172 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004173
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004174 return false;
4175}
4176
Jim Grosbach7ce05792011-08-03 23:50:40 +00004177/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004178/// ( lsl | lsr | asr | ror ) , # shift_amount
4179/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004180/// return true if it parses a shift otherwise it returns false.
4181bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4182 unsigned &Amount) {
4183 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004184 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004185 if (Tok.isNot(AsmToken::Identifier))
4186 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004187 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004188 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4189 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004190 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004191 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004192 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004193 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004194 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004195 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004196 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004197 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004198 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004199 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004200 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004201 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004202
Jim Grosbach7ce05792011-08-03 23:50:40 +00004203 // rrx stands alone.
4204 Amount = 0;
4205 if (St != ARM_AM::rrx) {
4206 Loc = Parser.getTok().getLoc();
4207 // A '#' and a shift amount.
4208 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004209 if (HashTok.isNot(AsmToken::Hash) &&
4210 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004211 return Error(HashTok.getLoc(), "'#' expected");
4212 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004213
Jim Grosbach7ce05792011-08-03 23:50:40 +00004214 const MCExpr *Expr;
4215 if (getParser().ParseExpression(Expr))
4216 return true;
4217 // Range check the immediate.
4218 // lsl, ror: 0 <= imm <= 31
4219 // lsr, asr: 0 <= imm <= 32
4220 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4221 if (!CE)
4222 return Error(Loc, "shift amount must be an immediate");
4223 int64_t Imm = CE->getValue();
4224 if (Imm < 0 ||
4225 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4226 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4227 return Error(Loc, "immediate shift value out of range");
4228 Amount = Imm;
4229 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004230
4231 return false;
4232}
4233
Jim Grosbach9d390362011-10-03 23:38:36 +00004234/// parseFPImm - A floating point immediate expression operand.
4235ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4236parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4237 SMLoc S = Parser.getTok().getLoc();
4238
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004239 if (Parser.getTok().isNot(AsmToken::Hash) &&
4240 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004241 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004242
4243 // Disambiguate the VMOV forms that can accept an FP immediate.
4244 // vmov.f32 <sreg>, #imm
4245 // vmov.f64 <dreg>, #imm
4246 // vmov.f32 <dreg>, #imm @ vector f32x2
4247 // vmov.f32 <qreg>, #imm @ vector f32x4
4248 //
4249 // There are also the NEON VMOV instructions which expect an
4250 // integer constant. Make sure we don't try to parse an FPImm
4251 // for these:
4252 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4253 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4254 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4255 TyOp->getToken() != ".f64"))
4256 return MatchOperand_NoMatch;
4257
Jim Grosbach9d390362011-10-03 23:38:36 +00004258 Parser.Lex(); // Eat the '#'.
4259
4260 // Handle negation, as that still comes through as a separate token.
4261 bool isNegative = false;
4262 if (Parser.getTok().is(AsmToken::Minus)) {
4263 isNegative = true;
4264 Parser.Lex();
4265 }
4266 const AsmToken &Tok = Parser.getTok();
4267 if (Tok.is(AsmToken::Real)) {
4268 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4269 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4270 // If we had a '-' in front, toggle the sign bit.
4271 IntVal ^= (uint64_t)isNegative << 63;
4272 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4273 Parser.Lex(); // Eat the token.
4274 if (Val == -1) {
4275 TokError("floating point value out of range");
4276 return MatchOperand_ParseFail;
4277 }
4278 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4279 return MatchOperand_Success;
4280 }
4281 if (Tok.is(AsmToken::Integer)) {
4282 int64_t Val = Tok.getIntVal();
4283 Parser.Lex(); // Eat the token.
4284 if (Val > 255 || Val < 0) {
4285 TokError("encoded floating point value out of range");
4286 return MatchOperand_ParseFail;
4287 }
4288 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4289 return MatchOperand_Success;
4290 }
4291
4292 TokError("invalid floating point immediate");
4293 return MatchOperand_ParseFail;
4294}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004295/// Parse a arm instruction operand. For now this parses the operand regardless
4296/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004297bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004298 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004299 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004300
4301 // Check if the current operand has a custom associated parser, if so, try to
4302 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004303 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4304 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004305 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004306 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4307 // there was a match, but an error occurred, in which case, just return that
4308 // the operand parsing failed.
4309 if (ResTy == MatchOperand_ParseFail)
4310 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004311
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004312 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004313 default:
4314 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004315 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004316 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004317 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004318 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004319 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004320 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004321 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004322 else if (Res == -1) // irrecoverable error
4323 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004324 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004325 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4326 S = Parser.getTok().getLoc();
4327 Parser.Lex();
4328 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4329 return false;
4330 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004331
4332 // Fall though for the Identifier case that is not a register or a
4333 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004334 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004335 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004336 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004337 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004338 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004339 // This was not a register so parse other operands that start with an
4340 // identifier (like labels) as expressions and create them as immediates.
4341 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004342 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004343 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004344 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004345 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004346 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4347 return false;
4348 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004349 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004350 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004351 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004352 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004353 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004354 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004355 // #42 -> immediate.
4356 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004357 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004358 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004359 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004360 const MCExpr *ImmVal;
4361 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004362 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004363 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004364 if (CE) {
4365 int32_t Val = CE->getValue();
4366 if (isNegative && Val == 0)
4367 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004368 }
Sean Callanan76264762010-04-02 22:27:05 +00004369 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004370 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4371 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004372 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004373 case AsmToken::Colon: {
4374 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004375 // FIXME: Check it's an expression prefix,
4376 // e.g. (FOO - :lower16:BAR) isn't legal.
4377 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004378 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004379 return true;
4380
Evan Cheng75972122011-01-13 07:58:56 +00004381 const MCExpr *SubExprVal;
4382 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004383 return true;
4384
Evan Cheng75972122011-01-13 07:58:56 +00004385 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4386 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004387 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004388 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004389 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004390 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004391 }
4392}
4393
Jim Grosbach1355cf12011-07-26 17:10:22 +00004394// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004395// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004396bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004397 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004398
4399 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004400 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004401 Parser.Lex(); // Eat ':'
4402
4403 if (getLexer().isNot(AsmToken::Identifier)) {
4404 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4405 return true;
4406 }
4407
4408 StringRef IDVal = Parser.getTok().getIdentifier();
4409 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004410 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004411 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004412 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004413 } else {
4414 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4415 return true;
4416 }
4417 Parser.Lex();
4418
4419 if (getLexer().isNot(AsmToken::Colon)) {
4420 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4421 return true;
4422 }
4423 Parser.Lex(); // Eat the last ':'
4424 return false;
4425}
4426
Daniel Dunbar352e1482011-01-11 15:59:50 +00004427/// \brief Given a mnemonic, split out possible predication code and carry
4428/// setting letters to form a canonical mnemonic and flags.
4429//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004430// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004431// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004432StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004433 unsigned &PredicationCode,
4434 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004435 unsigned &ProcessorIMod,
4436 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004437 PredicationCode = ARMCC::AL;
4438 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004439 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004440
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004441 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004442 //
4443 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004444 if ((Mnemonic == "movs" && isThumb()) ||
4445 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4446 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4447 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4448 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4449 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4450 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004451 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4452 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004453 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004454
Jim Grosbach3f00e312011-07-11 17:09:57 +00004455 // First, split out any predication code. Ignore mnemonics we know aren't
4456 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004457 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004458 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004459 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004460 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004461 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4462 .Case("eq", ARMCC::EQ)
4463 .Case("ne", ARMCC::NE)
4464 .Case("hs", ARMCC::HS)
4465 .Case("cs", ARMCC::HS)
4466 .Case("lo", ARMCC::LO)
4467 .Case("cc", ARMCC::LO)
4468 .Case("mi", ARMCC::MI)
4469 .Case("pl", ARMCC::PL)
4470 .Case("vs", ARMCC::VS)
4471 .Case("vc", ARMCC::VC)
4472 .Case("hi", ARMCC::HI)
4473 .Case("ls", ARMCC::LS)
4474 .Case("ge", ARMCC::GE)
4475 .Case("lt", ARMCC::LT)
4476 .Case("gt", ARMCC::GT)
4477 .Case("le", ARMCC::LE)
4478 .Case("al", ARMCC::AL)
4479 .Default(~0U);
4480 if (CC != ~0U) {
4481 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4482 PredicationCode = CC;
4483 }
Bill Wendling52925b62010-10-29 23:50:21 +00004484 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004485
Daniel Dunbar352e1482011-01-11 15:59:50 +00004486 // Next, determine if we have a carry setting bit. We explicitly ignore all
4487 // the instructions we know end in 's'.
4488 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004489 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004490 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4491 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4492 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004493 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004494 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004495 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004496 Mnemonic == "fmuls" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004497 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004498 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4499 CarrySetting = true;
4500 }
4501
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004502 // The "cps" instruction can have a interrupt mode operand which is glued into
4503 // the mnemonic. Check if this is the case, split it and parse the imod op
4504 if (Mnemonic.startswith("cps")) {
4505 // Split out any imod code.
4506 unsigned IMod =
4507 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4508 .Case("ie", ARM_PROC::IE)
4509 .Case("id", ARM_PROC::ID)
4510 .Default(~0U);
4511 if (IMod != ~0U) {
4512 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4513 ProcessorIMod = IMod;
4514 }
4515 }
4516
Jim Grosbach89df9962011-08-26 21:43:41 +00004517 // The "it" instruction has the condition mask on the end of the mnemonic.
4518 if (Mnemonic.startswith("it")) {
4519 ITMask = Mnemonic.slice(2, Mnemonic.size());
4520 Mnemonic = Mnemonic.slice(0, 2);
4521 }
4522
Daniel Dunbar352e1482011-01-11 15:59:50 +00004523 return Mnemonic;
4524}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004525
4526/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4527/// inclusion of carry set or predication code operands.
4528//
4529// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004530void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004531getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004532 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004533 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4534 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004535 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004536 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004537 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004538 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004539 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004540 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004541 Mnemonic == "mla" || Mnemonic == "smlal" ||
4542 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004543 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004544 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004545 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004546
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004547 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4548 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4549 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4550 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004551 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4552 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004553 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004554 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4555 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4556 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004557 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4558 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004559 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004560 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004561 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004562 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004563
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004564 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004565 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004566 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004567 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004568 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004569}
4570
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004571bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4572 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004573 // FIXME: This is all horribly hacky. We really need a better way to deal
4574 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004575
4576 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4577 // another does not. Specifically, the MOVW instruction does not. So we
4578 // special case it here and remove the defaulted (non-setting) cc_out
4579 // operand if that's the instruction we're trying to match.
4580 //
4581 // We do this as post-processing of the explicit operands rather than just
4582 // conditionally adding the cc_out in the first place because we need
4583 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004584 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004585 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4586 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4587 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4588 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004589
4590 // Register-register 'add' for thumb does not have a cc_out operand
4591 // when there are only two register operands.
4592 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4593 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4594 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4595 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4596 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004597 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004598 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4599 // have to check the immediate range here since Thumb2 has a variant
4600 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004601 if (((isThumb() && Mnemonic == "add") ||
4602 (isThumbTwo() && Mnemonic == "sub")) &&
4603 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004604 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4605 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4606 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004607 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4608 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4609 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004610 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004611 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4612 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004613 // selecting via the generic "add" mnemonic, so to know that we
4614 // should remove the cc_out operand, we have to explicitly check that
4615 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004616 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4617 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004618 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4619 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4620 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4621 // Nest conditions rather than one big 'if' statement for readability.
4622 //
4623 // If either register is a high reg, it's either one of the SP
4624 // variants (handled above) or a 32-bit encoding, so we just
4625 // check against T3.
4626 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4627 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4628 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4629 return false;
4630 // If both registers are low, we're in an IT block, and the immediate is
4631 // in range, we should use encoding T1 instead, which has a cc_out.
4632 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004633 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004634 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4635 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4636 return false;
4637
4638 // Otherwise, we use encoding T4, which does not have a cc_out
4639 // operand.
4640 return true;
4641 }
4642
Jim Grosbach64944f42011-09-14 21:00:40 +00004643 // The thumb2 multiply instruction doesn't have a CCOut register, so
4644 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4645 // use the 16-bit encoding or not.
4646 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4647 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4648 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4649 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4650 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4651 // If the registers aren't low regs, the destination reg isn't the
4652 // same as one of the source regs, or the cc_out operand is zero
4653 // outside of an IT block, we have to use the 32-bit encoding, so
4654 // remove the cc_out operand.
4655 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4656 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004657 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004658 !inITBlock() ||
4659 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4660 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4661 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4662 static_cast<ARMOperand*>(Operands[4])->getReg())))
4663 return true;
4664
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004665 // Also check the 'mul' syntax variant that doesn't specify an explicit
4666 // destination register.
4667 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4668 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4669 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4670 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4671 // If the registers aren't low regs or the cc_out operand is zero
4672 // outside of an IT block, we have to use the 32-bit encoding, so
4673 // remove the cc_out operand.
4674 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4675 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4676 !inITBlock()))
4677 return true;
4678
Jim Grosbach64944f42011-09-14 21:00:40 +00004679
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004680
Jim Grosbachf69c8042011-08-24 21:42:27 +00004681 // Register-register 'add/sub' for thumb does not have a cc_out operand
4682 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4683 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4684 // right, this will result in better diagnostics (which operand is off)
4685 // anyway.
4686 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4687 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004688 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4689 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4690 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4691 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004692
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004693 return false;
4694}
4695
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004696static bool isDataTypeToken(StringRef Tok) {
4697 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4698 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4699 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4700 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4701 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4702 Tok == ".f" || Tok == ".d";
4703}
4704
4705// FIXME: This bit should probably be handled via an explicit match class
4706// in the .td files that matches the suffix instead of having it be
4707// a literal string token the way it is now.
4708static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4709 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4710}
4711
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004712static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004713/// Parse an arm instruction mnemonic followed by its operands.
4714bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4715 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004716 // Apply mnemonic aliases before doing anything else, as the destination
4717 // mnemnonic may include suffices and we want to handle them normally.
4718 // The generic tblgen'erated code does this later, at the start of
4719 // MatchInstructionImpl(), but that's too late for aliases that include
4720 // any sort of suffix.
4721 unsigned AvailableFeatures = getAvailableFeatures();
4722 applyMnemonicAliases(Name, AvailableFeatures);
4723
Jim Grosbacha39cda72011-12-14 02:16:11 +00004724 // First check for the ARM-specific .req directive.
4725 if (Parser.getTok().is(AsmToken::Identifier) &&
4726 Parser.getTok().getIdentifier() == ".req") {
4727 parseDirectiveReq(Name, NameLoc);
4728 // We always return 'error' for this, as we're done with this
4729 // statement and don't need to match the 'instruction."
4730 return true;
4731 }
4732
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004733 // Create the leading tokens for the mnemonic, split by '.' characters.
4734 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004735 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004736
Daniel Dunbar352e1482011-01-11 15:59:50 +00004737 // Split out the predication code and carry setting flag from the mnemonic.
4738 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004739 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004740 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004741 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004742 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004743 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004744
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004745 // In Thumb1, only the branch (B) instruction can be predicated.
4746 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4747 Parser.EatToEndOfStatement();
4748 return Error(NameLoc, "conditional execution not supported in Thumb1");
4749 }
4750
Jim Grosbachffa32252011-07-19 19:13:28 +00004751 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4752
Jim Grosbach89df9962011-08-26 21:43:41 +00004753 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4754 // is the mask as it will be for the IT encoding if the conditional
4755 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4756 // where the conditional bit0 is zero, the instruction post-processing
4757 // will adjust the mask accordingly.
4758 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004759 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4760 if (ITMask.size() > 3) {
4761 Parser.EatToEndOfStatement();
4762 return Error(Loc, "too many conditions on IT instruction");
4763 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004764 unsigned Mask = 8;
4765 for (unsigned i = ITMask.size(); i != 0; --i) {
4766 char pos = ITMask[i - 1];
4767 if (pos != 't' && pos != 'e') {
4768 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004769 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004770 }
4771 Mask >>= 1;
4772 if (ITMask[i - 1] == 't')
4773 Mask |= 8;
4774 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004775 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004776 }
4777
Jim Grosbachffa32252011-07-19 19:13:28 +00004778 // FIXME: This is all a pretty gross hack. We should automatically handle
4779 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004780
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004781 // Next, add the CCOut and ConditionCode operands, if needed.
4782 //
4783 // For mnemonics which can ever incorporate a carry setting bit or predication
4784 // code, our matching model involves us always generating CCOut and
4785 // ConditionCode operands to match the mnemonic "as written" and then we let
4786 // the matcher deal with finding the right instruction or generating an
4787 // appropriate error.
4788 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004789 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004790
Jim Grosbach33c16a22011-07-14 22:04:21 +00004791 // If we had a carry-set on an instruction that can't do that, issue an
4792 // error.
4793 if (!CanAcceptCarrySet && CarrySetting) {
4794 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004795 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004796 "' can not set flags, but 's' suffix specified");
4797 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004798 // If we had a predication code on an instruction that can't do that, issue an
4799 // error.
4800 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4801 Parser.EatToEndOfStatement();
4802 return Error(NameLoc, "instruction '" + Mnemonic +
4803 "' is not predicable, but condition code specified");
4804 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004805
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004806 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004807 if (CanAcceptCarrySet) {
4808 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004809 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004810 Loc));
4811 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004812
4813 // Add the predication code operand, if necessary.
4814 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004815 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4816 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004817 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004818 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004819 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004820
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004821 // Add the processor imod operand, if necessary.
4822 if (ProcessorIMod) {
4823 Operands.push_back(ARMOperand::CreateImm(
4824 MCConstantExpr::Create(ProcessorIMod, getContext()),
4825 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004826 }
4827
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004828 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004829 while (Next != StringRef::npos) {
4830 Start = Next;
4831 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004832 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004833
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004834 // Some NEON instructions have an optional datatype suffix that is
4835 // completely ignored. Check for that.
4836 if (isDataTypeToken(ExtraToken) &&
4837 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4838 continue;
4839
Jim Grosbach81d2e392011-09-07 16:06:04 +00004840 if (ExtraToken != ".n") {
4841 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4842 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4843 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004844 }
4845
4846 // Read the remaining operands.
4847 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004848 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004849 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004850 Parser.EatToEndOfStatement();
4851 return true;
4852 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004853
4854 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004855 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004856
4857 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004858 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004859 Parser.EatToEndOfStatement();
4860 return true;
4861 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004862 }
4863 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004864
Chris Lattnercbf8a982010-09-11 16:18:25 +00004865 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004866 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004867 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004868 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004869 }
Bill Wendling146018f2010-11-06 21:42:12 +00004870
Chris Lattner34e53142010-09-08 05:10:46 +00004871 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004872
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004873 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4874 // do and don't have a cc_out optional-def operand. With some spot-checks
4875 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004876 // parse and adjust accordingly before actually matching. We shouldn't ever
4877 // try to remove a cc_out operand that was explicitly set on the the
4878 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4879 // table driven matcher doesn't fit well with the ARM instruction set.
4880 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004881 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4882 Operands.erase(Operands.begin() + 1);
4883 delete Op;
4884 }
4885
Jim Grosbachcf121c32011-07-28 21:57:55 +00004886 // ARM mode 'blx' need special handling, as the register operand version
4887 // is predicable, but the label operand version is not. So, we can't rely
4888 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004889 // a k_CondCode operand in the list. If we're trying to match the label
4890 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004891 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4892 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4893 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4894 Operands.erase(Operands.begin() + 1);
4895 delete Op;
4896 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004897
4898 // The vector-compare-to-zero instructions have a literal token "#0" at
4899 // the end that comes to here as an immediate operand. Convert it to a
4900 // token to play nicely with the matcher.
4901 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4902 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4903 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4904 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4905 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4906 if (CE && CE->getValue() == 0) {
4907 Operands.erase(Operands.begin() + 5);
4908 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4909 delete Op;
4910 }
4911 }
Jim Grosbach68259142011-10-03 22:30:24 +00004912 // VCMP{E} does the same thing, but with a different operand count.
4913 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4914 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4915 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4916 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4917 if (CE && CE->getValue() == 0) {
4918 Operands.erase(Operands.begin() + 4);
4919 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4920 delete Op;
4921 }
4922 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004923 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004924 // end. Convert it to a token here. Take care not to convert those
4925 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004926 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004927 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4928 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004929 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4930 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4931 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004932 if (CE && CE->getValue() == 0 &&
4933 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004934 // The cc_out operand matches the IT block.
4935 ((inITBlock() != CarrySetting) &&
4936 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004937 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004938 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004939 Operands.erase(Operands.begin() + 5);
4940 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4941 delete Op;
4942 }
4943 }
4944
Chris Lattner98986712010-01-14 22:21:20 +00004945 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004946}
4947
Jim Grosbach189610f2011-07-26 18:25:39 +00004948// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004949
4950// return 'true' if register list contains non-low GPR registers,
4951// 'false' otherwise. If Reg is in the register list or is HiReg, set
4952// 'containsReg' to true.
4953static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4954 unsigned HiReg, bool &containsReg) {
4955 containsReg = false;
4956 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4957 unsigned OpReg = Inst.getOperand(i).getReg();
4958 if (OpReg == Reg)
4959 containsReg = true;
4960 // Anything other than a low register isn't legal here.
4961 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4962 return true;
4963 }
4964 return false;
4965}
4966
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004967// Check if the specified regisgter is in the register list of the inst,
4968// starting at the indicated operand number.
4969static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4970 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4971 unsigned OpReg = Inst.getOperand(i).getReg();
4972 if (OpReg == Reg)
4973 return true;
4974 }
4975 return false;
4976}
4977
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004978// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4979// the ARMInsts array) instead. Getting that here requires awkward
4980// API changes, though. Better way?
4981namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004982extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004983}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004984static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004985 return ARMInsts[Opcode];
4986}
4987
Jim Grosbach189610f2011-07-26 18:25:39 +00004988// FIXME: We would really like to be able to tablegen'erate this.
4989bool ARMAsmParser::
4990validateInstruction(MCInst &Inst,
4991 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004992 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004993 SMLoc Loc = Operands[0]->getStartLoc();
4994 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004995 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4996 // being allowed in IT blocks, but not being predicable. It just always
4997 // executes.
4998 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004999 unsigned bit = 1;
5000 if (ITState.FirstCond)
5001 ITState.FirstCond = false;
5002 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005003 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005004 // The instruction must be predicable.
5005 if (!MCID.isPredicable())
5006 return Error(Loc, "instructions in IT block must be predicable");
5007 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5008 unsigned ITCond = bit ? ITState.Cond :
5009 ARMCC::getOppositeCondition(ITState.Cond);
5010 if (Cond != ITCond) {
5011 // Find the condition code Operand to get its SMLoc information.
5012 SMLoc CondLoc;
5013 for (unsigned i = 1; i < Operands.size(); ++i)
5014 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5015 CondLoc = Operands[i]->getStartLoc();
5016 return Error(CondLoc, "incorrect condition in IT block; got '" +
5017 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5018 "', but expected '" +
5019 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5020 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005021 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005022 } else if (isThumbTwo() && MCID.isPredicable() &&
5023 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005024 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5025 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005026 return Error(Loc, "predicated instructions must be in IT block");
5027
Jim Grosbach189610f2011-07-26 18:25:39 +00005028 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005029 case ARM::LDRD:
5030 case ARM::LDRD_PRE:
5031 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005032 case ARM::LDREXD: {
5033 // Rt2 must be Rt + 1.
5034 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5035 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5036 if (Rt2 != Rt + 1)
5037 return Error(Operands[3]->getStartLoc(),
5038 "destination operands must be sequential");
5039 return false;
5040 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005041 case ARM::STRD: {
5042 // Rt2 must be Rt + 1.
5043 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5044 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5045 if (Rt2 != Rt + 1)
5046 return Error(Operands[3]->getStartLoc(),
5047 "source operands must be sequential");
5048 return false;
5049 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005050 case ARM::STRD_PRE:
5051 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005052 case ARM::STREXD: {
5053 // Rt2 must be Rt + 1.
5054 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5055 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5056 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005057 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005058 "source operands must be sequential");
5059 return false;
5060 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005061 case ARM::SBFX:
5062 case ARM::UBFX: {
5063 // width must be in range [1, 32-lsb]
5064 unsigned lsb = Inst.getOperand(2).getImm();
5065 unsigned widthm1 = Inst.getOperand(3).getImm();
5066 if (widthm1 >= 32 - lsb)
5067 return Error(Operands[5]->getStartLoc(),
5068 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005069 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005070 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005071 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005072 // If we're parsing Thumb2, the .w variant is available and handles
5073 // most cases that are normally illegal for a Thumb1 LDM
5074 // instruction. We'll make the transformation in processInstruction()
5075 // if necessary.
5076 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005077 // Thumb LDM instructions are writeback iff the base register is not
5078 // in the register list.
5079 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005080 bool hasWritebackToken =
5081 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5082 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005083 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005084 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005085 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5086 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005087 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005088 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005089 return Error(Operands[2]->getStartLoc(),
5090 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005091 // If we should not have writeback, there must not be a '!'. This is
5092 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005093 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005094 return Error(Operands[3]->getStartLoc(),
5095 "writeback operator '!' not allowed when base register "
5096 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005097
5098 break;
5099 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005100 case ARM::t2LDMIA_UPD: {
5101 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5102 return Error(Operands[4]->getStartLoc(),
5103 "writeback operator '!' not allowed when base register "
5104 "in register list");
5105 break;
5106 }
Jim Grosbach54026372011-11-10 23:17:11 +00005107 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5108 // so only issue a diagnostic for thumb1. The instructions will be
5109 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005110 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005111 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005112 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5113 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005114 return Error(Operands[2]->getStartLoc(),
5115 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005116 break;
5117 }
5118 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005119 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005120 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5121 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005122 return Error(Operands[2]->getStartLoc(),
5123 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005124 break;
5125 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005126 case ARM::tSTMIA_UPD: {
5127 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005128 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005129 return Error(Operands[4]->getStartLoc(),
5130 "registers must be in range r0-r7");
5131 break;
5132 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005133 }
5134
5135 return false;
5136}
5137
Jim Grosbach5b484312011-12-20 20:46:29 +00005138static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005139 switch(Opc) {
5140 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005141 // VST1LN
5142 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5143 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5144 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005145 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005146 return ARM::VST1LNd8_UPD;
5147 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5148 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5149 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005150 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005151 return ARM::VST1LNd16_UPD;
5152 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5153 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5154 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005155 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005156 return ARM::VST1LNd32_UPD;
5157 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5158 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5159 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005160 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005161 return ARM::VST1LNd8_UPD;
5162 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5163 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5164 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005165 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005166 return ARM::VST1LNd16_UPD;
5167 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5168 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5169 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005170 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005171 return ARM::VST1LNd32_UPD;
5172 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5173 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5174 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005175 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005176 return ARM::VST1LNd8;
5177 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5178 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5179 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005180 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005181 return ARM::VST1LNd16;
5182 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5183 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5184 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005185 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005186 return ARM::VST1LNd32;
5187
5188 // VST2LN
5189 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5190 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5191 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005192 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005193 return ARM::VST2LNd8_UPD;
5194 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5195 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5196 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005197 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005198 return ARM::VST2LNd16_UPD;
5199 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5200 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5201 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005202 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005203 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005204 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5205 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5206 case ARM::VST2LNqWB_fixed_Asm_U16:
5207 Spacing = 2;
5208 return ARM::VST2LNq16_UPD;
5209 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5210 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5211 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5212 Spacing = 2;
5213 return ARM::VST2LNq32_UPD;
5214
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005215 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5216 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5217 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005218 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005219 return ARM::VST2LNd8_UPD;
5220 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5221 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5222 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005223 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005224 return ARM::VST2LNd16_UPD;
5225 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5226 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5227 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005228 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005229 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005230 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5231 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5232 case ARM::VST2LNqWB_register_Asm_U16:
5233 Spacing = 2;
5234 return ARM::VST2LNq16_UPD;
5235 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5236 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5237 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5238 Spacing = 2;
5239 return ARM::VST2LNq32_UPD;
5240
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005241 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5242 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5243 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005244 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005245 return ARM::VST2LNd8;
5246 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5247 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5248 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005249 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005250 return ARM::VST2LNd16;
5251 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5252 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5253 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005254 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005255 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005256 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5257 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5258 case ARM::VST2LNqAsm_U16:
5259 Spacing = 2;
5260 return ARM::VST2LNq16;
5261 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5262 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5263 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5264 Spacing = 2;
5265 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005266 }
5267}
5268
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005269static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005270 switch(Opc) {
5271 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005272 // VLD1LN
5273 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5274 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5275 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005276 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005277 return ARM::VLD1LNd8_UPD;
5278 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5279 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5280 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005281 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005282 return ARM::VLD1LNd16_UPD;
5283 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5284 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5285 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005286 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005287 return ARM::VLD1LNd32_UPD;
5288 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5289 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5290 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005291 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005292 return ARM::VLD1LNd8_UPD;
5293 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5294 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5295 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005296 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005297 return ARM::VLD1LNd16_UPD;
5298 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5299 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5300 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005301 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005302 return ARM::VLD1LNd32_UPD;
5303 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5304 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5305 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005306 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005307 return ARM::VLD1LNd8;
5308 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5309 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5310 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005311 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005312 return ARM::VLD1LNd16;
5313 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5314 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5315 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005316 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005317 return ARM::VLD1LNd32;
5318
5319 // VLD2LN
5320 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5321 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5322 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005323 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005324 return ARM::VLD2LNd8_UPD;
5325 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5326 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5327 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005328 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005329 return ARM::VLD2LNd16_UPD;
5330 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5331 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5332 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005333 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005334 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005335 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5336 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5337 case ARM::VLD2LNqWB_fixed_Asm_U16:
5338 Spacing = 1;
5339 return ARM::VLD2LNq16_UPD;
5340 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5341 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5342 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5343 Spacing = 2;
5344 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005345 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5346 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5347 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005348 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005349 return ARM::VLD2LNd8_UPD;
5350 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5351 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5352 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005353 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005354 return ARM::VLD2LNd16_UPD;
5355 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5356 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5357 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005358 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005359 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005360 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5361 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5362 case ARM::VLD2LNqWB_register_Asm_U16:
5363 Spacing = 2;
5364 return ARM::VLD2LNq16_UPD;
5365 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5366 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5367 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5368 Spacing = 2;
5369 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005370 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5371 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5372 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005373 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005374 return ARM::VLD2LNd8;
5375 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5376 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5377 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005378 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005379 return ARM::VLD2LNd16;
5380 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5381 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5382 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005383 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005384 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005385 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5386 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5387 case ARM::VLD2LNqAsm_U16:
5388 Spacing = 2;
5389 return ARM::VLD2LNq16;
5390 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5391 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5392 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5393 Spacing = 2;
5394 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005395 }
5396}
5397
Jim Grosbach83ec8772011-11-10 23:42:14 +00005398bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005399processInstruction(MCInst &Inst,
5400 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5401 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005402 // Handle NEON VST complex aliases.
5403 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5404 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5405 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5406 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5407 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5408 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5409 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5410 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005411 MCInst TmpInst;
5412 // Shuffle the operands around so the lane index operand is in the
5413 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005414 unsigned Spacing;
5415 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005416 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5417 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5418 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5419 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5420 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5421 TmpInst.addOperand(Inst.getOperand(1)); // lane
5422 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5423 TmpInst.addOperand(Inst.getOperand(6));
5424 Inst = TmpInst;
5425 return true;
5426 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005427
Jim Grosbach5b484312011-12-20 20:46:29 +00005428 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5429 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5430 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005431 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5432 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005433 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005434 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005435 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5436 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5437 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5438 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5439 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5440 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5441 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005442 MCInst TmpInst;
5443 // Shuffle the operands around so the lane index operand is in the
5444 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005445 unsigned Spacing;
5446 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005447 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5448 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5449 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5450 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5451 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005452 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5453 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005454 TmpInst.addOperand(Inst.getOperand(1)); // lane
5455 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5456 TmpInst.addOperand(Inst.getOperand(6));
5457 Inst = TmpInst;
5458 return true;
5459 }
5460 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5461 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5462 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5463 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5464 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5465 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5466 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5467 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005468 MCInst TmpInst;
5469 // Shuffle the operands around so the lane index operand is in the
5470 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005471 unsigned Spacing;
5472 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005473 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5474 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5475 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5476 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5477 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5478 TmpInst.addOperand(Inst.getOperand(1)); // lane
5479 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5480 TmpInst.addOperand(Inst.getOperand(5));
5481 Inst = TmpInst;
5482 return true;
5483 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005484
Jim Grosbach5b484312011-12-20 20:46:29 +00005485 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5486 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5487 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005488 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5489 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005490 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005491 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005492 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5493 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5494 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5495 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5496 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5497 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5498 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005499 MCInst TmpInst;
5500 // Shuffle the operands around so the lane index operand is in the
5501 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005502 unsigned Spacing;
5503 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005504 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5505 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5506 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5507 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5508 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005509 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5510 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005511 TmpInst.addOperand(Inst.getOperand(1)); // lane
5512 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5513 TmpInst.addOperand(Inst.getOperand(5));
5514 Inst = TmpInst;
5515 return true;
5516 }
5517 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5518 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5519 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5520 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5521 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005522 case ARM::VST1LNdAsm_U32: {
5523 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;
5527 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005528 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5529 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5530 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5531 TmpInst.addOperand(Inst.getOperand(1)); // lane
5532 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5533 TmpInst.addOperand(Inst.getOperand(5));
5534 Inst = TmpInst;
5535 return true;
5536 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005537
Jim Grosbach5b484312011-12-20 20:46:29 +00005538 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5539 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005540 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005541 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005542 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005543 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5544 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5545 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5546 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005547 MCInst TmpInst;
5548 // Shuffle the operands around so the lane index operand is in the
5549 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005550 unsigned Spacing;
5551 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005552 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5553 TmpInst.addOperand(Inst.getOperand(3)); // alignment
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(4)); // CondCode
5559 TmpInst.addOperand(Inst.getOperand(5));
5560 Inst = TmpInst;
5561 return true;
5562 }
5563 // Handle NEON VLD complex aliases.
5564 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5565 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5566 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5567 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5568 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5569 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5570 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5571 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005572 MCInst TmpInst;
5573 // Shuffle the operands around so the lane index operand is in the
5574 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005575 unsigned Spacing;
5576 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005577 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5578 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5579 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5580 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5581 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5582 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5583 TmpInst.addOperand(Inst.getOperand(1)); // lane
5584 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5585 TmpInst.addOperand(Inst.getOperand(6));
5586 Inst = TmpInst;
5587 return true;
5588 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005589
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005590 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5591 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5592 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005593 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5594 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005595 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005596 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005597 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005598 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5599 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5600 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5601 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5602 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5603 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005604 MCInst TmpInst;
5605 // Shuffle the operands around so the lane index operand is in the
5606 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005607 unsigned Spacing;
5608 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005609 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005610 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5611 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005612 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5613 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5614 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5615 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5616 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005617 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5618 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005619 TmpInst.addOperand(Inst.getOperand(1)); // lane
5620 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5621 TmpInst.addOperand(Inst.getOperand(6));
5622 Inst = TmpInst;
5623 return true;
5624 }
5625
5626 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5627 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5628 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5629 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5630 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5631 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5632 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5633 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005634 MCInst TmpInst;
5635 // Shuffle the operands around so the lane index operand is in the
5636 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005637 unsigned Spacing;
5638 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005639 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5640 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5641 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5642 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5643 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5644 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5645 TmpInst.addOperand(Inst.getOperand(1)); // lane
5646 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5647 TmpInst.addOperand(Inst.getOperand(5));
5648 Inst = TmpInst;
5649 return true;
5650 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005651
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005652 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5653 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5654 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005655 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5656 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005657 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005658 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005659 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005660 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5661 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5662 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5663 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5664 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5665 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005666 MCInst TmpInst;
5667 // Shuffle the operands around so the lane index operand is in the
5668 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005669 unsigned Spacing;
5670 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005671 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005672 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5673 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005674 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5675 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5676 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5677 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5678 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005679 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5680 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005681 TmpInst.addOperand(Inst.getOperand(1)); // lane
5682 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5683 TmpInst.addOperand(Inst.getOperand(5));
5684 Inst = TmpInst;
5685 return true;
5686 }
5687
Jim Grosbach5b484312011-12-20 20:46:29 +00005688 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5689 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005690 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005691 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005692 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005693 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005694 MCInst TmpInst;
5695 // Shuffle the operands around so the lane index operand is in the
5696 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005697 unsigned Spacing;
5698 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005699 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5700 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5701 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5702 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5703 TmpInst.addOperand(Inst.getOperand(1)); // lane
5704 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5705 TmpInst.addOperand(Inst.getOperand(5));
5706 Inst = TmpInst;
5707 return true;
5708 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005709
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005710 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5711 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005712 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005713 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005714 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005715 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5716 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5717 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5718 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5719 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005720 MCInst TmpInst;
5721 // Shuffle the operands around so the lane index operand is in the
5722 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005723 unsigned Spacing;
5724 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005725 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005726 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5727 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005728 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5729 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5730 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005731 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5732 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005733 TmpInst.addOperand(Inst.getOperand(1)); // lane
5734 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5735 TmpInst.addOperand(Inst.getOperand(5));
5736 Inst = TmpInst;
5737 return true;
5738 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005739 // Handle the Thumb2 mode MOV complex aliases.
5740 case ARM::t2MOVsi:
5741 case ARM::t2MOVSsi: {
5742 // Which instruction to expand to depends on the CCOut operand and
5743 // whether we're in an IT block if the register operands are low
5744 // registers.
5745 bool isNarrow = false;
5746 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5747 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5748 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5749 isNarrow = true;
5750 MCInst TmpInst;
5751 unsigned newOpc;
5752 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5753 default: llvm_unreachable("unexpected opcode!");
5754 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5755 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5756 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5757 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5758 }
5759 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5760 if (Ammount == 32) Ammount = 0;
5761 TmpInst.setOpcode(newOpc);
5762 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5763 if (isNarrow)
5764 TmpInst.addOperand(MCOperand::CreateReg(
5765 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5766 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5767 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5768 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5769 TmpInst.addOperand(Inst.getOperand(4));
5770 if (!isNarrow)
5771 TmpInst.addOperand(MCOperand::CreateReg(
5772 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5773 Inst = TmpInst;
5774 return true;
5775 }
5776 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005777 case ARM::ASRr:
5778 case ARM::LSRr:
5779 case ARM::LSLr:
5780 case ARM::RORr: {
5781 ARM_AM::ShiftOpc ShiftTy;
5782 switch(Inst.getOpcode()) {
5783 default: llvm_unreachable("unexpected opcode!");
5784 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5785 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5786 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5787 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5788 }
5789 // A shift by zero is a plain MOVr, not a MOVsi.
5790 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5791 MCInst TmpInst;
5792 TmpInst.setOpcode(ARM::MOVsr);
5793 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5794 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5795 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5796 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5797 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5798 TmpInst.addOperand(Inst.getOperand(4));
5799 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5800 Inst = TmpInst;
5801 return true;
5802 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005803 case ARM::ASRi:
5804 case ARM::LSRi:
5805 case ARM::LSLi:
5806 case ARM::RORi: {
5807 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005808 switch(Inst.getOpcode()) {
5809 default: llvm_unreachable("unexpected opcode!");
5810 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5811 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5812 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5813 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5814 }
5815 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005816 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005817 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5818 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005819 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005820 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005821 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5822 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005823 if (Opc == ARM::MOVsi)
5824 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005825 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5826 TmpInst.addOperand(Inst.getOperand(4));
5827 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5828 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005829 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005830 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005831 case ARM::RRXi: {
5832 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5833 MCInst TmpInst;
5834 TmpInst.setOpcode(ARM::MOVsi);
5835 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5836 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5837 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5838 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5839 TmpInst.addOperand(Inst.getOperand(3));
5840 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5841 Inst = TmpInst;
5842 return true;
5843 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005844 case ARM::t2LDMIA_UPD: {
5845 // If this is a load of a single register, then we should use
5846 // a post-indexed LDR instruction instead, per the ARM ARM.
5847 if (Inst.getNumOperands() != 5)
5848 return false;
5849 MCInst TmpInst;
5850 TmpInst.setOpcode(ARM::t2LDR_POST);
5851 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5852 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5853 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5854 TmpInst.addOperand(MCOperand::CreateImm(4));
5855 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5856 TmpInst.addOperand(Inst.getOperand(3));
5857 Inst = TmpInst;
5858 return true;
5859 }
5860 case ARM::t2STMDB_UPD: {
5861 // If this is a store of a single register, then we should use
5862 // a pre-indexed STR instruction instead, per the ARM ARM.
5863 if (Inst.getNumOperands() != 5)
5864 return false;
5865 MCInst TmpInst;
5866 TmpInst.setOpcode(ARM::t2STR_PRE);
5867 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5868 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5869 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5870 TmpInst.addOperand(MCOperand::CreateImm(-4));
5871 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5872 TmpInst.addOperand(Inst.getOperand(3));
5873 Inst = TmpInst;
5874 return true;
5875 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005876 case ARM::LDMIA_UPD:
5877 // If this is a load of a single register via a 'pop', then we should use
5878 // a post-indexed LDR instruction instead, per the ARM ARM.
5879 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5880 Inst.getNumOperands() == 5) {
5881 MCInst TmpInst;
5882 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5883 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5884 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5885 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5886 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5887 TmpInst.addOperand(MCOperand::CreateImm(4));
5888 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5889 TmpInst.addOperand(Inst.getOperand(3));
5890 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005891 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005892 }
5893 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005894 case ARM::STMDB_UPD:
5895 // If this is a store of a single register via a 'push', then we should use
5896 // a pre-indexed STR instruction instead, per the ARM ARM.
5897 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5898 Inst.getNumOperands() == 5) {
5899 MCInst TmpInst;
5900 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5901 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5902 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5903 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5904 TmpInst.addOperand(MCOperand::CreateImm(-4));
5905 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5906 TmpInst.addOperand(Inst.getOperand(3));
5907 Inst = TmpInst;
5908 }
5909 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005910 case ARM::t2ADDri12:
5911 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5912 // mnemonic was used (not "addw"), encoding T3 is preferred.
5913 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5914 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5915 break;
5916 Inst.setOpcode(ARM::t2ADDri);
5917 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5918 break;
5919 case ARM::t2SUBri12:
5920 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5921 // mnemonic was used (not "subw"), encoding T3 is preferred.
5922 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5923 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5924 break;
5925 Inst.setOpcode(ARM::t2SUBri);
5926 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5927 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005928 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005929 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5930 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5931 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5932 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005933 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005934 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005935 return true;
5936 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005937 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005938 case ARM::tSUBi8:
5939 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5940 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5941 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5942 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005943 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005944 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005945 return true;
5946 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005947 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005948 case ARM::t2ADDrr: {
5949 // If the destination and first source operand are the same, and
5950 // there's no setting of the flags, use encoding T2 instead of T3.
5951 // Note that this is only for ADD, not SUB. This mirrors the system
5952 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5953 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5954 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005955 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5956 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005957 break;
5958 MCInst TmpInst;
5959 TmpInst.setOpcode(ARM::tADDhirr);
5960 TmpInst.addOperand(Inst.getOperand(0));
5961 TmpInst.addOperand(Inst.getOperand(0));
5962 TmpInst.addOperand(Inst.getOperand(2));
5963 TmpInst.addOperand(Inst.getOperand(3));
5964 TmpInst.addOperand(Inst.getOperand(4));
5965 Inst = TmpInst;
5966 return true;
5967 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005968 case ARM::tB:
5969 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005970 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005971 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005972 return true;
5973 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005974 break;
5975 case ARM::t2B:
5976 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005977 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005978 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005979 return true;
5980 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005981 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005982 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005983 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005984 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005985 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005986 return true;
5987 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005988 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005989 case ARM::tBcc:
5990 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005991 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005992 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005993 return true;
5994 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005995 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005996 case ARM::tLDMIA: {
5997 // If the register list contains any high registers, or if the writeback
5998 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5999 // instead if we're in Thumb2. Otherwise, this should have generated
6000 // an error in validateInstruction().
6001 unsigned Rn = Inst.getOperand(0).getReg();
6002 bool hasWritebackToken =
6003 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6004 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6005 bool listContainsBase;
6006 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6007 (!listContainsBase && !hasWritebackToken) ||
6008 (listContainsBase && hasWritebackToken)) {
6009 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6010 assert (isThumbTwo());
6011 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6012 // If we're switching to the updating version, we need to insert
6013 // the writeback tied operand.
6014 if (hasWritebackToken)
6015 Inst.insert(Inst.begin(),
6016 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006017 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006018 }
6019 break;
6020 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006021 case ARM::tSTMIA_UPD: {
6022 // If the register list contains any high registers, we need to use
6023 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6024 // should have generated an error in validateInstruction().
6025 unsigned Rn = Inst.getOperand(0).getReg();
6026 bool listContainsBase;
6027 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6028 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6029 assert (isThumbTwo());
6030 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006031 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006032 }
6033 break;
6034 }
Jim Grosbach54026372011-11-10 23:17:11 +00006035 case ARM::tPOP: {
6036 bool listContainsBase;
6037 // If the register list contains any high registers, we need to use
6038 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6039 // should have generated an error in validateInstruction().
6040 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006041 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006042 assert (isThumbTwo());
6043 Inst.setOpcode(ARM::t2LDMIA_UPD);
6044 // Add the base register and writeback operands.
6045 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6046 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006047 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006048 }
6049 case ARM::tPUSH: {
6050 bool listContainsBase;
6051 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006052 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006053 assert (isThumbTwo());
6054 Inst.setOpcode(ARM::t2STMDB_UPD);
6055 // Add the base register and writeback operands.
6056 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6057 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006058 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006059 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006060 case ARM::t2MOVi: {
6061 // If we can use the 16-bit encoding and the user didn't explicitly
6062 // request the 32-bit variant, transform it here.
6063 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6064 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006065 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6066 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6067 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006068 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6069 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6070 // The operands aren't in the same order for tMOVi8...
6071 MCInst TmpInst;
6072 TmpInst.setOpcode(ARM::tMOVi8);
6073 TmpInst.addOperand(Inst.getOperand(0));
6074 TmpInst.addOperand(Inst.getOperand(4));
6075 TmpInst.addOperand(Inst.getOperand(1));
6076 TmpInst.addOperand(Inst.getOperand(2));
6077 TmpInst.addOperand(Inst.getOperand(3));
6078 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006079 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006080 }
6081 break;
6082 }
6083 case ARM::t2MOVr: {
6084 // If we can use the 16-bit encoding and the user didn't explicitly
6085 // request the 32-bit variant, transform it here.
6086 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6087 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6088 Inst.getOperand(2).getImm() == ARMCC::AL &&
6089 Inst.getOperand(4).getReg() == ARM::CPSR &&
6090 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6091 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6092 // The operands aren't the same for tMOV[S]r... (no cc_out)
6093 MCInst TmpInst;
6094 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6095 TmpInst.addOperand(Inst.getOperand(0));
6096 TmpInst.addOperand(Inst.getOperand(1));
6097 TmpInst.addOperand(Inst.getOperand(2));
6098 TmpInst.addOperand(Inst.getOperand(3));
6099 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006100 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006101 }
6102 break;
6103 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006104 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006105 case ARM::t2SXTB:
6106 case ARM::t2UXTH:
6107 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006108 // If we can use the 16-bit encoding and the user didn't explicitly
6109 // request the 32-bit variant, transform it here.
6110 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6111 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6112 Inst.getOperand(2).getImm() == 0 &&
6113 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6114 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006115 unsigned NewOpc;
6116 switch (Inst.getOpcode()) {
6117 default: llvm_unreachable("Illegal opcode!");
6118 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6119 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6120 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6121 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6122 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006123 // The operands aren't the same for thumb1 (no rotate operand).
6124 MCInst TmpInst;
6125 TmpInst.setOpcode(NewOpc);
6126 TmpInst.addOperand(Inst.getOperand(0));
6127 TmpInst.addOperand(Inst.getOperand(1));
6128 TmpInst.addOperand(Inst.getOperand(3));
6129 TmpInst.addOperand(Inst.getOperand(4));
6130 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006131 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006132 }
6133 break;
6134 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006135 case ARM::MOVsi: {
6136 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6137 if (SOpc == ARM_AM::rrx) return false;
6138 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6139 // Shifting by zero is accepted as a vanilla 'MOVr'
6140 MCInst TmpInst;
6141 TmpInst.setOpcode(ARM::MOVr);
6142 TmpInst.addOperand(Inst.getOperand(0));
6143 TmpInst.addOperand(Inst.getOperand(1));
6144 TmpInst.addOperand(Inst.getOperand(3));
6145 TmpInst.addOperand(Inst.getOperand(4));
6146 TmpInst.addOperand(Inst.getOperand(5));
6147 Inst = TmpInst;
6148 return true;
6149 }
6150 return false;
6151 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006152 case ARM::t2IT: {
6153 // The mask bits for all but the first condition are represented as
6154 // the low bit of the condition code value implies 't'. We currently
6155 // always have 1 implies 't', so XOR toggle the bits if the low bit
6156 // of the condition code is zero. The encoding also expects the low
6157 // bit of the condition to be encoded as bit 4 of the mask operand,
6158 // so mask that in if needed
6159 MCOperand &MO = Inst.getOperand(1);
6160 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006161 unsigned OrigMask = Mask;
6162 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006163 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006164 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6165 for (unsigned i = 3; i != TZ; --i)
6166 Mask ^= 1 << i;
6167 } else
6168 Mask |= 0x10;
6169 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006170
6171 // Set up the IT block state according to the IT instruction we just
6172 // matched.
6173 assert(!inITBlock() && "nested IT blocks?!");
6174 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6175 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6176 ITState.CurPosition = 0;
6177 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006178 break;
6179 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006180 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006181 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006182}
6183
Jim Grosbach47a0d522011-08-16 20:45:50 +00006184unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6185 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6186 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006187 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006188 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006189 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6190 assert(MCID.hasOptionalDef() &&
6191 "optionally flag setting instruction missing optional def operand");
6192 assert(MCID.NumOperands == Inst.getNumOperands() &&
6193 "operand count mismatch!");
6194 // Find the optional-def operand (cc_out).
6195 unsigned OpNo;
6196 for (OpNo = 0;
6197 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6198 ++OpNo)
6199 ;
6200 // If we're parsing Thumb1, reject it completely.
6201 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6202 return Match_MnemonicFail;
6203 // If we're parsing Thumb2, which form is legal depends on whether we're
6204 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006205 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6206 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006207 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006208 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6209 inITBlock())
6210 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006211 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006212 // Some high-register supporting Thumb1 encodings only allow both registers
6213 // to be from r0-r7 when in Thumb2.
6214 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6215 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6216 isARMLowRegister(Inst.getOperand(2).getReg()))
6217 return Match_RequiresThumb2;
6218 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006219 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006220 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6221 isARMLowRegister(Inst.getOperand(1).getReg()))
6222 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006223 return Match_Success;
6224}
6225
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006226bool ARMAsmParser::
6227MatchAndEmitInstruction(SMLoc IDLoc,
6228 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6229 MCStreamer &Out) {
6230 MCInst Inst;
6231 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006232 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006233 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006234 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006235 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006236 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006237 // Context sensitive operand constraints aren't handled by the matcher,
6238 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006239 if (validateInstruction(Inst, Operands)) {
6240 // Still progress the IT block, otherwise one wrong condition causes
6241 // nasty cascading errors.
6242 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006243 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006244 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006245
Jim Grosbachf8fce712011-08-11 17:35:48 +00006246 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006247 // encoding is selected. Loop on it while changes happen so the
6248 // individual transformations can chain off each other. E.g.,
6249 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6250 while (processInstruction(Inst, Operands))
6251 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006252
Jim Grosbacha1109882011-09-02 23:22:08 +00006253 // Only move forward at the very end so that everything in validate
6254 // and process gets a consistent answer about whether we're in an IT
6255 // block.
6256 forwardITPosition();
6257
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006258 Out.EmitInstruction(Inst);
6259 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006260 case Match_MissingFeature:
6261 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6262 return true;
6263 case Match_InvalidOperand: {
6264 SMLoc ErrorLoc = IDLoc;
6265 if (ErrorInfo != ~0U) {
6266 if (ErrorInfo >= Operands.size())
6267 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006268
Chris Lattnere73d4f82010-10-28 21:41:58 +00006269 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6270 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6271 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006272
Chris Lattnere73d4f82010-10-28 21:41:58 +00006273 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006274 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006275 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006276 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006277 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006278 // The converter function will have already emited a diagnostic.
6279 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006280 case Match_RequiresNotITBlock:
6281 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006282 case Match_RequiresITBlock:
6283 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006284 case Match_RequiresV6:
6285 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6286 case Match_RequiresThumb2:
6287 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006288 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006289
Eric Christopherc223e2b2010-10-29 09:26:59 +00006290 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006291 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006292}
6293
Jim Grosbach1355cf12011-07-26 17:10:22 +00006294/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006295bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6296 StringRef IDVal = DirectiveID.getIdentifier();
6297 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006298 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006299 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006300 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006301 else if (IDVal == ".arm")
6302 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006303 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006304 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006305 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006306 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006307 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006308 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006309 else if (IDVal == ".unreq")
6310 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006311 else if (IDVal == ".arch")
6312 return parseDirectiveArch(DirectiveID.getLoc());
6313 else if (IDVal == ".eabi_attribute")
6314 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006315 return true;
6316}
6317
Jim Grosbach1355cf12011-07-26 17:10:22 +00006318/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006319/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006320bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006321 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6322 for (;;) {
6323 const MCExpr *Value;
6324 if (getParser().ParseExpression(Value))
6325 return true;
6326
Chris Lattneraaec2052010-01-19 19:46:13 +00006327 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006328
6329 if (getLexer().is(AsmToken::EndOfStatement))
6330 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006331
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006332 // FIXME: Improve diagnostic.
6333 if (getLexer().isNot(AsmToken::Comma))
6334 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006335 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006336 }
6337 }
6338
Sean Callananb9a25b72010-01-19 20:27:46 +00006339 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006340 return false;
6341}
6342
Jim Grosbach1355cf12011-07-26 17:10:22 +00006343/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006344/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006345bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006346 if (getLexer().isNot(AsmToken::EndOfStatement))
6347 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006348 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006349
Jim Grosbach9a70df92011-12-07 18:04:19 +00006350 if (!isThumb())
6351 SwitchMode();
6352 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6353 return false;
6354}
6355
6356/// parseDirectiveARM
6357/// ::= .arm
6358bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6359 if (getLexer().isNot(AsmToken::EndOfStatement))
6360 return Error(L, "unexpected token in directive");
6361 Parser.Lex();
6362
6363 if (isThumb())
6364 SwitchMode();
6365 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006366 return false;
6367}
6368
Jim Grosbach1355cf12011-07-26 17:10:22 +00006369/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006370/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006371bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006372 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6373 bool isMachO = MAI.hasSubsectionsViaSymbols();
6374 StringRef Name;
6375
6376 // Darwin asm has function name after .thumb_func direction
6377 // ELF doesn't
6378 if (isMachO) {
6379 const AsmToken &Tok = Parser.getTok();
6380 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6381 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00006382 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006383 Parser.Lex(); // Consume the identifier token.
6384 }
6385
Jim Grosbachd475f862011-11-10 20:48:53 +00006386 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006387 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006388 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006389
Rafael Espindola64695402011-05-16 16:17:21 +00006390 // FIXME: assuming function name will be the line following .thumb_func
6391 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006392 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006393 }
6394
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006395 // Mark symbol as a thumb symbol.
6396 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6397 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006398 return false;
6399}
6400
Jim Grosbach1355cf12011-07-26 17:10:22 +00006401/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006402/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006403bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006404 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006405 if (Tok.isNot(AsmToken::Identifier))
6406 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006407 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006408 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006409 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006410 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006411 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006412 else
6413 return Error(L, "unrecognized syntax mode in .syntax directive");
6414
6415 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006416 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006417 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006418
6419 // TODO tell the MC streamer the mode
6420 // getParser().getStreamer().Emit???();
6421 return false;
6422}
6423
Jim Grosbach1355cf12011-07-26 17:10:22 +00006424/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006425/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006426bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006427 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006428 if (Tok.isNot(AsmToken::Integer))
6429 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006430 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006431 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006432 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006433 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006434 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006435 else
6436 return Error(L, "invalid operand to .code directive");
6437
6438 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006439 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006440 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006441
Evan Cheng32869202011-07-08 22:36:29 +00006442 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006443 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006444 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006445 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006446 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006447 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006448 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006449 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006450 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006451
Kevin Enderby515d5092009-10-15 20:48:48 +00006452 return false;
6453}
6454
Jim Grosbacha39cda72011-12-14 02:16:11 +00006455/// parseDirectiveReq
6456/// ::= name .req registername
6457bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6458 Parser.Lex(); // Eat the '.req' token.
6459 unsigned Reg;
6460 SMLoc SRegLoc, ERegLoc;
6461 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6462 Parser.EatToEndOfStatement();
6463 return Error(SRegLoc, "register name expected");
6464 }
6465
6466 // Shouldn't be anything else.
6467 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6468 Parser.EatToEndOfStatement();
6469 return Error(Parser.getTok().getLoc(),
6470 "unexpected input in .req directive.");
6471 }
6472
6473 Parser.Lex(); // Consume the EndOfStatement
6474
6475 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6476 return Error(SRegLoc, "redefinition of '" + Name +
6477 "' does not match original.");
6478
6479 return false;
6480}
6481
6482/// parseDirectiveUneq
6483/// ::= .unreq registername
6484bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6485 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6486 Parser.EatToEndOfStatement();
6487 return Error(L, "unexpected input in .unreq directive.");
6488 }
6489 RegisterReqs.erase(Parser.getTok().getIdentifier());
6490 Parser.Lex(); // Eat the identifier.
6491 return false;
6492}
6493
Jason W Kimd7c9e082011-12-20 17:38:12 +00006494/// parseDirectiveArch
6495/// ::= .arch token
6496bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6497 return true;
6498}
6499
6500/// parseDirectiveEabiAttr
6501/// ::= .eabi_attribute int, int
6502bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6503 return true;
6504}
6505
Sean Callanan90b70972010-04-07 20:29:34 +00006506extern "C" void LLVMInitializeARMAsmLexer();
6507
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006508/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006509extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006510 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6511 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006512 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006513}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006514
Chris Lattner0692ee62010-09-06 19:11:01 +00006515#define GET_REGISTER_MATCHER
6516#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006517#include "ARMGenAsmMatcher.inc"