blob: d70511ff556da3132045c77d355864e23190fc9a [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 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002424 // shift by zero is a nop. Always send it through as lsl.
2425 // ('as' compatibility)
2426 if (Imm == 0)
2427 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002428 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002429 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002430 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002431 if (ShiftReg == -1) {
2432 Error (L, "expected immediate or register in shift operand");
2433 return -1;
2434 }
2435 } else {
2436 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002437 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002438 return -1;
2439 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002440 }
2441
Owen Anderson92a20222011-07-21 18:54:16 +00002442 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2443 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002444 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002445 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002446 else
2447 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2448 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002449
Jim Grosbach19906722011-07-13 18:49:30 +00002450 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002451}
2452
2453
Bill Wendling50d0f582010-11-18 23:43:05 +00002454/// Try to parse a register name. The token must be an Identifier when called.
2455/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2456/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002457///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002458/// TODO this is likely to change to allow different register types and or to
2459/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002460bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002461tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002462 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002463 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002464 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002465 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002466
Bill Wendling50d0f582010-11-18 23:43:05 +00002467 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002468
Chris Lattnere5658fa2010-10-30 04:09:10 +00002469 const AsmToken &ExclaimTok = Parser.getTok();
2470 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002471 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2472 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002473 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002474 return false;
2475 }
2476
2477 // Also check for an index operand. This is only legal for vector registers,
2478 // but that'll get caught OK in operand matching, so we don't need to
2479 // explicitly filter everything else out here.
2480 if (Parser.getTok().is(AsmToken::LBrac)) {
2481 SMLoc SIdx = Parser.getTok().getLoc();
2482 Parser.Lex(); // Eat left bracket token.
2483
2484 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002485 if (getParser().ParseExpression(ImmVal))
2486 return MatchOperand_ParseFail;
2487 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2488 if (!MCE) {
2489 TokError("immediate value expected for vector index");
2490 return MatchOperand_ParseFail;
2491 }
2492
2493 SMLoc E = Parser.getTok().getLoc();
2494 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2495 Error(E, "']' expected");
2496 return MatchOperand_ParseFail;
2497 }
2498
2499 Parser.Lex(); // Eat right bracket token.
2500
2501 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2502 SIdx, E,
2503 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002504 }
2505
Bill Wendling50d0f582010-11-18 23:43:05 +00002506 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002507}
2508
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002509/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2510/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2511/// "c5", ...
2512static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002513 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2514 // but efficient.
2515 switch (Name.size()) {
2516 default: break;
2517 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002518 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002519 return -1;
2520 switch (Name[1]) {
2521 default: return -1;
2522 case '0': return 0;
2523 case '1': return 1;
2524 case '2': return 2;
2525 case '3': return 3;
2526 case '4': return 4;
2527 case '5': return 5;
2528 case '6': return 6;
2529 case '7': return 7;
2530 case '8': return 8;
2531 case '9': return 9;
2532 }
2533 break;
2534 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002535 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002536 return -1;
2537 switch (Name[2]) {
2538 default: return -1;
2539 case '0': return 10;
2540 case '1': return 11;
2541 case '2': return 12;
2542 case '3': return 13;
2543 case '4': return 14;
2544 case '5': return 15;
2545 }
2546 break;
2547 }
2548
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002549 return -1;
2550}
2551
Jim Grosbach89df9962011-08-26 21:43:41 +00002552/// parseITCondCode - Try to parse a condition code for an IT instruction.
2553ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2554parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2555 SMLoc S = Parser.getTok().getLoc();
2556 const AsmToken &Tok = Parser.getTok();
2557 if (!Tok.is(AsmToken::Identifier))
2558 return MatchOperand_NoMatch;
2559 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2560 .Case("eq", ARMCC::EQ)
2561 .Case("ne", ARMCC::NE)
2562 .Case("hs", ARMCC::HS)
2563 .Case("cs", ARMCC::HS)
2564 .Case("lo", ARMCC::LO)
2565 .Case("cc", ARMCC::LO)
2566 .Case("mi", ARMCC::MI)
2567 .Case("pl", ARMCC::PL)
2568 .Case("vs", ARMCC::VS)
2569 .Case("vc", ARMCC::VC)
2570 .Case("hi", ARMCC::HI)
2571 .Case("ls", ARMCC::LS)
2572 .Case("ge", ARMCC::GE)
2573 .Case("lt", ARMCC::LT)
2574 .Case("gt", ARMCC::GT)
2575 .Case("le", ARMCC::LE)
2576 .Case("al", ARMCC::AL)
2577 .Default(~0U);
2578 if (CC == ~0U)
2579 return MatchOperand_NoMatch;
2580 Parser.Lex(); // Eat the token.
2581
2582 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2583
2584 return MatchOperand_Success;
2585}
2586
Jim Grosbach43904292011-07-25 20:14:50 +00002587/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002588/// token must be an Identifier when called, and if it is a coprocessor
2589/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002590ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002591parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002592 SMLoc S = Parser.getTok().getLoc();
2593 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002594 if (Tok.isNot(AsmToken::Identifier))
2595 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002596
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002597 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002598 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002599 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002600
2601 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002602 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002603 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002604}
2605
Jim Grosbach43904292011-07-25 20:14:50 +00002606/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002607/// token must be an Identifier when called, and if it is a coprocessor
2608/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002609ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002610parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002611 SMLoc S = Parser.getTok().getLoc();
2612 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002613 if (Tok.isNot(AsmToken::Identifier))
2614 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002615
2616 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2617 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002618 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002619
2620 Parser.Lex(); // Eat identifier token.
2621 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002622 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002623}
2624
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002625/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2626/// coproc_option : '{' imm0_255 '}'
2627ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2628parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2629 SMLoc S = Parser.getTok().getLoc();
2630
2631 // If this isn't a '{', this isn't a coprocessor immediate operand.
2632 if (Parser.getTok().isNot(AsmToken::LCurly))
2633 return MatchOperand_NoMatch;
2634 Parser.Lex(); // Eat the '{'
2635
2636 const MCExpr *Expr;
2637 SMLoc Loc = Parser.getTok().getLoc();
2638 if (getParser().ParseExpression(Expr)) {
2639 Error(Loc, "illegal expression");
2640 return MatchOperand_ParseFail;
2641 }
2642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2643 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2644 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2645 return MatchOperand_ParseFail;
2646 }
2647 int Val = CE->getValue();
2648
2649 // Check for and consume the closing '}'
2650 if (Parser.getTok().isNot(AsmToken::RCurly))
2651 return MatchOperand_ParseFail;
2652 SMLoc E = Parser.getTok().getLoc();
2653 Parser.Lex(); // Eat the '}'
2654
2655 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2656 return MatchOperand_Success;
2657}
2658
Jim Grosbachd0588e22011-09-14 18:08:35 +00002659// For register list parsing, we need to map from raw GPR register numbering
2660// to the enumeration values. The enumeration values aren't sorted by
2661// register number due to our using "sp", "lr" and "pc" as canonical names.
2662static unsigned getNextRegister(unsigned Reg) {
2663 // If this is a GPR, we need to do it manually, otherwise we can rely
2664 // on the sort ordering of the enumeration since the other reg-classes
2665 // are sane.
2666 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2667 return Reg + 1;
2668 switch(Reg) {
2669 default: assert(0 && "Invalid GPR number!");
2670 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2671 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2672 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2673 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2674 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2675 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2676 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2677 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2678 }
2679}
2680
Jim Grosbachce485e72011-11-11 21:27:40 +00002681// Return the low-subreg of a given Q register.
2682static unsigned getDRegFromQReg(unsigned QReg) {
2683 switch (QReg) {
2684 default: llvm_unreachable("expected a Q register!");
2685 case ARM::Q0: return ARM::D0;
2686 case ARM::Q1: return ARM::D2;
2687 case ARM::Q2: return ARM::D4;
2688 case ARM::Q3: return ARM::D6;
2689 case ARM::Q4: return ARM::D8;
2690 case ARM::Q5: return ARM::D10;
2691 case ARM::Q6: return ARM::D12;
2692 case ARM::Q7: return ARM::D14;
2693 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002694 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002695 case ARM::Q10: return ARM::D20;
2696 case ARM::Q11: return ARM::D22;
2697 case ARM::Q12: return ARM::D24;
2698 case ARM::Q13: return ARM::D26;
2699 case ARM::Q14: return ARM::D28;
2700 case ARM::Q15: return ARM::D30;
2701 }
2702}
2703
Jim Grosbachd0588e22011-09-14 18:08:35 +00002704/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002705bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002706parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002707 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002708 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002709 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002710 Parser.Lex(); // Eat '{' token.
2711 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002712
Jim Grosbachd0588e22011-09-14 18:08:35 +00002713 // Check the first register in the list to see what register class
2714 // this is a list of.
2715 int Reg = tryParseRegister();
2716 if (Reg == -1)
2717 return Error(RegLoc, "register expected");
2718
Jim Grosbachce485e72011-11-11 21:27:40 +00002719 // The reglist instructions have at most 16 registers, so reserve
2720 // space for that many.
2721 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2722
2723 // Allow Q regs and just interpret them as the two D sub-registers.
2724 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2725 Reg = getDRegFromQReg(Reg);
2726 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2727 ++Reg;
2728 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002729 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002730 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2731 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2732 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2733 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2734 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2735 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2736 else
2737 return Error(RegLoc, "invalid register in register list");
2738
Jim Grosbachce485e72011-11-11 21:27:40 +00002739 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002740 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002741
Jim Grosbachd0588e22011-09-14 18:08:35 +00002742 // This starts immediately after the first register token in the list,
2743 // so we can see either a comma or a minus (range separator) as a legal
2744 // next token.
2745 while (Parser.getTok().is(AsmToken::Comma) ||
2746 Parser.getTok().is(AsmToken::Minus)) {
2747 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002748 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002749 SMLoc EndLoc = Parser.getTok().getLoc();
2750 int EndReg = tryParseRegister();
2751 if (EndReg == -1)
2752 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002753 // Allow Q regs and just interpret them as the two D sub-registers.
2754 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2755 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002756 // If the register is the same as the start reg, there's nothing
2757 // more to do.
2758 if (Reg == EndReg)
2759 continue;
2760 // The register must be in the same register class as the first.
2761 if (!RC->contains(EndReg))
2762 return Error(EndLoc, "invalid register in register list");
2763 // Ranges must go from low to high.
2764 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2765 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002766
Jim Grosbachd0588e22011-09-14 18:08:35 +00002767 // Add all the registers in the range to the register list.
2768 while (Reg != EndReg) {
2769 Reg = getNextRegister(Reg);
2770 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2771 }
2772 continue;
2773 }
2774 Parser.Lex(); // Eat the comma.
2775 RegLoc = Parser.getTok().getLoc();
2776 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002777 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002778 Reg = tryParseRegister();
2779 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002780 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002781 // Allow Q regs and just interpret them as the two D sub-registers.
2782 bool isQReg = false;
2783 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2784 Reg = getDRegFromQReg(Reg);
2785 isQReg = true;
2786 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002787 // The register must be in the same register class as the first.
2788 if (!RC->contains(Reg))
2789 return Error(RegLoc, "invalid register in register list");
2790 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002791 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002792 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002793 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2794 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2795 ") in register list");
2796 continue;
2797 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002798 // VFP register lists must also be contiguous.
2799 // It's OK to use the enumeration values directly here rather, as the
2800 // VFP register classes have the enum sorted properly.
2801 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2802 Reg != OldReg + 1)
2803 return Error(RegLoc, "non-contiguous register range");
2804 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002805 if (isQReg)
2806 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002807 }
2808
Jim Grosbachd0588e22011-09-14 18:08:35 +00002809 SMLoc E = Parser.getTok().getLoc();
2810 if (Parser.getTok().isNot(AsmToken::RCurly))
2811 return Error(E, "'}' expected");
2812 Parser.Lex(); // Eat '}' token.
2813
Jim Grosbach27debd62011-12-13 21:48:29 +00002814 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002815 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002816
2817 // The ARM system instruction variants for LDM/STM have a '^' token here.
2818 if (Parser.getTok().is(AsmToken::Caret)) {
2819 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2820 Parser.Lex(); // Eat '^' token.
2821 }
2822
Bill Wendling50d0f582010-11-18 23:43:05 +00002823 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002824}
2825
Jim Grosbach98b05a52011-11-30 01:09:44 +00002826// Helper function to parse the lane index for vector lists.
2827ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002828parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2829 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002830 if (Parser.getTok().is(AsmToken::LBrac)) {
2831 Parser.Lex(); // Eat the '['.
2832 if (Parser.getTok().is(AsmToken::RBrac)) {
2833 // "Dn[]" is the 'all lanes' syntax.
2834 LaneKind = AllLanes;
2835 Parser.Lex(); // Eat the ']'.
2836 return MatchOperand_Success;
2837 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002838 const MCExpr *LaneIndex;
2839 SMLoc Loc = Parser.getTok().getLoc();
2840 if (getParser().ParseExpression(LaneIndex)) {
2841 Error(Loc, "illegal expression");
2842 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002843 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002844 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2845 if (!CE) {
2846 Error(Loc, "lane index must be empty or an integer");
2847 return MatchOperand_ParseFail;
2848 }
2849 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2850 Error(Parser.getTok().getLoc(), "']' expected");
2851 return MatchOperand_ParseFail;
2852 }
2853 Parser.Lex(); // Eat the ']'.
2854 int64_t Val = CE->getValue();
2855
2856 // FIXME: Make this range check context sensitive for .8, .16, .32.
2857 if (Val < 0 || Val > 7) {
2858 Error(Parser.getTok().getLoc(), "lane index out of range");
2859 return MatchOperand_ParseFail;
2860 }
2861 Index = Val;
2862 LaneKind = IndexedLane;
2863 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002864 }
2865 LaneKind = NoLanes;
2866 return MatchOperand_Success;
2867}
2868
Jim Grosbach862019c2011-10-18 23:02:30 +00002869// parse a vector register list
2870ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2871parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002872 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002873 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002874 SMLoc S = Parser.getTok().getLoc();
2875 // As an extension (to match gas), support a plain D register or Q register
2876 // (without encosing curly braces) as a single or double entry list,
2877 // respectively.
2878 if (Parser.getTok().is(AsmToken::Identifier)) {
2879 int Reg = tryParseRegister();
2880 if (Reg == -1)
2881 return MatchOperand_NoMatch;
2882 SMLoc E = Parser.getTok().getLoc();
2883 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002884 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002885 if (Res != MatchOperand_Success)
2886 return Res;
2887 switch (LaneKind) {
2888 default:
2889 assert(0 && "unexpected lane kind!");
2890 case NoLanes:
2891 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002892 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002893 break;
2894 case AllLanes:
2895 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002896 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2897 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002898 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002899 case IndexedLane:
2900 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002901 LaneIndex,
2902 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002903 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002904 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002905 return MatchOperand_Success;
2906 }
2907 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2908 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002909 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002910 if (Res != MatchOperand_Success)
2911 return Res;
2912 switch (LaneKind) {
2913 default:
2914 assert(0 && "unexpected lane kind!");
2915 case NoLanes:
2916 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002917 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002918 break;
2919 case AllLanes:
2920 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002921 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2922 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002923 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002924 case IndexedLane:
2925 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002926 LaneIndex,
2927 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002928 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002929 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002930 return MatchOperand_Success;
2931 }
2932 Error(S, "vector register expected");
2933 return MatchOperand_ParseFail;
2934 }
2935
2936 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002937 return MatchOperand_NoMatch;
2938
Jim Grosbach862019c2011-10-18 23:02:30 +00002939 Parser.Lex(); // Eat '{' token.
2940 SMLoc RegLoc = Parser.getTok().getLoc();
2941
2942 int Reg = tryParseRegister();
2943 if (Reg == -1) {
2944 Error(RegLoc, "register expected");
2945 return MatchOperand_ParseFail;
2946 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002947 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002948 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002949 unsigned FirstReg = Reg;
2950 // The list is of D registers, but we also allow Q regs and just interpret
2951 // them as the two D sub-registers.
2952 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2953 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002954 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2955 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002956 ++Reg;
2957 ++Count;
2958 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002959 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002960 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002961
Jim Grosbache43862b2011-11-15 23:19:15 +00002962 while (Parser.getTok().is(AsmToken::Comma) ||
2963 Parser.getTok().is(AsmToken::Minus)) {
2964 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002965 if (!Spacing)
2966 Spacing = 1; // Register range implies a single spaced list.
2967 else if (Spacing == 2) {
2968 Error(Parser.getTok().getLoc(),
2969 "sequential registers in double spaced list");
2970 return MatchOperand_ParseFail;
2971 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002972 Parser.Lex(); // Eat the minus.
2973 SMLoc EndLoc = Parser.getTok().getLoc();
2974 int EndReg = tryParseRegister();
2975 if (EndReg == -1) {
2976 Error(EndLoc, "register expected");
2977 return MatchOperand_ParseFail;
2978 }
2979 // Allow Q regs and just interpret them as the two D sub-registers.
2980 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2981 EndReg = getDRegFromQReg(EndReg) + 1;
2982 // If the register is the same as the start reg, there's nothing
2983 // more to do.
2984 if (Reg == EndReg)
2985 continue;
2986 // The register must be in the same register class as the first.
2987 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2988 Error(EndLoc, "invalid register in register list");
2989 return MatchOperand_ParseFail;
2990 }
2991 // Ranges must go from low to high.
2992 if (Reg > EndReg) {
2993 Error(EndLoc, "bad range in register list");
2994 return MatchOperand_ParseFail;
2995 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002996 // Parse the lane specifier if present.
2997 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002998 unsigned NextLaneIndex;
2999 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003000 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003001 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003002 Error(EndLoc, "mismatched lane index in register list");
3003 return MatchOperand_ParseFail;
3004 }
3005 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003006
3007 // Add all the registers in the range to the register list.
3008 Count += EndReg - Reg;
3009 Reg = EndReg;
3010 continue;
3011 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003012 Parser.Lex(); // Eat the comma.
3013 RegLoc = Parser.getTok().getLoc();
3014 int OldReg = Reg;
3015 Reg = tryParseRegister();
3016 if (Reg == -1) {
3017 Error(RegLoc, "register expected");
3018 return MatchOperand_ParseFail;
3019 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003020 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003021 // It's OK to use the enumeration values directly here rather, as the
3022 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003023 //
3024 // The list is of D registers, but we also allow Q regs and just interpret
3025 // them as the two D sub-registers.
3026 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003027 if (!Spacing)
3028 Spacing = 1; // Register range implies a single spaced list.
3029 else if (Spacing == 2) {
3030 Error(RegLoc,
3031 "invalid register in double-spaced list (must be 'D' register')");
3032 return MatchOperand_ParseFail;
3033 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003034 Reg = getDRegFromQReg(Reg);
3035 if (Reg != OldReg + 1) {
3036 Error(RegLoc, "non-contiguous register range");
3037 return MatchOperand_ParseFail;
3038 }
3039 ++Reg;
3040 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003041 // Parse the lane specifier if present.
3042 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003043 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003044 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003045 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003046 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003047 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003048 Error(EndLoc, "mismatched lane index in register list");
3049 return MatchOperand_ParseFail;
3050 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003051 continue;
3052 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003053 // Normal D register.
3054 // Figure out the register spacing (single or double) of the list if
3055 // we don't know it already.
3056 if (!Spacing)
3057 Spacing = 1 + (Reg == OldReg + 2);
3058
3059 // Just check that it's contiguous and keep going.
3060 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003061 Error(RegLoc, "non-contiguous register range");
3062 return MatchOperand_ParseFail;
3063 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003064 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003065 // Parse the lane specifier if present.
3066 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003067 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003068 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003069 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003070 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003071 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003072 Error(EndLoc, "mismatched lane index in register list");
3073 return MatchOperand_ParseFail;
3074 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003075 }
3076
3077 SMLoc E = Parser.getTok().getLoc();
3078 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3079 Error(E, "'}' expected");
3080 return MatchOperand_ParseFail;
3081 }
3082 Parser.Lex(); // Eat '}' token.
3083
Jim Grosbach98b05a52011-11-30 01:09:44 +00003084 switch (LaneKind) {
3085 default:
3086 assert(0 && "unexpected lane kind in register list.");
3087 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003088 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3089 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003090 break;
3091 case AllLanes:
3092 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003093 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003094 S, E));
3095 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003096 case IndexedLane:
3097 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003098 LaneIndex,
3099 (Spacing == 2),
3100 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003101 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003102 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003103 return MatchOperand_Success;
3104}
3105
Jim Grosbach43904292011-07-25 20:14:50 +00003106/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003107ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003108parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003109 SMLoc S = Parser.getTok().getLoc();
3110 const AsmToken &Tok = Parser.getTok();
3111 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3112 StringRef OptStr = Tok.getString();
3113
3114 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3115 .Case("sy", ARM_MB::SY)
3116 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003117 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003118 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003119 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003120 .Case("ishst", ARM_MB::ISHST)
3121 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003122 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003123 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003124 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003125 .Case("osh", ARM_MB::OSH)
3126 .Case("oshst", ARM_MB::OSHST)
3127 .Default(~0U);
3128
3129 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003130 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003131
3132 Parser.Lex(); // Eat identifier token.
3133 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003134 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003135}
3136
Jim Grosbach43904292011-07-25 20:14:50 +00003137/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003138ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003139parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003140 SMLoc S = Parser.getTok().getLoc();
3141 const AsmToken &Tok = Parser.getTok();
3142 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3143 StringRef IFlagsStr = Tok.getString();
3144
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003145 // An iflags string of "none" is interpreted to mean that none of the AIF
3146 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003147 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003148 if (IFlagsStr != "none") {
3149 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3150 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3151 .Case("a", ARM_PROC::A)
3152 .Case("i", ARM_PROC::I)
3153 .Case("f", ARM_PROC::F)
3154 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003155
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003156 // If some specific iflag is already set, it means that some letter is
3157 // present more than once, this is not acceptable.
3158 if (Flag == ~0U || (IFlags & Flag))
3159 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003160
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003161 IFlags |= Flag;
3162 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003163 }
3164
3165 Parser.Lex(); // Eat identifier token.
3166 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3167 return MatchOperand_Success;
3168}
3169
Jim Grosbach43904292011-07-25 20:14:50 +00003170/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003171ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003172parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003173 SMLoc S = Parser.getTok().getLoc();
3174 const AsmToken &Tok = Parser.getTok();
3175 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3176 StringRef Mask = Tok.getString();
3177
James Molloyacad68d2011-09-28 14:21:38 +00003178 if (isMClass()) {
3179 // See ARMv6-M 10.1.1
3180 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3181 .Case("apsr", 0)
3182 .Case("iapsr", 1)
3183 .Case("eapsr", 2)
3184 .Case("xpsr", 3)
3185 .Case("ipsr", 5)
3186 .Case("epsr", 6)
3187 .Case("iepsr", 7)
3188 .Case("msp", 8)
3189 .Case("psp", 9)
3190 .Case("primask", 16)
3191 .Case("basepri", 17)
3192 .Case("basepri_max", 18)
3193 .Case("faultmask", 19)
3194 .Case("control", 20)
3195 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003196
James Molloyacad68d2011-09-28 14:21:38 +00003197 if (FlagsVal == ~0U)
3198 return MatchOperand_NoMatch;
3199
3200 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3201 // basepri, basepri_max and faultmask only valid for V7m.
3202 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003203
James Molloyacad68d2011-09-28 14:21:38 +00003204 Parser.Lex(); // Eat identifier token.
3205 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3206 return MatchOperand_Success;
3207 }
3208
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003209 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3210 size_t Start = 0, Next = Mask.find('_');
3211 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003212 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003213 if (Next != StringRef::npos)
3214 Flags = Mask.slice(Next+1, Mask.size());
3215
3216 // FlagsVal contains the complete mask:
3217 // 3-0: Mask
3218 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3219 unsigned FlagsVal = 0;
3220
3221 if (SpecReg == "apsr") {
3222 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003223 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003224 .Case("g", 0x4) // same as CPSR_s
3225 .Case("nzcvqg", 0xc) // same as CPSR_fs
3226 .Default(~0U);
3227
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003228 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003229 if (!Flags.empty())
3230 return MatchOperand_NoMatch;
3231 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003232 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003233 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003234 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003235 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3236 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003237 for (int i = 0, e = Flags.size(); i != e; ++i) {
3238 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3239 .Case("c", 1)
3240 .Case("x", 2)
3241 .Case("s", 4)
3242 .Case("f", 8)
3243 .Default(~0U);
3244
3245 // If some specific flag is already set, it means that some letter is
3246 // present more than once, this is not acceptable.
3247 if (FlagsVal == ~0U || (FlagsVal & Flag))
3248 return MatchOperand_NoMatch;
3249 FlagsVal |= Flag;
3250 }
3251 } else // No match for special register.
3252 return MatchOperand_NoMatch;
3253
Owen Anderson7784f1d2011-10-21 18:43:28 +00003254 // Special register without flags is NOT equivalent to "fc" flags.
3255 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3256 // two lines would enable gas compatibility at the expense of breaking
3257 // round-tripping.
3258 //
3259 // if (!FlagsVal)
3260 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003261
3262 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3263 if (SpecReg == "spsr")
3264 FlagsVal |= 16;
3265
3266 Parser.Lex(); // Eat identifier token.
3267 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3268 return MatchOperand_Success;
3269}
3270
Jim Grosbachf6c05252011-07-21 17:23:04 +00003271ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3272parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3273 int Low, int High) {
3274 const AsmToken &Tok = Parser.getTok();
3275 if (Tok.isNot(AsmToken::Identifier)) {
3276 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3277 return MatchOperand_ParseFail;
3278 }
3279 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003280 std::string LowerOp = Op.lower();
3281 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003282 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3283 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3284 return MatchOperand_ParseFail;
3285 }
3286 Parser.Lex(); // Eat shift type token.
3287
3288 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003289 if (Parser.getTok().isNot(AsmToken::Hash) &&
3290 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003291 Error(Parser.getTok().getLoc(), "'#' expected");
3292 return MatchOperand_ParseFail;
3293 }
3294 Parser.Lex(); // Eat hash token.
3295
3296 const MCExpr *ShiftAmount;
3297 SMLoc Loc = Parser.getTok().getLoc();
3298 if (getParser().ParseExpression(ShiftAmount)) {
3299 Error(Loc, "illegal expression");
3300 return MatchOperand_ParseFail;
3301 }
3302 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3303 if (!CE) {
3304 Error(Loc, "constant expression expected");
3305 return MatchOperand_ParseFail;
3306 }
3307 int Val = CE->getValue();
3308 if (Val < Low || Val > High) {
3309 Error(Loc, "immediate value out of range");
3310 return MatchOperand_ParseFail;
3311 }
3312
3313 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3314
3315 return MatchOperand_Success;
3316}
3317
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003318ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3319parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3320 const AsmToken &Tok = Parser.getTok();
3321 SMLoc S = Tok.getLoc();
3322 if (Tok.isNot(AsmToken::Identifier)) {
3323 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3324 return MatchOperand_ParseFail;
3325 }
3326 int Val = StringSwitch<int>(Tok.getString())
3327 .Case("be", 1)
3328 .Case("le", 0)
3329 .Default(-1);
3330 Parser.Lex(); // Eat the token.
3331
3332 if (Val == -1) {
3333 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3334 return MatchOperand_ParseFail;
3335 }
3336 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3337 getContext()),
3338 S, Parser.getTok().getLoc()));
3339 return MatchOperand_Success;
3340}
3341
Jim Grosbach580f4a92011-07-25 22:20:28 +00003342/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3343/// instructions. Legal values are:
3344/// lsl #n 'n' in [0,31]
3345/// asr #n 'n' in [1,32]
3346/// n == 32 encoded as n == 0.
3347ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3348parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3349 const AsmToken &Tok = Parser.getTok();
3350 SMLoc S = Tok.getLoc();
3351 if (Tok.isNot(AsmToken::Identifier)) {
3352 Error(S, "shift operator 'asr' or 'lsl' expected");
3353 return MatchOperand_ParseFail;
3354 }
3355 StringRef ShiftName = Tok.getString();
3356 bool isASR;
3357 if (ShiftName == "lsl" || ShiftName == "LSL")
3358 isASR = false;
3359 else if (ShiftName == "asr" || ShiftName == "ASR")
3360 isASR = true;
3361 else {
3362 Error(S, "shift operator 'asr' or 'lsl' expected");
3363 return MatchOperand_ParseFail;
3364 }
3365 Parser.Lex(); // Eat the operator.
3366
3367 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003368 if (Parser.getTok().isNot(AsmToken::Hash) &&
3369 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003370 Error(Parser.getTok().getLoc(), "'#' expected");
3371 return MatchOperand_ParseFail;
3372 }
3373 Parser.Lex(); // Eat hash token.
3374
3375 const MCExpr *ShiftAmount;
3376 SMLoc E = Parser.getTok().getLoc();
3377 if (getParser().ParseExpression(ShiftAmount)) {
3378 Error(E, "malformed shift expression");
3379 return MatchOperand_ParseFail;
3380 }
3381 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3382 if (!CE) {
3383 Error(E, "shift amount must be an immediate");
3384 return MatchOperand_ParseFail;
3385 }
3386
3387 int64_t Val = CE->getValue();
3388 if (isASR) {
3389 // Shift amount must be in [1,32]
3390 if (Val < 1 || Val > 32) {
3391 Error(E, "'asr' shift amount must be in range [1,32]");
3392 return MatchOperand_ParseFail;
3393 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003394 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3395 if (isThumb() && Val == 32) {
3396 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3397 return MatchOperand_ParseFail;
3398 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003399 if (Val == 32) Val = 0;
3400 } else {
3401 // Shift amount must be in [1,32]
3402 if (Val < 0 || Val > 31) {
3403 Error(E, "'lsr' shift amount must be in range [0,31]");
3404 return MatchOperand_ParseFail;
3405 }
3406 }
3407
3408 E = Parser.getTok().getLoc();
3409 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3410
3411 return MatchOperand_Success;
3412}
3413
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003414/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3415/// of instructions. Legal values are:
3416/// ror #n 'n' in {0, 8, 16, 24}
3417ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3418parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3419 const AsmToken &Tok = Parser.getTok();
3420 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003421 if (Tok.isNot(AsmToken::Identifier))
3422 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003423 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003424 if (ShiftName != "ror" && ShiftName != "ROR")
3425 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003426 Parser.Lex(); // Eat the operator.
3427
3428 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003429 if (Parser.getTok().isNot(AsmToken::Hash) &&
3430 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003431 Error(Parser.getTok().getLoc(), "'#' expected");
3432 return MatchOperand_ParseFail;
3433 }
3434 Parser.Lex(); // Eat hash token.
3435
3436 const MCExpr *ShiftAmount;
3437 SMLoc E = Parser.getTok().getLoc();
3438 if (getParser().ParseExpression(ShiftAmount)) {
3439 Error(E, "malformed rotate expression");
3440 return MatchOperand_ParseFail;
3441 }
3442 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3443 if (!CE) {
3444 Error(E, "rotate amount must be an immediate");
3445 return MatchOperand_ParseFail;
3446 }
3447
3448 int64_t Val = CE->getValue();
3449 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3450 // normally, zero is represented in asm by omitting the rotate operand
3451 // entirely.
3452 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3453 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3454 return MatchOperand_ParseFail;
3455 }
3456
3457 E = Parser.getTok().getLoc();
3458 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3459
3460 return MatchOperand_Success;
3461}
3462
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003463ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3464parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3465 SMLoc S = Parser.getTok().getLoc();
3466 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003467 if (Parser.getTok().isNot(AsmToken::Hash) &&
3468 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003469 Error(Parser.getTok().getLoc(), "'#' expected");
3470 return MatchOperand_ParseFail;
3471 }
3472 Parser.Lex(); // Eat hash token.
3473
3474 const MCExpr *LSBExpr;
3475 SMLoc E = Parser.getTok().getLoc();
3476 if (getParser().ParseExpression(LSBExpr)) {
3477 Error(E, "malformed immediate expression");
3478 return MatchOperand_ParseFail;
3479 }
3480 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3481 if (!CE) {
3482 Error(E, "'lsb' operand must be an immediate");
3483 return MatchOperand_ParseFail;
3484 }
3485
3486 int64_t LSB = CE->getValue();
3487 // The LSB must be in the range [0,31]
3488 if (LSB < 0 || LSB > 31) {
3489 Error(E, "'lsb' operand must be in the range [0,31]");
3490 return MatchOperand_ParseFail;
3491 }
3492 E = Parser.getTok().getLoc();
3493
3494 // Expect another immediate operand.
3495 if (Parser.getTok().isNot(AsmToken::Comma)) {
3496 Error(Parser.getTok().getLoc(), "too few operands");
3497 return MatchOperand_ParseFail;
3498 }
3499 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003500 if (Parser.getTok().isNot(AsmToken::Hash) &&
3501 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003502 Error(Parser.getTok().getLoc(), "'#' expected");
3503 return MatchOperand_ParseFail;
3504 }
3505 Parser.Lex(); // Eat hash token.
3506
3507 const MCExpr *WidthExpr;
3508 if (getParser().ParseExpression(WidthExpr)) {
3509 Error(E, "malformed immediate expression");
3510 return MatchOperand_ParseFail;
3511 }
3512 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3513 if (!CE) {
3514 Error(E, "'width' operand must be an immediate");
3515 return MatchOperand_ParseFail;
3516 }
3517
3518 int64_t Width = CE->getValue();
3519 // The LSB must be in the range [1,32-lsb]
3520 if (Width < 1 || Width > 32 - LSB) {
3521 Error(E, "'width' operand must be in the range [1,32-lsb]");
3522 return MatchOperand_ParseFail;
3523 }
3524 E = Parser.getTok().getLoc();
3525
3526 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3527
3528 return MatchOperand_Success;
3529}
3530
Jim Grosbach7ce05792011-08-03 23:50:40 +00003531ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3532parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3533 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003534 // postidx_reg := '+' register {, shift}
3535 // | '-' register {, shift}
3536 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003537
3538 // This method must return MatchOperand_NoMatch without consuming any tokens
3539 // in the case where there is no match, as other alternatives take other
3540 // parse methods.
3541 AsmToken Tok = Parser.getTok();
3542 SMLoc S = Tok.getLoc();
3543 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003544 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003545 int Reg = -1;
3546 if (Tok.is(AsmToken::Plus)) {
3547 Parser.Lex(); // Eat the '+' token.
3548 haveEaten = true;
3549 } else if (Tok.is(AsmToken::Minus)) {
3550 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003551 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003552 haveEaten = true;
3553 }
3554 if (Parser.getTok().is(AsmToken::Identifier))
3555 Reg = tryParseRegister();
3556 if (Reg == -1) {
3557 if (!haveEaten)
3558 return MatchOperand_NoMatch;
3559 Error(Parser.getTok().getLoc(), "register expected");
3560 return MatchOperand_ParseFail;
3561 }
3562 SMLoc E = Parser.getTok().getLoc();
3563
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003564 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3565 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003566 if (Parser.getTok().is(AsmToken::Comma)) {
3567 Parser.Lex(); // Eat the ','.
3568 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3569 return MatchOperand_ParseFail;
3570 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003571
3572 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3573 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003574
3575 return MatchOperand_Success;
3576}
3577
Jim Grosbach251bf252011-08-10 21:56:18 +00003578ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3579parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3580 // Check for a post-index addressing register operand. Specifically:
3581 // am3offset := '+' register
3582 // | '-' register
3583 // | register
3584 // | # imm
3585 // | # + imm
3586 // | # - imm
3587
3588 // This method must return MatchOperand_NoMatch without consuming any tokens
3589 // in the case where there is no match, as other alternatives take other
3590 // parse methods.
3591 AsmToken Tok = Parser.getTok();
3592 SMLoc S = Tok.getLoc();
3593
3594 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003595 if (Parser.getTok().is(AsmToken::Hash) ||
3596 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003597 Parser.Lex(); // Eat the '#'.
3598 // Explicitly look for a '-', as we need to encode negative zero
3599 // differently.
3600 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3601 const MCExpr *Offset;
3602 if (getParser().ParseExpression(Offset))
3603 return MatchOperand_ParseFail;
3604 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3605 if (!CE) {
3606 Error(S, "constant expression expected");
3607 return MatchOperand_ParseFail;
3608 }
3609 SMLoc E = Tok.getLoc();
3610 // Negative zero is encoded as the flag value INT32_MIN.
3611 int32_t Val = CE->getValue();
3612 if (isNegative && Val == 0)
3613 Val = INT32_MIN;
3614
3615 Operands.push_back(
3616 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3617
3618 return MatchOperand_Success;
3619 }
3620
3621
3622 bool haveEaten = false;
3623 bool isAdd = true;
3624 int Reg = -1;
3625 if (Tok.is(AsmToken::Plus)) {
3626 Parser.Lex(); // Eat the '+' token.
3627 haveEaten = true;
3628 } else if (Tok.is(AsmToken::Minus)) {
3629 Parser.Lex(); // Eat the '-' token.
3630 isAdd = false;
3631 haveEaten = true;
3632 }
3633 if (Parser.getTok().is(AsmToken::Identifier))
3634 Reg = tryParseRegister();
3635 if (Reg == -1) {
3636 if (!haveEaten)
3637 return MatchOperand_NoMatch;
3638 Error(Parser.getTok().getLoc(), "register expected");
3639 return MatchOperand_ParseFail;
3640 }
3641 SMLoc E = Parser.getTok().getLoc();
3642
3643 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3644 0, S, E));
3645
3646 return MatchOperand_Success;
3647}
3648
Jim Grosbacha77295d2011-09-08 22:07:06 +00003649/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3650/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3651/// when they refer multiple MIOperands inside a single one.
3652bool ARMAsmParser::
3653cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3654 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3655 // Rt, Rt2
3656 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3657 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3658 // Create a writeback register dummy placeholder.
3659 Inst.addOperand(MCOperand::CreateReg(0));
3660 // addr
3661 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3662 // pred
3663 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3664 return true;
3665}
3666
3667/// cvtT2StrdPre - Convert parsed operands to MCInst.
3668/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3669/// when they refer multiple MIOperands inside a single one.
3670bool ARMAsmParser::
3671cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3672 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3673 // Create a writeback register dummy placeholder.
3674 Inst.addOperand(MCOperand::CreateReg(0));
3675 // Rt, Rt2
3676 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3677 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3678 // addr
3679 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3680 // pred
3681 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3682 return true;
3683}
3684
Jim Grosbacheeec0252011-09-08 00:39:19 +00003685/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3686/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3687/// when they refer multiple MIOperands inside a single one.
3688bool ARMAsmParser::
3689cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3690 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3691 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3692
3693 // Create a writeback register dummy placeholder.
3694 Inst.addOperand(MCOperand::CreateImm(0));
3695
3696 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3697 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3698 return true;
3699}
3700
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003701/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3702/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3703/// when they refer multiple MIOperands inside a single one.
3704bool ARMAsmParser::
3705cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3706 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3707 // Create a writeback register dummy placeholder.
3708 Inst.addOperand(MCOperand::CreateImm(0));
3709 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3710 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3711 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3712 return true;
3713}
3714
Jim Grosbach1355cf12011-07-26 17:10:22 +00003715/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003716/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3717/// when they refer multiple MIOperands inside a single one.
3718bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003719cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003720 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3721 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3722
3723 // Create a writeback register dummy placeholder.
3724 Inst.addOperand(MCOperand::CreateImm(0));
3725
Jim Grosbach7ce05792011-08-03 23:50:40 +00003726 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003727 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3728 return true;
3729}
3730
Owen Anderson9ab0f252011-08-26 20:43:14 +00003731/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3732/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3733/// when they refer multiple MIOperands inside a single one.
3734bool ARMAsmParser::
3735cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3736 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3737 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3738
3739 // Create a writeback register dummy placeholder.
3740 Inst.addOperand(MCOperand::CreateImm(0));
3741
3742 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3743 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3744 return true;
3745}
3746
3747
Jim Grosbach548340c2011-08-11 19:22:40 +00003748/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3749/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3750/// when they refer multiple MIOperands inside a single one.
3751bool ARMAsmParser::
3752cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3753 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3754 // Create a writeback register dummy placeholder.
3755 Inst.addOperand(MCOperand::CreateImm(0));
3756 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3757 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3758 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3759 return true;
3760}
3761
Jim Grosbach1355cf12011-07-26 17:10:22 +00003762/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003763/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3764/// when they refer multiple MIOperands inside a single one.
3765bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003766cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003767 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3768 // Create a writeback register dummy placeholder.
3769 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003770 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3771 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3772 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003773 return true;
3774}
3775
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003776/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3777/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3778/// when they refer multiple MIOperands inside a single one.
3779bool ARMAsmParser::
3780cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3781 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3782 // Create a writeback register dummy placeholder.
3783 Inst.addOperand(MCOperand::CreateImm(0));
3784 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3785 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3786 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3787 return true;
3788}
3789
Jim Grosbach7ce05792011-08-03 23:50:40 +00003790/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3791/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3792/// when they refer multiple MIOperands inside a single one.
3793bool ARMAsmParser::
3794cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3795 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3796 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003797 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003798 // Create a writeback register dummy placeholder.
3799 Inst.addOperand(MCOperand::CreateImm(0));
3800 // addr
3801 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3802 // offset
3803 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3804 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003805 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3806 return true;
3807}
3808
Jim Grosbach7ce05792011-08-03 23:50:40 +00003809/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003810/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3811/// when they refer multiple MIOperands inside a single one.
3812bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003813cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3814 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3815 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003816 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003817 // Create a writeback register dummy placeholder.
3818 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003819 // addr
3820 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3821 // offset
3822 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3823 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3825 return true;
3826}
3827
Jim Grosbach7ce05792011-08-03 23:50:40 +00003828/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3830/// when they refer multiple MIOperands inside a single one.
3831bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003832cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003834 // Create a writeback register dummy placeholder.
3835 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003836 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003837 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003838 // addr
3839 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3840 // offset
3841 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3842 // pred
3843 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3844 return true;
3845}
3846
3847/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3848/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3849/// when they refer multiple MIOperands inside a single one.
3850bool ARMAsmParser::
3851cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3852 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3853 // Create a writeback register dummy placeholder.
3854 Inst.addOperand(MCOperand::CreateImm(0));
3855 // Rt
3856 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3857 // addr
3858 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3859 // offset
3860 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3861 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003862 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3863 return true;
3864}
3865
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003866/// cvtLdrdPre - Convert parsed operands to MCInst.
3867/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3868/// when they refer multiple MIOperands inside a single one.
3869bool ARMAsmParser::
3870cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3871 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3872 // Rt, Rt2
3873 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3874 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3875 // Create a writeback register dummy placeholder.
3876 Inst.addOperand(MCOperand::CreateImm(0));
3877 // addr
3878 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3879 // pred
3880 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3881 return true;
3882}
3883
Jim Grosbach14605d12011-08-11 20:28:23 +00003884/// cvtStrdPre - Convert parsed operands to MCInst.
3885/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3886/// when they refer multiple MIOperands inside a single one.
3887bool ARMAsmParser::
3888cvtStrdPre(MCInst &Inst, unsigned Opcode,
3889 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3890 // Create a writeback register dummy placeholder.
3891 Inst.addOperand(MCOperand::CreateImm(0));
3892 // Rt, Rt2
3893 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3894 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3895 // addr
3896 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3897 // pred
3898 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3899 return true;
3900}
3901
Jim Grosbach623a4542011-08-10 22:42:16 +00003902/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3903/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3904/// when they refer multiple MIOperands inside a single one.
3905bool ARMAsmParser::
3906cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3907 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3908 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3909 // Create a writeback register dummy placeholder.
3910 Inst.addOperand(MCOperand::CreateImm(0));
3911 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3912 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3913 return true;
3914}
3915
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003916/// cvtThumbMultiple- Convert parsed operands to MCInst.
3917/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3918/// when they refer multiple MIOperands inside a single one.
3919bool ARMAsmParser::
3920cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3921 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3922 // The second source operand must be the same register as the destination
3923 // operand.
3924 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003925 (((ARMOperand*)Operands[3])->getReg() !=
3926 ((ARMOperand*)Operands[5])->getReg()) &&
3927 (((ARMOperand*)Operands[3])->getReg() !=
3928 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003929 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003930 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003931 return false;
3932 }
3933 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3934 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003935 // If we have a three-operand form, make sure to set Rn to be the operand
3936 // that isn't the same as Rd.
3937 unsigned RegOp = 4;
3938 if (Operands.size() == 6 &&
3939 ((ARMOperand*)Operands[4])->getReg() ==
3940 ((ARMOperand*)Operands[3])->getReg())
3941 RegOp = 5;
3942 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3943 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003944 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3945
3946 return true;
3947}
Jim Grosbach623a4542011-08-10 22:42:16 +00003948
Jim Grosbach12431322011-10-24 22:16:58 +00003949bool ARMAsmParser::
3950cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3951 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3952 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003953 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003954 // Create a writeback register dummy placeholder.
3955 Inst.addOperand(MCOperand::CreateImm(0));
3956 // Vn
3957 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3958 // pred
3959 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3960 return true;
3961}
3962
3963bool ARMAsmParser::
3964cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3965 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3966 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003967 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003968 // Create a writeback register dummy placeholder.
3969 Inst.addOperand(MCOperand::CreateImm(0));
3970 // Vn
3971 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3972 // Vm
3973 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3974 // pred
3975 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3976 return true;
3977}
3978
Jim Grosbach4334e032011-10-31 21:50:31 +00003979bool ARMAsmParser::
3980cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3981 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3982 // Create a writeback register dummy placeholder.
3983 Inst.addOperand(MCOperand::CreateImm(0));
3984 // Vn
3985 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3986 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003987 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003988 // pred
3989 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3990 return true;
3991}
3992
3993bool ARMAsmParser::
3994cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3995 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3996 // Create a writeback register dummy placeholder.
3997 Inst.addOperand(MCOperand::CreateImm(0));
3998 // Vn
3999 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4000 // Vm
4001 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4002 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004003 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004004 // pred
4005 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4006 return true;
4007}
4008
Bill Wendlinge7176102010-11-06 22:36:58 +00004009/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004010/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004011bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004012parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004013 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004014 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004015 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004016 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004017 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004018
Sean Callanan18b83232010-01-19 21:44:56 +00004019 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004020 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004021 if (BaseRegNum == -1)
4022 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004023
Daniel Dunbar05710932011-01-18 05:34:17 +00004024 // The next token must either be a comma or a closing bracket.
4025 const AsmToken &Tok = Parser.getTok();
4026 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004027 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004028
Jim Grosbach7ce05792011-08-03 23:50:40 +00004029 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004030 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004031 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004032
Jim Grosbach7ce05792011-08-03 23:50:40 +00004033 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004034 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004035
Jim Grosbachfb12f352011-09-19 18:42:21 +00004036 // If there's a pre-indexing writeback marker, '!', just add it as a token
4037 // operand. It's rather odd, but syntactically valid.
4038 if (Parser.getTok().is(AsmToken::Exclaim)) {
4039 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4040 Parser.Lex(); // Eat the '!'.
4041 }
4042
Jim Grosbach7ce05792011-08-03 23:50:40 +00004043 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004044 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004045
Jim Grosbach7ce05792011-08-03 23:50:40 +00004046 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4047 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004048
Jim Grosbach57dcb852011-10-11 17:29:55 +00004049 // If we have a ':', it's an alignment specifier.
4050 if (Parser.getTok().is(AsmToken::Colon)) {
4051 Parser.Lex(); // Eat the ':'.
4052 E = Parser.getTok().getLoc();
4053
4054 const MCExpr *Expr;
4055 if (getParser().ParseExpression(Expr))
4056 return true;
4057
4058 // The expression has to be a constant. Memory references with relocations
4059 // don't come through here, as they use the <label> forms of the relevant
4060 // instructions.
4061 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4062 if (!CE)
4063 return Error (E, "constant expression expected");
4064
4065 unsigned Align = 0;
4066 switch (CE->getValue()) {
4067 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004068 return Error(E,
4069 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4070 case 16: Align = 2; break;
4071 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004072 case 64: Align = 8; break;
4073 case 128: Align = 16; break;
4074 case 256: Align = 32; break;
4075 }
4076
4077 // Now we should have the closing ']'
4078 E = Parser.getTok().getLoc();
4079 if (Parser.getTok().isNot(AsmToken::RBrac))
4080 return Error(E, "']' expected");
4081 Parser.Lex(); // Eat right bracket token.
4082
4083 // Don't worry about range checking the value here. That's handled by
4084 // the is*() predicates.
4085 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4086 ARM_AM::no_shift, 0, Align,
4087 false, S, E));
4088
4089 // If there's a pre-indexing writeback marker, '!', just add it as a token
4090 // operand.
4091 if (Parser.getTok().is(AsmToken::Exclaim)) {
4092 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4093 Parser.Lex(); // Eat the '!'.
4094 }
4095
4096 return false;
4097 }
4098
4099 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004100 // offset. Be friendly and also accept a plain integer (without a leading
4101 // hash) for gas compatibility.
4102 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004103 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004104 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004105 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004106 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004107 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004108
Owen Anderson0da10cf2011-08-29 19:36:44 +00004109 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004110 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004111 if (getParser().ParseExpression(Offset))
4112 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004113
4114 // The expression has to be a constant. Memory references with relocations
4115 // don't come through here, as they use the <label> forms of the relevant
4116 // instructions.
4117 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4118 if (!CE)
4119 return Error (E, "constant expression expected");
4120
Owen Anderson0da10cf2011-08-29 19:36:44 +00004121 // If the constant was #-0, represent it as INT32_MIN.
4122 int32_t Val = CE->getValue();
4123 if (isNegative && Val == 0)
4124 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4125
Jim Grosbach7ce05792011-08-03 23:50:40 +00004126 // Now we should have the closing ']'
4127 E = Parser.getTok().getLoc();
4128 if (Parser.getTok().isNot(AsmToken::RBrac))
4129 return Error(E, "']' expected");
4130 Parser.Lex(); // Eat right bracket token.
4131
4132 // Don't worry about range checking the value here. That's handled by
4133 // the is*() predicates.
4134 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004135 ARM_AM::no_shift, 0, 0,
4136 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004137
4138 // If there's a pre-indexing writeback marker, '!', just add it as a token
4139 // operand.
4140 if (Parser.getTok().is(AsmToken::Exclaim)) {
4141 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4142 Parser.Lex(); // Eat the '!'.
4143 }
4144
4145 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004146 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004147
4148 // The register offset is optionally preceded by a '+' or '-'
4149 bool isNegative = false;
4150 if (Parser.getTok().is(AsmToken::Minus)) {
4151 isNegative = true;
4152 Parser.Lex(); // Eat the '-'.
4153 } else if (Parser.getTok().is(AsmToken::Plus)) {
4154 // Nothing to do.
4155 Parser.Lex(); // Eat the '+'.
4156 }
4157
4158 E = Parser.getTok().getLoc();
4159 int OffsetRegNum = tryParseRegister();
4160 if (OffsetRegNum == -1)
4161 return Error(E, "register expected");
4162
4163 // If there's a shift operator, handle it.
4164 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004165 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004166 if (Parser.getTok().is(AsmToken::Comma)) {
4167 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004168 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004169 return true;
4170 }
4171
4172 // Now we should have the closing ']'
4173 E = Parser.getTok().getLoc();
4174 if (Parser.getTok().isNot(AsmToken::RBrac))
4175 return Error(E, "']' expected");
4176 Parser.Lex(); // Eat right bracket token.
4177
4178 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004179 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004180 S, E));
4181
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004182 // If there's a pre-indexing writeback marker, '!', just add it as a token
4183 // operand.
4184 if (Parser.getTok().is(AsmToken::Exclaim)) {
4185 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4186 Parser.Lex(); // Eat the '!'.
4187 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004188
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004189 return false;
4190}
4191
Jim Grosbach7ce05792011-08-03 23:50:40 +00004192/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004193/// ( lsl | lsr | asr | ror ) , # shift_amount
4194/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004195/// return true if it parses a shift otherwise it returns false.
4196bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4197 unsigned &Amount) {
4198 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004199 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004200 if (Tok.isNot(AsmToken::Identifier))
4201 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004202 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004203 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4204 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004205 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004206 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004207 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004208 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004209 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004210 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004211 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004212 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004213 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004214 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004215 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004216 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004217
Jim Grosbach7ce05792011-08-03 23:50:40 +00004218 // rrx stands alone.
4219 Amount = 0;
4220 if (St != ARM_AM::rrx) {
4221 Loc = Parser.getTok().getLoc();
4222 // A '#' and a shift amount.
4223 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004224 if (HashTok.isNot(AsmToken::Hash) &&
4225 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004226 return Error(HashTok.getLoc(), "'#' expected");
4227 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004228
Jim Grosbach7ce05792011-08-03 23:50:40 +00004229 const MCExpr *Expr;
4230 if (getParser().ParseExpression(Expr))
4231 return true;
4232 // Range check the immediate.
4233 // lsl, ror: 0 <= imm <= 31
4234 // lsr, asr: 0 <= imm <= 32
4235 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4236 if (!CE)
4237 return Error(Loc, "shift amount must be an immediate");
4238 int64_t Imm = CE->getValue();
4239 if (Imm < 0 ||
4240 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4241 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4242 return Error(Loc, "immediate shift value out of range");
4243 Amount = Imm;
4244 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004245
4246 return false;
4247}
4248
Jim Grosbach9d390362011-10-03 23:38:36 +00004249/// parseFPImm - A floating point immediate expression operand.
4250ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4251parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4252 SMLoc S = Parser.getTok().getLoc();
4253
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004254 if (Parser.getTok().isNot(AsmToken::Hash) &&
4255 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004256 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004257
4258 // Disambiguate the VMOV forms that can accept an FP immediate.
4259 // vmov.f32 <sreg>, #imm
4260 // vmov.f64 <dreg>, #imm
4261 // vmov.f32 <dreg>, #imm @ vector f32x2
4262 // vmov.f32 <qreg>, #imm @ vector f32x4
4263 //
4264 // There are also the NEON VMOV instructions which expect an
4265 // integer constant. Make sure we don't try to parse an FPImm
4266 // for these:
4267 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4268 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4269 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4270 TyOp->getToken() != ".f64"))
4271 return MatchOperand_NoMatch;
4272
Jim Grosbach9d390362011-10-03 23:38:36 +00004273 Parser.Lex(); // Eat the '#'.
4274
4275 // Handle negation, as that still comes through as a separate token.
4276 bool isNegative = false;
4277 if (Parser.getTok().is(AsmToken::Minus)) {
4278 isNegative = true;
4279 Parser.Lex();
4280 }
4281 const AsmToken &Tok = Parser.getTok();
4282 if (Tok.is(AsmToken::Real)) {
4283 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4284 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4285 // If we had a '-' in front, toggle the sign bit.
4286 IntVal ^= (uint64_t)isNegative << 63;
4287 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4288 Parser.Lex(); // Eat the token.
4289 if (Val == -1) {
4290 TokError("floating point value out of range");
4291 return MatchOperand_ParseFail;
4292 }
4293 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4294 return MatchOperand_Success;
4295 }
4296 if (Tok.is(AsmToken::Integer)) {
4297 int64_t Val = Tok.getIntVal();
4298 Parser.Lex(); // Eat the token.
4299 if (Val > 255 || Val < 0) {
4300 TokError("encoded floating point value out of range");
4301 return MatchOperand_ParseFail;
4302 }
4303 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4304 return MatchOperand_Success;
4305 }
4306
4307 TokError("invalid floating point immediate");
4308 return MatchOperand_ParseFail;
4309}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004310/// Parse a arm instruction operand. For now this parses the operand regardless
4311/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004312bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004313 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004314 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004315
4316 // Check if the current operand has a custom associated parser, if so, try to
4317 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004318 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4319 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004320 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004321 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4322 // there was a match, but an error occurred, in which case, just return that
4323 // the operand parsing failed.
4324 if (ResTy == MatchOperand_ParseFail)
4325 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004326
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004327 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004328 default:
4329 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004330 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004331 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004332 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004333 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004334 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004335 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004336 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004337 else if (Res == -1) // irrecoverable error
4338 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004339 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004340 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4341 S = Parser.getTok().getLoc();
4342 Parser.Lex();
4343 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4344 return false;
4345 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004346
4347 // Fall though for the Identifier case that is not a register or a
4348 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004349 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004350 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004351 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004352 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004353 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004354 // This was not a register so parse other operands that start with an
4355 // identifier (like labels) as expressions and create them as immediates.
4356 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004357 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004358 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004359 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004360 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004361 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4362 return false;
4363 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004364 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004365 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004366 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004367 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004368 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004369 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004370 // #42 -> immediate.
4371 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004372 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004373 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004374 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004375 const MCExpr *ImmVal;
4376 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004377 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004378 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004379 if (CE) {
4380 int32_t Val = CE->getValue();
4381 if (isNegative && Val == 0)
4382 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004383 }
Sean Callanan76264762010-04-02 22:27:05 +00004384 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004385 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4386 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004387 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004388 case AsmToken::Colon: {
4389 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004390 // FIXME: Check it's an expression prefix,
4391 // e.g. (FOO - :lower16:BAR) isn't legal.
4392 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004393 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004394 return true;
4395
Evan Cheng75972122011-01-13 07:58:56 +00004396 const MCExpr *SubExprVal;
4397 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004398 return true;
4399
Evan Cheng75972122011-01-13 07:58:56 +00004400 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4401 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004402 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004403 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004404 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004405 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004406 }
4407}
4408
Jim Grosbach1355cf12011-07-26 17:10:22 +00004409// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004410// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004411bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004412 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004413
4414 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004415 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004416 Parser.Lex(); // Eat ':'
4417
4418 if (getLexer().isNot(AsmToken::Identifier)) {
4419 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4420 return true;
4421 }
4422
4423 StringRef IDVal = Parser.getTok().getIdentifier();
4424 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004425 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004426 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004427 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004428 } else {
4429 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4430 return true;
4431 }
4432 Parser.Lex();
4433
4434 if (getLexer().isNot(AsmToken::Colon)) {
4435 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4436 return true;
4437 }
4438 Parser.Lex(); // Eat the last ':'
4439 return false;
4440}
4441
Daniel Dunbar352e1482011-01-11 15:59:50 +00004442/// \brief Given a mnemonic, split out possible predication code and carry
4443/// setting letters to form a canonical mnemonic and flags.
4444//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004445// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004446// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004447StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004448 unsigned &PredicationCode,
4449 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004450 unsigned &ProcessorIMod,
4451 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004452 PredicationCode = ARMCC::AL;
4453 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004454 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004455
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004456 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004457 //
4458 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004459 if ((Mnemonic == "movs" && isThumb()) ||
4460 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4461 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4462 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4463 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4464 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4465 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004466 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4467 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004468 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004469
Jim Grosbach3f00e312011-07-11 17:09:57 +00004470 // First, split out any predication code. Ignore mnemonics we know aren't
4471 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004472 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004473 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004474 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004475 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004476 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4477 .Case("eq", ARMCC::EQ)
4478 .Case("ne", ARMCC::NE)
4479 .Case("hs", ARMCC::HS)
4480 .Case("cs", ARMCC::HS)
4481 .Case("lo", ARMCC::LO)
4482 .Case("cc", ARMCC::LO)
4483 .Case("mi", ARMCC::MI)
4484 .Case("pl", ARMCC::PL)
4485 .Case("vs", ARMCC::VS)
4486 .Case("vc", ARMCC::VC)
4487 .Case("hi", ARMCC::HI)
4488 .Case("ls", ARMCC::LS)
4489 .Case("ge", ARMCC::GE)
4490 .Case("lt", ARMCC::LT)
4491 .Case("gt", ARMCC::GT)
4492 .Case("le", ARMCC::LE)
4493 .Case("al", ARMCC::AL)
4494 .Default(~0U);
4495 if (CC != ~0U) {
4496 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4497 PredicationCode = CC;
4498 }
Bill Wendling52925b62010-10-29 23:50:21 +00004499 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004500
Daniel Dunbar352e1482011-01-11 15:59:50 +00004501 // Next, determine if we have a carry setting bit. We explicitly ignore all
4502 // the instructions we know end in 's'.
4503 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004504 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004505 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4506 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4507 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004508 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004509 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004510 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004511 Mnemonic == "fmuls" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004512 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004513 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4514 CarrySetting = true;
4515 }
4516
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004517 // The "cps" instruction can have a interrupt mode operand which is glued into
4518 // the mnemonic. Check if this is the case, split it and parse the imod op
4519 if (Mnemonic.startswith("cps")) {
4520 // Split out any imod code.
4521 unsigned IMod =
4522 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4523 .Case("ie", ARM_PROC::IE)
4524 .Case("id", ARM_PROC::ID)
4525 .Default(~0U);
4526 if (IMod != ~0U) {
4527 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4528 ProcessorIMod = IMod;
4529 }
4530 }
4531
Jim Grosbach89df9962011-08-26 21:43:41 +00004532 // The "it" instruction has the condition mask on the end of the mnemonic.
4533 if (Mnemonic.startswith("it")) {
4534 ITMask = Mnemonic.slice(2, Mnemonic.size());
4535 Mnemonic = Mnemonic.slice(0, 2);
4536 }
4537
Daniel Dunbar352e1482011-01-11 15:59:50 +00004538 return Mnemonic;
4539}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004540
4541/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4542/// inclusion of carry set or predication code operands.
4543//
4544// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004545void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004546getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004547 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004548 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4549 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004550 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004551 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004552 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004553 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004554 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004555 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004556 Mnemonic == "mla" || Mnemonic == "smlal" ||
4557 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004558 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004559 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004560 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004561
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004562 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4563 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4564 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4565 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004566 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4567 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004568 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004569 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4570 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4571 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004572 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4573 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004574 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004575 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004576 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004577 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004578
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004579 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004580 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004581 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004582 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004583 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004584}
4585
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004586bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4587 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004588 // FIXME: This is all horribly hacky. We really need a better way to deal
4589 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004590
4591 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4592 // another does not. Specifically, the MOVW instruction does not. So we
4593 // special case it here and remove the defaulted (non-setting) cc_out
4594 // operand if that's the instruction we're trying to match.
4595 //
4596 // We do this as post-processing of the explicit operands rather than just
4597 // conditionally adding the cc_out in the first place because we need
4598 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004599 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004600 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4601 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4602 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4603 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004604
4605 // Register-register 'add' for thumb does not have a cc_out operand
4606 // when there are only two register operands.
4607 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4608 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4609 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4610 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4611 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004612 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004613 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4614 // have to check the immediate range here since Thumb2 has a variant
4615 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004616 if (((isThumb() && Mnemonic == "add") ||
4617 (isThumbTwo() && Mnemonic == "sub")) &&
4618 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004619 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4620 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4621 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004622 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4623 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4624 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004625 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004626 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4627 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004628 // selecting via the generic "add" mnemonic, so to know that we
4629 // should remove the cc_out operand, we have to explicitly check that
4630 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004631 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4632 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004633 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4634 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4635 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4636 // Nest conditions rather than one big 'if' statement for readability.
4637 //
4638 // If either register is a high reg, it's either one of the SP
4639 // variants (handled above) or a 32-bit encoding, so we just
4640 // check against T3.
4641 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4642 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4643 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4644 return false;
4645 // If both registers are low, we're in an IT block, and the immediate is
4646 // in range, we should use encoding T1 instead, which has a cc_out.
4647 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004648 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004649 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4650 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4651 return false;
4652
4653 // Otherwise, we use encoding T4, which does not have a cc_out
4654 // operand.
4655 return true;
4656 }
4657
Jim Grosbach64944f42011-09-14 21:00:40 +00004658 // The thumb2 multiply instruction doesn't have a CCOut register, so
4659 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4660 // use the 16-bit encoding or not.
4661 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4662 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4663 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4664 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4665 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4666 // If the registers aren't low regs, the destination reg isn't the
4667 // same as one of the source regs, or the cc_out operand is zero
4668 // outside of an IT block, we have to use the 32-bit encoding, so
4669 // remove the cc_out operand.
4670 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4671 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004672 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004673 !inITBlock() ||
4674 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4675 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4676 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4677 static_cast<ARMOperand*>(Operands[4])->getReg())))
4678 return true;
4679
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004680 // Also check the 'mul' syntax variant that doesn't specify an explicit
4681 // destination register.
4682 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4683 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4684 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4685 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4686 // If the registers aren't low regs or the cc_out operand is zero
4687 // outside of an IT block, we have to use the 32-bit encoding, so
4688 // remove the cc_out operand.
4689 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4690 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4691 !inITBlock()))
4692 return true;
4693
Jim Grosbach64944f42011-09-14 21:00:40 +00004694
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004695
Jim Grosbachf69c8042011-08-24 21:42:27 +00004696 // Register-register 'add/sub' for thumb does not have a cc_out operand
4697 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4698 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4699 // right, this will result in better diagnostics (which operand is off)
4700 // anyway.
4701 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4702 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004703 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4704 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4705 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4706 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004707
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004708 return false;
4709}
4710
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004711static bool isDataTypeToken(StringRef Tok) {
4712 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4713 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4714 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4715 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4716 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4717 Tok == ".f" || Tok == ".d";
4718}
4719
4720// FIXME: This bit should probably be handled via an explicit match class
4721// in the .td files that matches the suffix instead of having it be
4722// a literal string token the way it is now.
4723static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4724 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4725}
4726
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004727static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004728/// Parse an arm instruction mnemonic followed by its operands.
4729bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4730 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004731 // Apply mnemonic aliases before doing anything else, as the destination
4732 // mnemnonic may include suffices and we want to handle them normally.
4733 // The generic tblgen'erated code does this later, at the start of
4734 // MatchInstructionImpl(), but that's too late for aliases that include
4735 // any sort of suffix.
4736 unsigned AvailableFeatures = getAvailableFeatures();
4737 applyMnemonicAliases(Name, AvailableFeatures);
4738
Jim Grosbacha39cda72011-12-14 02:16:11 +00004739 // First check for the ARM-specific .req directive.
4740 if (Parser.getTok().is(AsmToken::Identifier) &&
4741 Parser.getTok().getIdentifier() == ".req") {
4742 parseDirectiveReq(Name, NameLoc);
4743 // We always return 'error' for this, as we're done with this
4744 // statement and don't need to match the 'instruction."
4745 return true;
4746 }
4747
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004748 // Create the leading tokens for the mnemonic, split by '.' characters.
4749 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004750 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004751
Daniel Dunbar352e1482011-01-11 15:59:50 +00004752 // Split out the predication code and carry setting flag from the mnemonic.
4753 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004754 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004755 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004756 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004757 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004758 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004759
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004760 // In Thumb1, only the branch (B) instruction can be predicated.
4761 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4762 Parser.EatToEndOfStatement();
4763 return Error(NameLoc, "conditional execution not supported in Thumb1");
4764 }
4765
Jim Grosbachffa32252011-07-19 19:13:28 +00004766 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4767
Jim Grosbach89df9962011-08-26 21:43:41 +00004768 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4769 // is the mask as it will be for the IT encoding if the conditional
4770 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4771 // where the conditional bit0 is zero, the instruction post-processing
4772 // will adjust the mask accordingly.
4773 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004774 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4775 if (ITMask.size() > 3) {
4776 Parser.EatToEndOfStatement();
4777 return Error(Loc, "too many conditions on IT instruction");
4778 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004779 unsigned Mask = 8;
4780 for (unsigned i = ITMask.size(); i != 0; --i) {
4781 char pos = ITMask[i - 1];
4782 if (pos != 't' && pos != 'e') {
4783 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004784 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004785 }
4786 Mask >>= 1;
4787 if (ITMask[i - 1] == 't')
4788 Mask |= 8;
4789 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004790 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004791 }
4792
Jim Grosbachffa32252011-07-19 19:13:28 +00004793 // FIXME: This is all a pretty gross hack. We should automatically handle
4794 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004795
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004796 // Next, add the CCOut and ConditionCode operands, if needed.
4797 //
4798 // For mnemonics which can ever incorporate a carry setting bit or predication
4799 // code, our matching model involves us always generating CCOut and
4800 // ConditionCode operands to match the mnemonic "as written" and then we let
4801 // the matcher deal with finding the right instruction or generating an
4802 // appropriate error.
4803 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004804 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004805
Jim Grosbach33c16a22011-07-14 22:04:21 +00004806 // If we had a carry-set on an instruction that can't do that, issue an
4807 // error.
4808 if (!CanAcceptCarrySet && CarrySetting) {
4809 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004810 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004811 "' can not set flags, but 's' suffix specified");
4812 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004813 // If we had a predication code on an instruction that can't do that, issue an
4814 // error.
4815 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4816 Parser.EatToEndOfStatement();
4817 return Error(NameLoc, "instruction '" + Mnemonic +
4818 "' is not predicable, but condition code specified");
4819 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004820
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004821 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004822 if (CanAcceptCarrySet) {
4823 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004824 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004825 Loc));
4826 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004827
4828 // Add the predication code operand, if necessary.
4829 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004830 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4831 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004832 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004833 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004834 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004835
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004836 // Add the processor imod operand, if necessary.
4837 if (ProcessorIMod) {
4838 Operands.push_back(ARMOperand::CreateImm(
4839 MCConstantExpr::Create(ProcessorIMod, getContext()),
4840 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004841 }
4842
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004843 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004844 while (Next != StringRef::npos) {
4845 Start = Next;
4846 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004847 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004848
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004849 // Some NEON instructions have an optional datatype suffix that is
4850 // completely ignored. Check for that.
4851 if (isDataTypeToken(ExtraToken) &&
4852 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4853 continue;
4854
Jim Grosbach81d2e392011-09-07 16:06:04 +00004855 if (ExtraToken != ".n") {
4856 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4857 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4858 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004859 }
4860
4861 // Read the remaining operands.
4862 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004863 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004864 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004865 Parser.EatToEndOfStatement();
4866 return true;
4867 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004868
4869 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004870 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004871
4872 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004873 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004874 Parser.EatToEndOfStatement();
4875 return true;
4876 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004877 }
4878 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004879
Chris Lattnercbf8a982010-09-11 16:18:25 +00004880 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004881 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004882 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004883 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004884 }
Bill Wendling146018f2010-11-06 21:42:12 +00004885
Chris Lattner34e53142010-09-08 05:10:46 +00004886 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004887
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004888 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4889 // do and don't have a cc_out optional-def operand. With some spot-checks
4890 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004891 // parse and adjust accordingly before actually matching. We shouldn't ever
4892 // try to remove a cc_out operand that was explicitly set on the the
4893 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4894 // table driven matcher doesn't fit well with the ARM instruction set.
4895 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004896 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4897 Operands.erase(Operands.begin() + 1);
4898 delete Op;
4899 }
4900
Jim Grosbachcf121c32011-07-28 21:57:55 +00004901 // ARM mode 'blx' need special handling, as the register operand version
4902 // is predicable, but the label operand version is not. So, we can't rely
4903 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004904 // a k_CondCode operand in the list. If we're trying to match the label
4905 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004906 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4907 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4908 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4909 Operands.erase(Operands.begin() + 1);
4910 delete Op;
4911 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004912
4913 // The vector-compare-to-zero instructions have a literal token "#0" at
4914 // the end that comes to here as an immediate operand. Convert it to a
4915 // token to play nicely with the matcher.
4916 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4917 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4918 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4919 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4920 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4921 if (CE && CE->getValue() == 0) {
4922 Operands.erase(Operands.begin() + 5);
4923 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4924 delete Op;
4925 }
4926 }
Jim Grosbach68259142011-10-03 22:30:24 +00004927 // VCMP{E} does the same thing, but with a different operand count.
4928 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4929 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4930 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4931 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4932 if (CE && CE->getValue() == 0) {
4933 Operands.erase(Operands.begin() + 4);
4934 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4935 delete Op;
4936 }
4937 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004938 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004939 // end. Convert it to a token here. Take care not to convert those
4940 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004941 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004942 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4943 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004944 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4945 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4946 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004947 if (CE && CE->getValue() == 0 &&
4948 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004949 // The cc_out operand matches the IT block.
4950 ((inITBlock() != CarrySetting) &&
4951 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004952 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004953 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004954 Operands.erase(Operands.begin() + 5);
4955 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4956 delete Op;
4957 }
4958 }
4959
Chris Lattner98986712010-01-14 22:21:20 +00004960 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004961}
4962
Jim Grosbach189610f2011-07-26 18:25:39 +00004963// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004964
4965// return 'true' if register list contains non-low GPR registers,
4966// 'false' otherwise. If Reg is in the register list or is HiReg, set
4967// 'containsReg' to true.
4968static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4969 unsigned HiReg, bool &containsReg) {
4970 containsReg = false;
4971 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4972 unsigned OpReg = Inst.getOperand(i).getReg();
4973 if (OpReg == Reg)
4974 containsReg = true;
4975 // Anything other than a low register isn't legal here.
4976 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4977 return true;
4978 }
4979 return false;
4980}
4981
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004982// Check if the specified regisgter is in the register list of the inst,
4983// starting at the indicated operand number.
4984static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4985 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4986 unsigned OpReg = Inst.getOperand(i).getReg();
4987 if (OpReg == Reg)
4988 return true;
4989 }
4990 return false;
4991}
4992
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004993// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4994// the ARMInsts array) instead. Getting that here requires awkward
4995// API changes, though. Better way?
4996namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004997extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004998}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004999static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005000 return ARMInsts[Opcode];
5001}
5002
Jim Grosbach189610f2011-07-26 18:25:39 +00005003// FIXME: We would really like to be able to tablegen'erate this.
5004bool ARMAsmParser::
5005validateInstruction(MCInst &Inst,
5006 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005007 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005008 SMLoc Loc = Operands[0]->getStartLoc();
5009 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005010 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5011 // being allowed in IT blocks, but not being predicable. It just always
5012 // executes.
5013 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005014 unsigned bit = 1;
5015 if (ITState.FirstCond)
5016 ITState.FirstCond = false;
5017 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005018 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005019 // The instruction must be predicable.
5020 if (!MCID.isPredicable())
5021 return Error(Loc, "instructions in IT block must be predicable");
5022 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5023 unsigned ITCond = bit ? ITState.Cond :
5024 ARMCC::getOppositeCondition(ITState.Cond);
5025 if (Cond != ITCond) {
5026 // Find the condition code Operand to get its SMLoc information.
5027 SMLoc CondLoc;
5028 for (unsigned i = 1; i < Operands.size(); ++i)
5029 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5030 CondLoc = Operands[i]->getStartLoc();
5031 return Error(CondLoc, "incorrect condition in IT block; got '" +
5032 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5033 "', but expected '" +
5034 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5035 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005036 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005037 } else if (isThumbTwo() && MCID.isPredicable() &&
5038 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005039 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5040 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005041 return Error(Loc, "predicated instructions must be in IT block");
5042
Jim Grosbach189610f2011-07-26 18:25:39 +00005043 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005044 case ARM::LDRD:
5045 case ARM::LDRD_PRE:
5046 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005047 case ARM::LDREXD: {
5048 // Rt2 must be Rt + 1.
5049 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5050 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5051 if (Rt2 != Rt + 1)
5052 return Error(Operands[3]->getStartLoc(),
5053 "destination operands must be sequential");
5054 return false;
5055 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005056 case ARM::STRD: {
5057 // Rt2 must be Rt + 1.
5058 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5059 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5060 if (Rt2 != Rt + 1)
5061 return Error(Operands[3]->getStartLoc(),
5062 "source operands must be sequential");
5063 return false;
5064 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005065 case ARM::STRD_PRE:
5066 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005067 case ARM::STREXD: {
5068 // Rt2 must be Rt + 1.
5069 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5070 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5071 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005072 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005073 "source operands must be sequential");
5074 return false;
5075 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005076 case ARM::SBFX:
5077 case ARM::UBFX: {
5078 // width must be in range [1, 32-lsb]
5079 unsigned lsb = Inst.getOperand(2).getImm();
5080 unsigned widthm1 = Inst.getOperand(3).getImm();
5081 if (widthm1 >= 32 - lsb)
5082 return Error(Operands[5]->getStartLoc(),
5083 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005084 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005085 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005086 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005087 // If we're parsing Thumb2, the .w variant is available and handles
5088 // most cases that are normally illegal for a Thumb1 LDM
5089 // instruction. We'll make the transformation in processInstruction()
5090 // if necessary.
5091 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005092 // Thumb LDM instructions are writeback iff the base register is not
5093 // in the register list.
5094 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005095 bool hasWritebackToken =
5096 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5097 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005098 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005099 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005100 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5101 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005102 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005103 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005104 return Error(Operands[2]->getStartLoc(),
5105 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005106 // If we should not have writeback, there must not be a '!'. This is
5107 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005108 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005109 return Error(Operands[3]->getStartLoc(),
5110 "writeback operator '!' not allowed when base register "
5111 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005112
5113 break;
5114 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005115 case ARM::t2LDMIA_UPD: {
5116 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5117 return Error(Operands[4]->getStartLoc(),
5118 "writeback operator '!' not allowed when base register "
5119 "in register list");
5120 break;
5121 }
Jim Grosbach54026372011-11-10 23:17:11 +00005122 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5123 // so only issue a diagnostic for thumb1. The instructions will be
5124 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005125 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005126 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005127 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5128 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005129 return Error(Operands[2]->getStartLoc(),
5130 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005131 break;
5132 }
5133 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005134 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005135 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5136 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005137 return Error(Operands[2]->getStartLoc(),
5138 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005139 break;
5140 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005141 case ARM::tSTMIA_UPD: {
5142 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005143 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005144 return Error(Operands[4]->getStartLoc(),
5145 "registers must be in range r0-r7");
5146 break;
5147 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005148 }
5149
5150 return false;
5151}
5152
Jim Grosbach5b484312011-12-20 20:46:29 +00005153static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005154 switch(Opc) {
5155 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005156 // VST1LN
5157 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5158 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5159 case ARM::VST1LNdWB_fixed_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_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5163 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5164 case ARM::VST1LNdWB_fixed_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_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5168 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5169 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_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::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5173 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5174 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005175 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005176 return ARM::VST1LNd8_UPD;
5177 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5178 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5179 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005180 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005181 return ARM::VST1LNd16_UPD;
5182 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5183 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5184 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005185 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005186 return ARM::VST1LNd32_UPD;
5187 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5188 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5189 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005190 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005191 return ARM::VST1LNd8;
5192 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5193 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5194 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005195 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005196 return ARM::VST1LNd16;
5197 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5198 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5199 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005200 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005201 return ARM::VST1LNd32;
5202
5203 // VST2LN
5204 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5205 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5206 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005207 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005208 return ARM::VST2LNd8_UPD;
5209 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5210 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5211 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005212 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005213 return ARM::VST2LNd16_UPD;
5214 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5215 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5216 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005217 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005218 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005219 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5220 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5221 case ARM::VST2LNqWB_fixed_Asm_U16:
5222 Spacing = 2;
5223 return ARM::VST2LNq16_UPD;
5224 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5225 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5226 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5227 Spacing = 2;
5228 return ARM::VST2LNq32_UPD;
5229
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005230 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5231 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5232 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005233 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005234 return ARM::VST2LNd8_UPD;
5235 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5236 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5237 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005238 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005239 return ARM::VST2LNd16_UPD;
5240 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5241 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5242 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005243 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005244 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005245 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5246 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5247 case ARM::VST2LNqWB_register_Asm_U16:
5248 Spacing = 2;
5249 return ARM::VST2LNq16_UPD;
5250 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5251 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5252 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5253 Spacing = 2;
5254 return ARM::VST2LNq32_UPD;
5255
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005256 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5257 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5258 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005259 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005260 return ARM::VST2LNd8;
5261 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5262 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5263 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005264 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005265 return ARM::VST2LNd16;
5266 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5267 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5268 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005269 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005270 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005271 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5272 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5273 case ARM::VST2LNqAsm_U16:
5274 Spacing = 2;
5275 return ARM::VST2LNq16;
5276 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5277 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5278 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5279 Spacing = 2;
5280 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005281 }
5282}
5283
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005284static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005285 switch(Opc) {
5286 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005287 // VLD1LN
5288 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5289 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5290 case ARM::VLD1LNdWB_fixed_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_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5294 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5295 case ARM::VLD1LNdWB_fixed_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_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5299 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5300 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_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::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5304 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5305 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005306 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005307 return ARM::VLD1LNd8_UPD;
5308 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5309 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5310 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005311 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005312 return ARM::VLD1LNd16_UPD;
5313 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5314 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5315 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005316 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005317 return ARM::VLD1LNd32_UPD;
5318 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5319 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5320 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005321 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005322 return ARM::VLD1LNd8;
5323 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5324 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5325 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005326 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005327 return ARM::VLD1LNd16;
5328 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5329 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5330 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005331 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005332 return ARM::VLD1LNd32;
5333
5334 // VLD2LN
5335 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5336 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5337 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005338 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005339 return ARM::VLD2LNd8_UPD;
5340 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5341 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5342 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005343 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005344 return ARM::VLD2LNd16_UPD;
5345 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5346 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5347 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005348 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005349 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005350 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5351 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5352 case ARM::VLD2LNqWB_fixed_Asm_U16:
5353 Spacing = 1;
5354 return ARM::VLD2LNq16_UPD;
5355 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5356 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5357 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5358 Spacing = 2;
5359 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005360 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5361 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5362 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005363 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005364 return ARM::VLD2LNd8_UPD;
5365 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5366 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5367 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005368 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005369 return ARM::VLD2LNd16_UPD;
5370 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5371 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5372 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005373 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005374 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005375 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5376 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5377 case ARM::VLD2LNqWB_register_Asm_U16:
5378 Spacing = 2;
5379 return ARM::VLD2LNq16_UPD;
5380 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5381 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5382 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5383 Spacing = 2;
5384 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005385 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5386 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5387 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005388 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005389 return ARM::VLD2LNd8;
5390 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5391 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5392 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005393 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005394 return ARM::VLD2LNd16;
5395 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5396 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5397 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005398 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005399 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005400 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5401 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5402 case ARM::VLD2LNqAsm_U16:
5403 Spacing = 2;
5404 return ARM::VLD2LNq16;
5405 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5406 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5407 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5408 Spacing = 2;
5409 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005410 }
5411}
5412
Jim Grosbach83ec8772011-11-10 23:42:14 +00005413bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005414processInstruction(MCInst &Inst,
5415 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5416 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005417 // Handle NEON VST complex aliases.
5418 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5419 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5420 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5421 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5422 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5423 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5424 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5425 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005426 MCInst TmpInst;
5427 // Shuffle the operands around so the lane index operand is in the
5428 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005429 unsigned Spacing;
5430 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005431 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5432 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5433 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5434 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5435 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5436 TmpInst.addOperand(Inst.getOperand(1)); // lane
5437 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5438 TmpInst.addOperand(Inst.getOperand(6));
5439 Inst = TmpInst;
5440 return true;
5441 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005442
Jim Grosbach5b484312011-12-20 20:46:29 +00005443 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5444 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5445 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005446 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5447 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005448 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005449 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005450 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5451 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5452 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5453 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5454 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5455 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5456 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005457 MCInst TmpInst;
5458 // Shuffle the operands around so the lane index operand is in the
5459 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005460 unsigned Spacing;
5461 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005462 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5463 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5464 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5465 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5466 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005467 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5468 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005469 TmpInst.addOperand(Inst.getOperand(1)); // lane
5470 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5471 TmpInst.addOperand(Inst.getOperand(6));
5472 Inst = TmpInst;
5473 return true;
5474 }
5475 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5476 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5477 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5478 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5479 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5480 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5481 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5482 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005483 MCInst TmpInst;
5484 // Shuffle the operands around so the lane index operand is in the
5485 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005486 unsigned Spacing;
5487 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005488 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5489 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5490 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5491 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5492 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5493 TmpInst.addOperand(Inst.getOperand(1)); // lane
5494 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5495 TmpInst.addOperand(Inst.getOperand(5));
5496 Inst = TmpInst;
5497 return true;
5498 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005499
Jim Grosbach5b484312011-12-20 20:46:29 +00005500 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5501 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5502 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005503 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5504 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005505 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005506 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005507 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5508 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5509 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5510 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5511 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5512 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5513 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005514 MCInst TmpInst;
5515 // Shuffle the operands around so the lane index operand is in the
5516 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005517 unsigned Spacing;
5518 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005519 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5520 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5521 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5522 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5523 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005524 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5525 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005526 TmpInst.addOperand(Inst.getOperand(1)); // lane
5527 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5528 TmpInst.addOperand(Inst.getOperand(5));
5529 Inst = TmpInst;
5530 return true;
5531 }
5532 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5533 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5534 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5535 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5536 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005537 case ARM::VST1LNdAsm_U32: {
5538 MCInst TmpInst;
5539 // Shuffle the operands around so the lane index operand is in the
5540 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005541 unsigned Spacing;
5542 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005543 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5544 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5545 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5546 TmpInst.addOperand(Inst.getOperand(1)); // lane
5547 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5548 TmpInst.addOperand(Inst.getOperand(5));
5549 Inst = TmpInst;
5550 return true;
5551 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005552
Jim Grosbach5b484312011-12-20 20:46:29 +00005553 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5554 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005555 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005556 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005557 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005558 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5559 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5560 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5561 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005562 MCInst TmpInst;
5563 // Shuffle the operands around so the lane index operand is in the
5564 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005565 unsigned Spacing;
5566 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005567 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5568 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5569 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005570 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5571 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005572 TmpInst.addOperand(Inst.getOperand(1)); // lane
5573 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5574 TmpInst.addOperand(Inst.getOperand(5));
5575 Inst = TmpInst;
5576 return true;
5577 }
5578 // Handle NEON VLD complex aliases.
5579 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5580 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5581 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5582 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5583 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5584 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5585 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5586 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005587 MCInst TmpInst;
5588 // Shuffle the operands around so the lane index operand is in the
5589 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005590 unsigned Spacing;
5591 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005592 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5593 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5594 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5595 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5596 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5597 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5598 TmpInst.addOperand(Inst.getOperand(1)); // lane
5599 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5600 TmpInst.addOperand(Inst.getOperand(6));
5601 Inst = TmpInst;
5602 return true;
5603 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005604
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005605 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5606 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5607 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005608 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5609 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005610 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005611 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005612 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005613 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5614 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5615 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5616 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5617 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5618 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005619 MCInst TmpInst;
5620 // Shuffle the operands around so the lane index operand is in the
5621 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005622 unsigned Spacing;
5623 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005624 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005625 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5626 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005627 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5628 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5629 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5630 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5631 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005632 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5633 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005634 TmpInst.addOperand(Inst.getOperand(1)); // lane
5635 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5636 TmpInst.addOperand(Inst.getOperand(6));
5637 Inst = TmpInst;
5638 return true;
5639 }
5640
5641 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5642 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5643 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5644 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5645 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5646 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5647 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5648 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005649 MCInst TmpInst;
5650 // Shuffle the operands around so the lane index operand is in the
5651 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005652 unsigned Spacing;
5653 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005654 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5655 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5656 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5657 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5658 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5659 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5660 TmpInst.addOperand(Inst.getOperand(1)); // lane
5661 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5662 TmpInst.addOperand(Inst.getOperand(5));
5663 Inst = TmpInst;
5664 return true;
5665 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005666
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005667 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5668 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5669 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005670 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5671 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005672 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005673 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005674 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005675 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5676 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5677 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5678 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5679 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5680 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005681 MCInst TmpInst;
5682 // Shuffle the operands around so the lane index operand is in the
5683 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005684 unsigned Spacing;
5685 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005686 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005687 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5688 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005689 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5690 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5691 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5692 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5693 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005694 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5695 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005696 TmpInst.addOperand(Inst.getOperand(1)); // lane
5697 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5698 TmpInst.addOperand(Inst.getOperand(5));
5699 Inst = TmpInst;
5700 return true;
5701 }
5702
Jim Grosbach5b484312011-12-20 20:46:29 +00005703 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5704 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005705 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005706 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005707 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005708 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005709 MCInst TmpInst;
5710 // Shuffle the operands around so the lane index operand is in the
5711 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005712 unsigned Spacing;
5713 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005714 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5715 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5716 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5717 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5718 TmpInst.addOperand(Inst.getOperand(1)); // lane
5719 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5720 TmpInst.addOperand(Inst.getOperand(5));
5721 Inst = TmpInst;
5722 return true;
5723 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005724
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005725 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5726 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005727 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005728 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005729 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005730 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5731 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5732 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5733 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5734 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005735 MCInst TmpInst;
5736 // Shuffle the operands around so the lane index operand is in the
5737 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005738 unsigned Spacing;
5739 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005740 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005741 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5742 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005743 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5744 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5745 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005746 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5747 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005748 TmpInst.addOperand(Inst.getOperand(1)); // lane
5749 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5750 TmpInst.addOperand(Inst.getOperand(5));
5751 Inst = TmpInst;
5752 return true;
5753 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005754 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00005755 case ARM::t2MOVsr:
5756 case ARM::t2MOVSsr: {
5757 // Which instruction to expand to depends on the CCOut operand and
5758 // whether we're in an IT block if the register operands are low
5759 // registers.
5760 bool isNarrow = false;
5761 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5762 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5763 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5764 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5765 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5766 isNarrow = true;
5767 MCInst TmpInst;
5768 unsigned newOpc;
5769 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5770 default: llvm_unreachable("unexpected opcode!");
5771 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5772 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5773 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5774 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5775 }
5776 TmpInst.setOpcode(newOpc);
5777 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5778 if (isNarrow)
5779 TmpInst.addOperand(MCOperand::CreateReg(
5780 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5781 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5782 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5783 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5784 TmpInst.addOperand(Inst.getOperand(5));
5785 if (!isNarrow)
5786 TmpInst.addOperand(MCOperand::CreateReg(
5787 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5788 Inst = TmpInst;
5789 return true;
5790 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005791 case ARM::t2MOVsi:
5792 case ARM::t2MOVSsi: {
5793 // Which instruction to expand to depends on the CCOut operand and
5794 // whether we're in an IT block if the register operands are low
5795 // registers.
5796 bool isNarrow = false;
5797 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5798 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5799 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5800 isNarrow = true;
5801 MCInst TmpInst;
5802 unsigned newOpc;
5803 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5804 default: llvm_unreachable("unexpected opcode!");
5805 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5806 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5807 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5808 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00005809 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00005810 }
5811 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5812 if (Ammount == 32) Ammount = 0;
5813 TmpInst.setOpcode(newOpc);
5814 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5815 if (isNarrow)
5816 TmpInst.addOperand(MCOperand::CreateReg(
5817 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5818 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00005819 if (newOpc != ARM::t2RRX)
5820 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00005821 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5822 TmpInst.addOperand(Inst.getOperand(4));
5823 if (!isNarrow)
5824 TmpInst.addOperand(MCOperand::CreateReg(
5825 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5826 Inst = TmpInst;
5827 return true;
5828 }
5829 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005830 case ARM::ASRr:
5831 case ARM::LSRr:
5832 case ARM::LSLr:
5833 case ARM::RORr: {
5834 ARM_AM::ShiftOpc ShiftTy;
5835 switch(Inst.getOpcode()) {
5836 default: llvm_unreachable("unexpected opcode!");
5837 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5838 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5839 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5840 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5841 }
Jim Grosbach23f22072011-11-16 18:31:45 +00005842 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5843 MCInst TmpInst;
5844 TmpInst.setOpcode(ARM::MOVsr);
5845 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5846 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5847 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5848 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5849 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5850 TmpInst.addOperand(Inst.getOperand(4));
5851 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5852 Inst = TmpInst;
5853 return true;
5854 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005855 case ARM::ASRi:
5856 case ARM::LSRi:
5857 case ARM::LSLi:
5858 case ARM::RORi: {
5859 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005860 switch(Inst.getOpcode()) {
5861 default: llvm_unreachable("unexpected opcode!");
5862 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5863 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5864 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5865 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5866 }
5867 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005868 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005869 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5870 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005871 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005872 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005873 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5874 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005875 if (Opc == ARM::MOVsi)
5876 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005877 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5878 TmpInst.addOperand(Inst.getOperand(4));
5879 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5880 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005881 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005882 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005883 case ARM::RRXi: {
5884 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5885 MCInst TmpInst;
5886 TmpInst.setOpcode(ARM::MOVsi);
5887 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5888 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5889 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5890 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5891 TmpInst.addOperand(Inst.getOperand(3));
5892 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5893 Inst = TmpInst;
5894 return true;
5895 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005896 case ARM::t2LDMIA_UPD: {
5897 // If this is a load of a single register, then we should use
5898 // a post-indexed LDR instruction instead, per the ARM ARM.
5899 if (Inst.getNumOperands() != 5)
5900 return false;
5901 MCInst TmpInst;
5902 TmpInst.setOpcode(ARM::t2LDR_POST);
5903 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5904 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5905 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5906 TmpInst.addOperand(MCOperand::CreateImm(4));
5907 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5908 TmpInst.addOperand(Inst.getOperand(3));
5909 Inst = TmpInst;
5910 return true;
5911 }
5912 case ARM::t2STMDB_UPD: {
5913 // If this is a store of a single register, then we should use
5914 // a pre-indexed STR instruction instead, per the ARM ARM.
5915 if (Inst.getNumOperands() != 5)
5916 return false;
5917 MCInst TmpInst;
5918 TmpInst.setOpcode(ARM::t2STR_PRE);
5919 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5920 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5921 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5922 TmpInst.addOperand(MCOperand::CreateImm(-4));
5923 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5924 TmpInst.addOperand(Inst.getOperand(3));
5925 Inst = TmpInst;
5926 return true;
5927 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005928 case ARM::LDMIA_UPD:
5929 // If this is a load of a single register via a 'pop', then we should use
5930 // a post-indexed LDR instruction instead, per the ARM ARM.
5931 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5932 Inst.getNumOperands() == 5) {
5933 MCInst TmpInst;
5934 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5935 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5936 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5937 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5938 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5939 TmpInst.addOperand(MCOperand::CreateImm(4));
5940 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5941 TmpInst.addOperand(Inst.getOperand(3));
5942 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005943 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005944 }
5945 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005946 case ARM::STMDB_UPD:
5947 // If this is a store of a single register via a 'push', then we should use
5948 // a pre-indexed STR instruction instead, per the ARM ARM.
5949 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5950 Inst.getNumOperands() == 5) {
5951 MCInst TmpInst;
5952 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5953 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5954 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5955 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5956 TmpInst.addOperand(MCOperand::CreateImm(-4));
5957 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5958 TmpInst.addOperand(Inst.getOperand(3));
5959 Inst = TmpInst;
5960 }
5961 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005962 case ARM::t2ADDri12:
5963 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5964 // mnemonic was used (not "addw"), encoding T3 is preferred.
5965 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5966 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5967 break;
5968 Inst.setOpcode(ARM::t2ADDri);
5969 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5970 break;
5971 case ARM::t2SUBri12:
5972 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5973 // mnemonic was used (not "subw"), encoding T3 is preferred.
5974 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5975 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5976 break;
5977 Inst.setOpcode(ARM::t2SUBri);
5978 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5979 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005980 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005981 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5982 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5983 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5984 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005985 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005986 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005987 return true;
5988 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005989 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005990 case ARM::tSUBi8:
5991 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5992 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5993 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5994 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005995 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005996 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005997 return true;
5998 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005999 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006000 case ARM::t2ADDrr: {
6001 // If the destination and first source operand are the same, and
6002 // there's no setting of the flags, use encoding T2 instead of T3.
6003 // Note that this is only for ADD, not SUB. This mirrors the system
6004 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6005 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6006 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006007 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6008 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006009 break;
6010 MCInst TmpInst;
6011 TmpInst.setOpcode(ARM::tADDhirr);
6012 TmpInst.addOperand(Inst.getOperand(0));
6013 TmpInst.addOperand(Inst.getOperand(0));
6014 TmpInst.addOperand(Inst.getOperand(2));
6015 TmpInst.addOperand(Inst.getOperand(3));
6016 TmpInst.addOperand(Inst.getOperand(4));
6017 Inst = TmpInst;
6018 return true;
6019 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006020 case ARM::tB:
6021 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006022 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006023 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006024 return true;
6025 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006026 break;
6027 case ARM::t2B:
6028 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006029 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006030 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006031 return true;
6032 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006033 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006034 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006035 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006036 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006037 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006038 return true;
6039 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006040 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006041 case ARM::tBcc:
6042 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006043 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006044 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006045 return true;
6046 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006047 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006048 case ARM::tLDMIA: {
6049 // If the register list contains any high registers, or if the writeback
6050 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6051 // instead if we're in Thumb2. Otherwise, this should have generated
6052 // an error in validateInstruction().
6053 unsigned Rn = Inst.getOperand(0).getReg();
6054 bool hasWritebackToken =
6055 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6056 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6057 bool listContainsBase;
6058 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6059 (!listContainsBase && !hasWritebackToken) ||
6060 (listContainsBase && hasWritebackToken)) {
6061 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6062 assert (isThumbTwo());
6063 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6064 // If we're switching to the updating version, we need to insert
6065 // the writeback tied operand.
6066 if (hasWritebackToken)
6067 Inst.insert(Inst.begin(),
6068 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006069 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006070 }
6071 break;
6072 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006073 case ARM::tSTMIA_UPD: {
6074 // If the register list contains any high registers, we need to use
6075 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6076 // should have generated an error in validateInstruction().
6077 unsigned Rn = Inst.getOperand(0).getReg();
6078 bool listContainsBase;
6079 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6080 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6081 assert (isThumbTwo());
6082 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006083 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006084 }
6085 break;
6086 }
Jim Grosbach54026372011-11-10 23:17:11 +00006087 case ARM::tPOP: {
6088 bool listContainsBase;
6089 // If the register list contains any high registers, we need to use
6090 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6091 // should have generated an error in validateInstruction().
6092 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006093 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006094 assert (isThumbTwo());
6095 Inst.setOpcode(ARM::t2LDMIA_UPD);
6096 // Add the base register and writeback operands.
6097 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6098 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006099 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006100 }
6101 case ARM::tPUSH: {
6102 bool listContainsBase;
6103 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006104 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006105 assert (isThumbTwo());
6106 Inst.setOpcode(ARM::t2STMDB_UPD);
6107 // Add the base register and writeback operands.
6108 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6109 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006110 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006111 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006112 case ARM::t2MOVi: {
6113 // If we can use the 16-bit encoding and the user didn't explicitly
6114 // request the 32-bit variant, transform it here.
6115 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6116 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006117 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6118 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6119 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006120 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6121 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6122 // The operands aren't in the same order for tMOVi8...
6123 MCInst TmpInst;
6124 TmpInst.setOpcode(ARM::tMOVi8);
6125 TmpInst.addOperand(Inst.getOperand(0));
6126 TmpInst.addOperand(Inst.getOperand(4));
6127 TmpInst.addOperand(Inst.getOperand(1));
6128 TmpInst.addOperand(Inst.getOperand(2));
6129 TmpInst.addOperand(Inst.getOperand(3));
6130 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006131 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006132 }
6133 break;
6134 }
6135 case ARM::t2MOVr: {
6136 // If we can use the 16-bit encoding and the user didn't explicitly
6137 // request the 32-bit variant, transform it here.
6138 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6139 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6140 Inst.getOperand(2).getImm() == ARMCC::AL &&
6141 Inst.getOperand(4).getReg() == ARM::CPSR &&
6142 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6143 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6144 // The operands aren't the same for tMOV[S]r... (no cc_out)
6145 MCInst TmpInst;
6146 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6147 TmpInst.addOperand(Inst.getOperand(0));
6148 TmpInst.addOperand(Inst.getOperand(1));
6149 TmpInst.addOperand(Inst.getOperand(2));
6150 TmpInst.addOperand(Inst.getOperand(3));
6151 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006152 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006153 }
6154 break;
6155 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006156 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006157 case ARM::t2SXTB:
6158 case ARM::t2UXTH:
6159 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006160 // If we can use the 16-bit encoding and the user didn't explicitly
6161 // request the 32-bit variant, transform it here.
6162 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6163 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6164 Inst.getOperand(2).getImm() == 0 &&
6165 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6166 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006167 unsigned NewOpc;
6168 switch (Inst.getOpcode()) {
6169 default: llvm_unreachable("Illegal opcode!");
6170 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6171 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6172 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6173 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6174 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006175 // The operands aren't the same for thumb1 (no rotate operand).
6176 MCInst TmpInst;
6177 TmpInst.setOpcode(NewOpc);
6178 TmpInst.addOperand(Inst.getOperand(0));
6179 TmpInst.addOperand(Inst.getOperand(1));
6180 TmpInst.addOperand(Inst.getOperand(3));
6181 TmpInst.addOperand(Inst.getOperand(4));
6182 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006183 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006184 }
6185 break;
6186 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006187 case ARM::MOVsi: {
6188 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6189 if (SOpc == ARM_AM::rrx) return false;
6190 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6191 // Shifting by zero is accepted as a vanilla 'MOVr'
6192 MCInst TmpInst;
6193 TmpInst.setOpcode(ARM::MOVr);
6194 TmpInst.addOperand(Inst.getOperand(0));
6195 TmpInst.addOperand(Inst.getOperand(1));
6196 TmpInst.addOperand(Inst.getOperand(3));
6197 TmpInst.addOperand(Inst.getOperand(4));
6198 TmpInst.addOperand(Inst.getOperand(5));
6199 Inst = TmpInst;
6200 return true;
6201 }
6202 return false;
6203 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006204 case ARM::t2IT: {
6205 // The mask bits for all but the first condition are represented as
6206 // the low bit of the condition code value implies 't'. We currently
6207 // always have 1 implies 't', so XOR toggle the bits if the low bit
6208 // of the condition code is zero. The encoding also expects the low
6209 // bit of the condition to be encoded as bit 4 of the mask operand,
6210 // so mask that in if needed
6211 MCOperand &MO = Inst.getOperand(1);
6212 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006213 unsigned OrigMask = Mask;
6214 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006215 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006216 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6217 for (unsigned i = 3; i != TZ; --i)
6218 Mask ^= 1 << i;
6219 } else
6220 Mask |= 0x10;
6221 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006222
6223 // Set up the IT block state according to the IT instruction we just
6224 // matched.
6225 assert(!inITBlock() && "nested IT blocks?!");
6226 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6227 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6228 ITState.CurPosition = 0;
6229 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006230 break;
6231 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006232 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006233 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006234}
6235
Jim Grosbach47a0d522011-08-16 20:45:50 +00006236unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6237 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6238 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006239 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006240 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006241 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6242 assert(MCID.hasOptionalDef() &&
6243 "optionally flag setting instruction missing optional def operand");
6244 assert(MCID.NumOperands == Inst.getNumOperands() &&
6245 "operand count mismatch!");
6246 // Find the optional-def operand (cc_out).
6247 unsigned OpNo;
6248 for (OpNo = 0;
6249 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6250 ++OpNo)
6251 ;
6252 // If we're parsing Thumb1, reject it completely.
6253 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6254 return Match_MnemonicFail;
6255 // If we're parsing Thumb2, which form is legal depends on whether we're
6256 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006257 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6258 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006259 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006260 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6261 inITBlock())
6262 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006263 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006264 // Some high-register supporting Thumb1 encodings only allow both registers
6265 // to be from r0-r7 when in Thumb2.
6266 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6267 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6268 isARMLowRegister(Inst.getOperand(2).getReg()))
6269 return Match_RequiresThumb2;
6270 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006271 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006272 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6273 isARMLowRegister(Inst.getOperand(1).getReg()))
6274 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006275 return Match_Success;
6276}
6277
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006278bool ARMAsmParser::
6279MatchAndEmitInstruction(SMLoc IDLoc,
6280 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6281 MCStreamer &Out) {
6282 MCInst Inst;
6283 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006284 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006285 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006286 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006287 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006288 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006289 // Context sensitive operand constraints aren't handled by the matcher,
6290 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006291 if (validateInstruction(Inst, Operands)) {
6292 // Still progress the IT block, otherwise one wrong condition causes
6293 // nasty cascading errors.
6294 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006295 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006296 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006297
Jim Grosbachf8fce712011-08-11 17:35:48 +00006298 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006299 // encoding is selected. Loop on it while changes happen so the
6300 // individual transformations can chain off each other. E.g.,
6301 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6302 while (processInstruction(Inst, Operands))
6303 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006304
Jim Grosbacha1109882011-09-02 23:22:08 +00006305 // Only move forward at the very end so that everything in validate
6306 // and process gets a consistent answer about whether we're in an IT
6307 // block.
6308 forwardITPosition();
6309
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006310 Out.EmitInstruction(Inst);
6311 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006312 case Match_MissingFeature:
6313 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6314 return true;
6315 case Match_InvalidOperand: {
6316 SMLoc ErrorLoc = IDLoc;
6317 if (ErrorInfo != ~0U) {
6318 if (ErrorInfo >= Operands.size())
6319 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006320
Chris Lattnere73d4f82010-10-28 21:41:58 +00006321 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6322 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6323 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006324
Chris Lattnere73d4f82010-10-28 21:41:58 +00006325 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006326 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006327 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006328 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006329 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006330 // The converter function will have already emited a diagnostic.
6331 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006332 case Match_RequiresNotITBlock:
6333 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006334 case Match_RequiresITBlock:
6335 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006336 case Match_RequiresV6:
6337 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6338 case Match_RequiresThumb2:
6339 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006340 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006341
Eric Christopherc223e2b2010-10-29 09:26:59 +00006342 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006343 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006344}
6345
Jim Grosbach1355cf12011-07-26 17:10:22 +00006346/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006347bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6348 StringRef IDVal = DirectiveID.getIdentifier();
6349 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006350 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006351 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006352 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006353 else if (IDVal == ".arm")
6354 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006355 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006356 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006357 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006358 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006359 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006360 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006361 else if (IDVal == ".unreq")
6362 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006363 else if (IDVal == ".arch")
6364 return parseDirectiveArch(DirectiveID.getLoc());
6365 else if (IDVal == ".eabi_attribute")
6366 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006367 return true;
6368}
6369
Jim Grosbach1355cf12011-07-26 17:10:22 +00006370/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006371/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006372bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006373 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6374 for (;;) {
6375 const MCExpr *Value;
6376 if (getParser().ParseExpression(Value))
6377 return true;
6378
Chris Lattneraaec2052010-01-19 19:46:13 +00006379 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006380
6381 if (getLexer().is(AsmToken::EndOfStatement))
6382 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006383
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006384 // FIXME: Improve diagnostic.
6385 if (getLexer().isNot(AsmToken::Comma))
6386 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006387 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006388 }
6389 }
6390
Sean Callananb9a25b72010-01-19 20:27:46 +00006391 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006392 return false;
6393}
6394
Jim Grosbach1355cf12011-07-26 17:10:22 +00006395/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006396/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006397bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006398 if (getLexer().isNot(AsmToken::EndOfStatement))
6399 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006400 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006401
Jim Grosbach9a70df92011-12-07 18:04:19 +00006402 if (!isThumb())
6403 SwitchMode();
6404 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6405 return false;
6406}
6407
6408/// parseDirectiveARM
6409/// ::= .arm
6410bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6411 if (getLexer().isNot(AsmToken::EndOfStatement))
6412 return Error(L, "unexpected token in directive");
6413 Parser.Lex();
6414
6415 if (isThumb())
6416 SwitchMode();
6417 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006418 return false;
6419}
6420
Jim Grosbach1355cf12011-07-26 17:10:22 +00006421/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006422/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006423bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006424 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6425 bool isMachO = MAI.hasSubsectionsViaSymbols();
6426 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006427 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006428
Jim Grosbachde4d8392011-12-21 22:30:16 +00006429 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006430 // ELF doesn't
6431 if (isMachO) {
6432 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006433 if (Tok.isNot(AsmToken::EndOfStatement)) {
6434 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6435 return Error(L, "unexpected token in .thumb_func directive");
6436 Name = Tok.getIdentifier();
6437 Parser.Lex(); // Consume the identifier token.
6438 needFuncName = false;
6439 }
Rafael Espindola64695402011-05-16 16:17:21 +00006440 }
6441
Jim Grosbachde4d8392011-12-21 22:30:16 +00006442 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006443 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006444
6445 // Eat the end of statement and any blank lines that follow.
6446 while (getLexer().is(AsmToken::EndOfStatement))
6447 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006448
Rafael Espindola64695402011-05-16 16:17:21 +00006449 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006450 // We really should be checking the next symbol definition even if there's
6451 // stuff in between.
6452 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006453 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006454 }
6455
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006456 // Mark symbol as a thumb symbol.
6457 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6458 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006459 return false;
6460}
6461
Jim Grosbach1355cf12011-07-26 17:10:22 +00006462/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006463/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006464bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006465 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006466 if (Tok.isNot(AsmToken::Identifier))
6467 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006468 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006469 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006470 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006471 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006472 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006473 else
6474 return Error(L, "unrecognized syntax mode in .syntax directive");
6475
6476 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006477 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006478 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006479
6480 // TODO tell the MC streamer the mode
6481 // getParser().getStreamer().Emit???();
6482 return false;
6483}
6484
Jim Grosbach1355cf12011-07-26 17:10:22 +00006485/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006486/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006487bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006488 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006489 if (Tok.isNot(AsmToken::Integer))
6490 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006491 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006492 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006493 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006494 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006495 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006496 else
6497 return Error(L, "invalid operand to .code directive");
6498
6499 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006500 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006501 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006502
Evan Cheng32869202011-07-08 22:36:29 +00006503 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006504 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006505 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006506 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006507 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006508 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006509 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006510 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006511 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006512
Kevin Enderby515d5092009-10-15 20:48:48 +00006513 return false;
6514}
6515
Jim Grosbacha39cda72011-12-14 02:16:11 +00006516/// parseDirectiveReq
6517/// ::= name .req registername
6518bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6519 Parser.Lex(); // Eat the '.req' token.
6520 unsigned Reg;
6521 SMLoc SRegLoc, ERegLoc;
6522 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6523 Parser.EatToEndOfStatement();
6524 return Error(SRegLoc, "register name expected");
6525 }
6526
6527 // Shouldn't be anything else.
6528 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6529 Parser.EatToEndOfStatement();
6530 return Error(Parser.getTok().getLoc(),
6531 "unexpected input in .req directive.");
6532 }
6533
6534 Parser.Lex(); // Consume the EndOfStatement
6535
6536 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6537 return Error(SRegLoc, "redefinition of '" + Name +
6538 "' does not match original.");
6539
6540 return false;
6541}
6542
6543/// parseDirectiveUneq
6544/// ::= .unreq registername
6545bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6546 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6547 Parser.EatToEndOfStatement();
6548 return Error(L, "unexpected input in .unreq directive.");
6549 }
6550 RegisterReqs.erase(Parser.getTok().getIdentifier());
6551 Parser.Lex(); // Eat the identifier.
6552 return false;
6553}
6554
Jason W Kimd7c9e082011-12-20 17:38:12 +00006555/// parseDirectiveArch
6556/// ::= .arch token
6557bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6558 return true;
6559}
6560
6561/// parseDirectiveEabiAttr
6562/// ::= .eabi_attribute int, int
6563bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6564 return true;
6565}
6566
Sean Callanan90b70972010-04-07 20:29:34 +00006567extern "C" void LLVMInitializeARMAsmLexer();
6568
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006569/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006570extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006571 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6572 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006573 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006574}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006575
Chris Lattner0692ee62010-09-06 19:11:01 +00006576#define GET_REGISTER_MATCHER
6577#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006578#include "ARMGenAsmMatcher.inc"