blob: ab954bea258639e140e1ee337a047eda76b4ea87 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan76264762010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbach862019c2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendling8155e5b2010-11-06 22:19:43 +0000344 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000351
Jim Grosbach9d390362011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000400
Bill Wendling146018f2010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan76264762010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000425 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan76264762010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000479
Sean Callanan76264762010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Daniel Dunbar8462b302010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503 }
504
Bill Wendling5fa22a12010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000509 }
510
Kevin Enderbycfe07242009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000512 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbach9d390362011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbach460a9052011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000550 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
557 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000558 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
565 }
566 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
573 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000574 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 256;
581 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000582 bool isImm0_1() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 2;
589 }
590 bool isImm0_3() const {
591 if (Kind != k_Immediate)
592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 4;
597 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000598 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 16;
613 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000614 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 32;
621 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 bool isImm0_63() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value >= 0 && Value < 64;
629 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000630 bool isImm8() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value == 16;
645 }
646 bool isImm32() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value == 32;
653 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000654 bool isShrImm8() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 8;
661 }
662 bool isShrImm16() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value <= 16;
669 }
670 bool isShrImm32() const {
671 if (Kind != k_Immediate)
672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value <= 32;
677 }
678 bool isShrImm64() const {
679 if (Kind != k_Immediate)
680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value > 0 && Value <= 64;
685 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000686 bool isImm1_7() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 8;
693 }
694 bool isImm1_15() const {
695 if (Kind != k_Immediate)
696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value > 0 && Value < 16;
701 }
702 bool isImm1_31() const {
703 if (Kind != k_Immediate)
704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value < 32;
709 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000710 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000712 return false;
713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 17;
717 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000718 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000720 return false;
721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
722 if (!CE) return false;
723 int64_t Value = CE->getValue();
724 return Value > 0 && Value < 33;
725 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000726 bool isImm0_32() const {
727 if (Kind != k_Immediate)
728 return false;
729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 33;
733 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000734 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 if (!CE) return false;
739 int64_t Value = CE->getValue();
740 return Value >= 0 && Value < 65536;
741 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000742 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000743 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000744 return false;
745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
746 // If it's not a constant expression, it'll generate a fixup and be
747 // handled later.
748 if (!CE) return true;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 65536;
751 }
Jim Grosbached838482011-07-26 16:24:27 +0000752 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return Value >= 0 && Value <= 0xffffff;
759 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000760 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return Value > 0 && Value < 33;
767 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000768 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value >= 0 && Value < 32;
775 }
776 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return Value > 0 && Value <= 32;
783 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000784 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000785 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getSOImmVal(Value) != -1;
791 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000792 bool isARMSOImmNot() const {
793 if (Kind != k_Immediate)
794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return ARM_AM::getSOImmVal(~Value) != -1;
799 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000800 bool isARMSOImmNeg() const {
801 if (Kind != k_Immediate)
802 return false;
803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getSOImmVal(-Value) != -1;
807 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000808 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000809 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000810 return false;
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 int64_t Value = CE->getValue();
814 return ARM_AM::getT2SOImmVal(Value) != -1;
815 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000816 bool isT2SOImmNot() const {
817 if (Kind != k_Immediate)
818 return false;
819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
820 if (!CE) return false;
821 int64_t Value = CE->getValue();
822 return ARM_AM::getT2SOImmVal(~Value) != -1;
823 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000824 bool isT2SOImmNeg() const {
825 if (Kind != k_Immediate)
826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return ARM_AM::getT2SOImmVal(-Value) != -1;
831 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000832 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000833 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000834 return false;
835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
838 return Value == 1 || Value == 0;
839 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000840 bool isReg() const { return Kind == k_Register; }
841 bool isRegList() const { return Kind == k_RegisterList; }
842 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
843 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
844 bool isToken() const { return Kind == k_Token; }
845 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
846 bool isMemory() const { return Kind == k_Memory; }
847 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
848 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
849 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
850 bool isRotImm() const { return Kind == k_RotateImmediate; }
851 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
852 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000853 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000854 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000855 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000857 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000858 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
861 (alignOK || Memory.Alignment == 0);
862 }
863 bool isAlignedMemory() const {
864 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000867 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000869 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000873 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000874 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000875 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000876 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000877 return false;
878 // Immediate offset in range [-4095, 4095].
879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
880 if (!CE) return false;
881 int64_t Val = CE->getValue();
882 return Val > -4096 && Val < 4096;
883 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000884 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000885 // If we have an immediate that's not a constant, treat it as a label
886 // reference needing a fixup. If it is a constant, it's something else
887 // and we reject it.
888 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
889 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000893 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000894 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000895 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000896 if (!Memory.OffsetImm) return true;
897 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000898 return Val > -256 && Val < 256;
899 }
900 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000901 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000902 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000903 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000904 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
905 // Immediate offset in range [-255, 255].
906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000909 // Special case, #-0 is INT32_MIN.
910 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000911 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
917 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000918 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000919 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000920 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000924 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000925 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000926 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000927 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000929 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000930 return false;
931 return true;
932 }
933 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000935 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
936 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000937 return false;
938 return true;
939 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000942 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000943 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000944 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000945 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
947 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000948 return false;
949 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000950 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000951 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000953 return false;
954 return true;
955 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000956 bool isMemThumbRR() const {
957 // Thumb reg+reg addressing is simple. Just two registers, a base and
958 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000959 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000960 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000961 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 return isARMLowRegister(Memory.BaseRegNum) &&
963 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000964 }
965 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000966 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000967 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000968 return false;
969 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000970 if (!Memory.OffsetImm) return true;
971 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000972 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
973 }
Jim Grosbach38466302011-08-19 18:55:51 +0000974 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000976 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000977 return false;
978 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000979 if (!Memory.OffsetImm) return true;
980 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000981 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
982 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000983 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000985 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000986 return false;
987 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000988 if (!Memory.OffsetImm) return true;
989 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000990 return Val >= 0 && Val <= 31;
991 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000992 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000993 if (!isMemory() || Memory.OffsetRegNum != 0 ||
994 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000995 return false;
996 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000999 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001000 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001001 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001002 // If we have an immediate that's not a constant, treat it as a label
1003 // reference needing a fixup. If it is a constant, it's something else
1004 // and we reject it.
1005 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
1006 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001007 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001008 return false;
1009 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001010 if (!Memory.OffsetImm) return true;
1011 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001012 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1013 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001014 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001015 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001016 return false;
1017 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001018 if (!Memory.OffsetImm) return true;
1019 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001020 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1021 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001022 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001023 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001024 return false;
1025 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001026 if (!Memory.OffsetImm) return true;
1027 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001028 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001029 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001030 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001032 return false;
1033 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001036 return Val >= 0 && Val < 256;
1037 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001038 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001040 return false;
1041 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001042 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001044 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001045 }
1046 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001048 return false;
1049 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001050 if (!Memory.OffsetImm) return true;
1051 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001052 return (Val >= 0 && Val < 4096);
1053 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001054 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001055 // If we have an immediate that's not a constant, treat it as a label
1056 // reference needing a fixup. If it is a constant, it's something else
1057 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001058 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001059 return true;
1060
Jim Grosbach57dcb852011-10-11 17:29:55 +00001061 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001062 return false;
1063 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001064 if (!Memory.OffsetImm) return true;
1065 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001066 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001067 }
1068 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001070 return false;
1071 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1072 if (!CE) return false;
1073 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001074 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001075 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001076 bool isPostIdxImm8s4() const {
1077 if (Kind != k_Immediate)
1078 return false;
1079 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1080 if (!CE) return false;
1081 int64_t Val = CE->getValue();
1082 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1083 (Val == INT32_MIN);
1084 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001085
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001086 bool isMSRMask() const { return Kind == k_MSRMask; }
1087 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001088
Jim Grosbach0e387b22011-10-17 22:26:03 +00001089 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 bool isSingleSpacedVectorList() const {
1091 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1092 }
1093 bool isDoubleSpacedVectorList() const {
1094 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1095 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001096 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001098 return VectorList.Count == 1;
1099 }
1100
Jim Grosbach280dfad2011-10-21 18:54:25 +00001101 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001103 return VectorList.Count == 2;
1104 }
1105
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001106 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001107 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001108 return VectorList.Count == 3;
1109 }
1110
Jim Grosbachb6310312011-10-21 20:35:01 +00001111 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001112 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001113 return VectorList.Count == 4;
1114 }
1115
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001116 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001117 if (!isDoubleSpacedVectorList()) return false;
1118 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001119 }
1120
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001121 bool isSingleSpacedVectorAllLanes() const {
1122 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1123 }
1124 bool isDoubleSpacedVectorAllLanes() const {
1125 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1126 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001127 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001128 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001129 return VectorList.Count == 1;
1130 }
1131
Jim Grosbach13af2222011-11-30 18:21:25 +00001132 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001133 if (!isSingleSpacedVectorAllLanes()) return false;
1134 return VectorList.Count == 2;
1135 }
1136
1137 bool isVecListTwoQAllLanes() const {
1138 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001139 return VectorList.Count == 2;
1140 }
1141
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001142 bool isSingleSpacedVectorIndexed() const {
1143 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1144 }
1145 bool isDoubleSpacedVectorIndexed() const {
1146 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1147 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001148 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001149 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001150 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1151 }
1152
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001153 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001154 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001155 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1156 }
1157
1158 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001159 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001160 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1161 }
1162
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001163 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001164 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001165 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1166 }
1167
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001168 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001169 if (!isSingleSpacedVectorIndexed()) return false;
1170 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1171 }
1172
1173 bool isVecListTwoQWordIndexed() const {
1174 if (!isDoubleSpacedVectorIndexed()) return false;
1175 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1176 }
1177
1178 bool isVecListTwoQHWordIndexed() const {
1179 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001180 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1181 }
1182
1183 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001184 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001185 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1186 }
1187
Jim Grosbach460a9052011-10-07 23:56:00 +00001188 bool isVectorIndex8() const {
1189 if (Kind != k_VectorIndex) return false;
1190 return VectorIndex.Val < 8;
1191 }
1192 bool isVectorIndex16() const {
1193 if (Kind != k_VectorIndex) return false;
1194 return VectorIndex.Val < 4;
1195 }
1196 bool isVectorIndex32() const {
1197 if (Kind != k_VectorIndex) return false;
1198 return VectorIndex.Val < 2;
1199 }
1200
Jim Grosbach0e387b22011-10-17 22:26:03 +00001201 bool isNEONi8splat() const {
1202 if (Kind != k_Immediate)
1203 return false;
1204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1205 // Must be a constant.
1206 if (!CE) return false;
1207 int64_t Value = CE->getValue();
1208 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1209 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001210 return Value >= 0 && Value < 256;
1211 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001212
Jim Grosbachea461102011-10-17 23:09:09 +00001213 bool isNEONi16splat() const {
1214 if (Kind != k_Immediate)
1215 return false;
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 // Must be a constant.
1218 if (!CE) return false;
1219 int64_t Value = CE->getValue();
1220 // i16 value in the range [0,255] or [0x0100, 0xff00]
1221 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1222 }
1223
Jim Grosbach6248a542011-10-18 00:22:00 +00001224 bool isNEONi32splat() const {
1225 if (Kind != k_Immediate)
1226 return false;
1227 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1228 // Must be a constant.
1229 if (!CE) return false;
1230 int64_t Value = CE->getValue();
1231 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1232 return (Value >= 0 && Value < 256) ||
1233 (Value >= 0x0100 && Value <= 0xff00) ||
1234 (Value >= 0x010000 && Value <= 0xff0000) ||
1235 (Value >= 0x01000000 && Value <= 0xff000000);
1236 }
1237
1238 bool isNEONi32vmov() const {
1239 if (Kind != k_Immediate)
1240 return false;
1241 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1242 // Must be a constant.
1243 if (!CE) return false;
1244 int64_t Value = CE->getValue();
1245 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1246 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1247 return (Value >= 0 && Value < 256) ||
1248 (Value >= 0x0100 && Value <= 0xff00) ||
1249 (Value >= 0x010000 && Value <= 0xff0000) ||
1250 (Value >= 0x01000000 && Value <= 0xff000000) ||
1251 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1252 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1253 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001254 bool isNEONi32vmovNeg() const {
1255 if (Kind != k_Immediate)
1256 return false;
1257 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1258 // Must be a constant.
1259 if (!CE) return false;
1260 int64_t Value = ~CE->getValue();
1261 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1262 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1263 return (Value >= 0 && Value < 256) ||
1264 (Value >= 0x0100 && Value <= 0xff00) ||
1265 (Value >= 0x010000 && Value <= 0xff0000) ||
1266 (Value >= 0x01000000 && Value <= 0xff000000) ||
1267 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1268 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1269 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001270
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001271 bool isNEONi64splat() const {
1272 if (Kind != k_Immediate)
1273 return false;
1274 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1275 // Must be a constant.
1276 if (!CE) return false;
1277 uint64_t Value = CE->getValue();
1278 // i64 value with each byte being either 0 or 0xff.
1279 for (unsigned i = 0; i < 8; ++i)
1280 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1281 return true;
1282 }
1283
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001284 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001285 // Add as immediates when possible. Null MCExpr = 0.
1286 if (Expr == 0)
1287 Inst.addOperand(MCOperand::CreateImm(0));
1288 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001289 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1290 else
1291 Inst.addOperand(MCOperand::CreateExpr(Expr));
1292 }
1293
Daniel Dunbar8462b302010-08-11 06:36:53 +00001294 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001295 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001296 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001297 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1298 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001299 }
1300
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001301 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1302 assert(N == 1 && "Invalid number of operands!");
1303 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1304 }
1305
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001306 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
1308 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1309 }
1310
1311 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1312 assert(N == 1 && "Invalid number of operands!");
1313 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1314 }
1315
Jim Grosbach89df9962011-08-26 21:43:41 +00001316 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
1318 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1319 }
1320
1321 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
1323 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1324 }
1325
Jim Grosbachd67641b2010-12-06 18:21:12 +00001326 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1327 assert(N == 1 && "Invalid number of operands!");
1328 Inst.addOperand(MCOperand::CreateReg(getReg()));
1329 }
1330
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001331 void addRegOperands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
1333 Inst.addOperand(MCOperand::CreateReg(getReg()));
1334 }
1335
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001336 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001337 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001338 assert(isRegShiftedReg() &&
1339 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001340 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1341 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001342 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001343 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001344 }
1345
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001346 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001347 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001348 assert(isRegShiftedImm() &&
1349 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001350 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001351 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001352 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001353 }
1354
Jim Grosbach580f4a92011-07-25 22:20:28 +00001355 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001356 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001357 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1358 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001359 }
1360
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001361 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001362 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001363 const SmallVectorImpl<unsigned> &RegList = getRegList();
1364 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001365 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1366 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001367 }
1368
Bill Wendling0f630752010-11-17 04:32:08 +00001369 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1370 addRegListOperands(Inst, N);
1371 }
1372
1373 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1374 addRegListOperands(Inst, N);
1375 }
1376
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001377 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1380 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1381 }
1382
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001383 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 // Munge the lsb/width into a bitfield mask.
1386 unsigned lsb = Bitfield.LSB;
1387 unsigned width = Bitfield.Width;
1388 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1389 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1390 (32 - (lsb + width)));
1391 Inst.addOperand(MCOperand::CreateImm(Mask));
1392 }
1393
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001394 void addImmOperands(MCInst &Inst, unsigned N) const {
1395 assert(N == 1 && "Invalid number of operands!");
1396 addExpr(Inst, getImm());
1397 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001398
Jim Grosbach9d390362011-10-03 23:38:36 +00001399 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1402 }
1403
Jim Grosbacha77295d2011-09-08 22:07:06 +00001404 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 // FIXME: We really want to scale the value here, but the LDRD/STRD
1407 // instruction don't encode operands that way yet.
1408 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1409 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1410 }
1411
Jim Grosbach72f39f82011-08-24 21:22:15 +00001412 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 1 && "Invalid number of operands!");
1414 // The immediate is scaled by four in the encoding and is stored
1415 // in the MCInst as such. Lop off the low two bits here.
1416 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1417 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1418 }
1419
1420 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
1422 // The immediate is scaled by four in the encoding and is stored
1423 // in the MCInst as such. Lop off the low two bits here.
1424 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1425 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1426 }
1427
Jim Grosbachf4943352011-07-25 23:09:14 +00001428 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
1430 // The constant encodes as the immediate-1, and we store in the instruction
1431 // the bits as encoded, so subtract off one here.
1432 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1433 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1434 }
1435
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001436 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 // The constant encodes as the immediate-1, and we store in the instruction
1439 // the bits as encoded, so subtract off one here.
1440 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1441 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1442 }
1443
Jim Grosbach70939ee2011-08-17 21:51:27 +00001444 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 // The constant encodes as the immediate, except for 32, which encodes as
1447 // zero.
1448 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1449 unsigned Imm = CE->getValue();
1450 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1451 }
1452
Jim Grosbachf6c05252011-07-21 17:23:04 +00001453 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1456 // the instruction as well.
1457 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1458 int Val = CE->getValue();
1459 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1460 }
1461
Jim Grosbach89a63372011-10-28 22:36:30 +00001462 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 1 && "Invalid number of operands!");
1464 // The operand is actually a t2_so_imm, but we have its bitwise
1465 // negation in the assembly source, so twiddle it here.
1466 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1467 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1468 }
1469
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001470 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
1472 // The operand is actually a t2_so_imm, but we have its
1473 // negation in the assembly source, so twiddle it here.
1474 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1475 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1476 }
1477
Jim Grosbache70ec842011-10-28 22:50:54 +00001478 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 1 && "Invalid number of operands!");
1480 // The operand is actually a so_imm, but we have its bitwise
1481 // negation in the assembly source, so twiddle it here.
1482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1484 }
1485
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001486 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 // The operand is actually a so_imm, but we have its
1489 // negation in the assembly source, so twiddle it here.
1490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1491 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1492 }
1493
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001494 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1497 }
1498
Jim Grosbach7ce05792011-08-03 23:50:40 +00001499 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001501 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001502 }
1503
Jim Grosbach57dcb852011-10-11 17:29:55 +00001504 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
1506 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1507 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1508 }
1509
Jim Grosbach7ce05792011-08-03 23:50:40 +00001510 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001512 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1513 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001514 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1515 // Special case for #-0
1516 if (Val == INT32_MIN) Val = 0;
1517 if (Val < 0) Val = -Val;
1518 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1519 } else {
1520 // For register offset, we encode the shift type and negation flag
1521 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001522 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1523 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001524 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001525 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1526 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001527 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001528 }
1529
Jim Grosbach039c2e12011-08-04 23:01:30 +00001530 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
1532 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1533 assert(CE && "non-constant AM2OffsetImm operand!");
1534 int32_t Val = CE->getValue();
1535 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1536 // Special case for #-0
1537 if (Val == INT32_MIN) Val = 0;
1538 if (Val < 0) Val = -Val;
1539 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1540 Inst.addOperand(MCOperand::CreateReg(0));
1541 Inst.addOperand(MCOperand::CreateImm(Val));
1542 }
1543
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001544 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1545 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001546 // If we have an immediate that's not a constant, treat it as a label
1547 // reference needing a fixup. If it is a constant, it's something else
1548 // and we reject it.
1549 if (isImm()) {
1550 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1551 Inst.addOperand(MCOperand::CreateReg(0));
1552 Inst.addOperand(MCOperand::CreateImm(0));
1553 return;
1554 }
1555
Jim Grosbache53c87b2011-10-11 15:59:20 +00001556 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1557 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001558 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1559 // Special case for #-0
1560 if (Val == INT32_MIN) Val = 0;
1561 if (Val < 0) Val = -Val;
1562 Val = ARM_AM::getAM3Opc(AddSub, Val);
1563 } else {
1564 // For register offset, we encode the shift type and negation flag
1565 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001566 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001567 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001568 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1569 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001570 Inst.addOperand(MCOperand::CreateImm(Val));
1571 }
1572
1573 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001575 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001576 int32_t Val =
1577 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1578 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1579 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001580 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001581 }
1582
1583 // Constant offset.
1584 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1585 int32_t Val = CE->getValue();
1586 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1587 // Special case for #-0
1588 if (Val == INT32_MIN) Val = 0;
1589 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001590 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001591 Inst.addOperand(MCOperand::CreateReg(0));
1592 Inst.addOperand(MCOperand::CreateImm(Val));
1593 }
1594
Jim Grosbach7ce05792011-08-03 23:50:40 +00001595 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1596 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001597 // If we have an immediate that's not a constant, treat it as a label
1598 // reference needing a fixup. If it is a constant, it's something else
1599 // and we reject it.
1600 if (isImm()) {
1601 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1602 Inst.addOperand(MCOperand::CreateImm(0));
1603 return;
1604 }
1605
Jim Grosbach7ce05792011-08-03 23:50:40 +00001606 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001607 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001608 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1609 // Special case for #-0
1610 if (Val == INT32_MIN) Val = 0;
1611 if (Val < 0) Val = -Val;
1612 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001613 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001614 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001615 }
1616
Jim Grosbacha77295d2011-09-08 22:07:06 +00001617 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1618 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001619 // If we have an immediate that's not a constant, treat it as a label
1620 // reference needing a fixup. If it is a constant, it's something else
1621 // and we reject it.
1622 if (isImm()) {
1623 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1624 Inst.addOperand(MCOperand::CreateImm(0));
1625 return;
1626 }
1627
Jim Grosbache53c87b2011-10-11 15:59:20 +00001628 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001630 Inst.addOperand(MCOperand::CreateImm(Val));
1631 }
1632
Jim Grosbachb6aed502011-09-09 18:37:27 +00001633 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1634 assert(N == 2 && "Invalid number of operands!");
1635 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001636 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1637 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001638 Inst.addOperand(MCOperand::CreateImm(Val));
1639 }
1640
Jim Grosbach7ce05792011-08-03 23:50:40 +00001641 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1642 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001643 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1644 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001645 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001646 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001647
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001648 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1649 addMemImm8OffsetOperands(Inst, N);
1650 }
1651
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001652 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001653 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001654 }
1655
1656 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1657 assert(N == 2 && "Invalid number of operands!");
1658 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001659 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001660 addExpr(Inst, getImm());
1661 Inst.addOperand(MCOperand::CreateImm(0));
1662 return;
1663 }
1664
1665 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001666 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1667 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001668 Inst.addOperand(MCOperand::CreateImm(Val));
1669 }
1670
Jim Grosbach7ce05792011-08-03 23:50:40 +00001671 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1672 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001673 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001674 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001675 addExpr(Inst, getImm());
1676 Inst.addOperand(MCOperand::CreateImm(0));
1677 return;
1678 }
1679
1680 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001681 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1682 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001683 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001684 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001685
Jim Grosbach7f739be2011-09-19 22:21:13 +00001686 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1687 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001688 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1689 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001690 }
1691
1692 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001694 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1695 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001696 }
1697
Jim Grosbach7ce05792011-08-03 23:50:40 +00001698 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1699 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001700 unsigned Val =
1701 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1702 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001703 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1704 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001705 Inst.addOperand(MCOperand::CreateImm(Val));
1706 }
1707
Jim Grosbachab899c12011-09-07 23:10:15 +00001708 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1709 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001710 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1711 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1712 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001713 }
1714
Jim Grosbach7ce05792011-08-03 23:50:40 +00001715 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001717 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1718 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001719 }
1720
Jim Grosbach60f91a32011-08-19 17:55:24 +00001721 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1722 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001723 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1724 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001725 Inst.addOperand(MCOperand::CreateImm(Val));
1726 }
1727
Jim Grosbach38466302011-08-19 18:55:51 +00001728 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1729 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001730 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1731 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001732 Inst.addOperand(MCOperand::CreateImm(Val));
1733 }
1734
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001735 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1736 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001737 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1738 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001739 Inst.addOperand(MCOperand::CreateImm(Val));
1740 }
1741
Jim Grosbachecd85892011-08-19 18:13:48 +00001742 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1743 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001744 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1745 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001746 Inst.addOperand(MCOperand::CreateImm(Val));
1747 }
1748
Jim Grosbach7ce05792011-08-03 23:50:40 +00001749 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1752 assert(CE && "non-constant post-idx-imm8 operand!");
1753 int Imm = CE->getValue();
1754 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001755 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001756 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1757 Inst.addOperand(MCOperand::CreateImm(Imm));
1758 }
1759
Jim Grosbach2bd01182011-10-11 21:55:36 +00001760 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1761 assert(N == 1 && "Invalid number of operands!");
1762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1763 assert(CE && "non-constant post-idx-imm8s4 operand!");
1764 int Imm = CE->getValue();
1765 bool isAdd = Imm >= 0;
1766 if (Imm == INT32_MIN) Imm = 0;
1767 // Immediate is scaled by 4.
1768 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1769 Inst.addOperand(MCOperand::CreateImm(Imm));
1770 }
1771
Jim Grosbach7ce05792011-08-03 23:50:40 +00001772 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1773 assert(N == 2 && "Invalid number of operands!");
1774 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001775 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1776 }
1777
1778 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1779 assert(N == 2 && "Invalid number of operands!");
1780 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1781 // The sign, shift type, and shift amount are encoded in a single operand
1782 // using the AM2 encoding helpers.
1783 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1784 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1785 PostIdxReg.ShiftTy);
1786 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001787 }
1788
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001789 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1790 assert(N == 1 && "Invalid number of operands!");
1791 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1792 }
1793
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001794 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 1 && "Invalid number of operands!");
1796 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1797 }
1798
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001799 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001800 assert(N == 1 && "Invalid number of operands!");
1801 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1802 }
1803
Jim Grosbach7636bf62011-12-02 00:35:16 +00001804 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1805 assert(N == 2 && "Invalid number of operands!");
1806 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1807 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1808 }
1809
Jim Grosbach460a9052011-10-07 23:56:00 +00001810 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1811 assert(N == 1 && "Invalid number of operands!");
1812 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1813 }
1814
1815 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1816 assert(N == 1 && "Invalid number of operands!");
1817 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1818 }
1819
1820 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1821 assert(N == 1 && "Invalid number of operands!");
1822 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1823 }
1824
Jim Grosbach0e387b22011-10-17 22:26:03 +00001825 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1826 assert(N == 1 && "Invalid number of operands!");
1827 // The immediate encodes the type of constant as well as the value.
1828 // Mask in that this is an i8 splat.
1829 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1830 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1831 }
1832
Jim Grosbachea461102011-10-17 23:09:09 +00001833 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1834 assert(N == 1 && "Invalid number of operands!");
1835 // The immediate encodes the type of constant as well as the value.
1836 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1837 unsigned Value = CE->getValue();
1838 if (Value >= 256)
1839 Value = (Value >> 8) | 0xa00;
1840 else
1841 Value |= 0x800;
1842 Inst.addOperand(MCOperand::CreateImm(Value));
1843 }
1844
Jim Grosbach6248a542011-10-18 00:22:00 +00001845 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1846 assert(N == 1 && "Invalid number of operands!");
1847 // The immediate encodes the type of constant as well as the value.
1848 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1849 unsigned Value = CE->getValue();
1850 if (Value >= 256 && Value <= 0xff00)
1851 Value = (Value >> 8) | 0x200;
1852 else if (Value > 0xffff && Value <= 0xff0000)
1853 Value = (Value >> 16) | 0x400;
1854 else if (Value > 0xffffff)
1855 Value = (Value >> 24) | 0x600;
1856 Inst.addOperand(MCOperand::CreateImm(Value));
1857 }
1858
1859 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1860 assert(N == 1 && "Invalid number of operands!");
1861 // The immediate encodes the type of constant as well as the value.
1862 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1863 unsigned Value = CE->getValue();
1864 if (Value >= 256 && Value <= 0xffff)
1865 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1866 else if (Value > 0xffff && Value <= 0xffffff)
1867 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1868 else if (Value > 0xffffff)
1869 Value = (Value >> 24) | 0x600;
1870 Inst.addOperand(MCOperand::CreateImm(Value));
1871 }
1872
Jim Grosbach9b087852011-12-19 23:51:07 +00001873 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1874 assert(N == 1 && "Invalid number of operands!");
1875 // The immediate encodes the type of constant as well as the value.
1876 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1877 unsigned Value = ~CE->getValue();
1878 if (Value >= 256 && Value <= 0xffff)
1879 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1880 else if (Value > 0xffff && Value <= 0xffffff)
1881 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1882 else if (Value > 0xffffff)
1883 Value = (Value >> 24) | 0x600;
1884 Inst.addOperand(MCOperand::CreateImm(Value));
1885 }
1886
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001887 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1888 assert(N == 1 && "Invalid number of operands!");
1889 // The immediate encodes the type of constant as well as the value.
1890 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1891 uint64_t Value = CE->getValue();
1892 unsigned Imm = 0;
1893 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1894 Imm |= (Value & 1) << i;
1895 }
1896 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1897 }
1898
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001899 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001900
Jim Grosbach89df9962011-08-26 21:43:41 +00001901 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001902 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001903 Op->ITMask.Mask = Mask;
1904 Op->StartLoc = S;
1905 Op->EndLoc = S;
1906 return Op;
1907 }
1908
Chris Lattner3a697562010-10-28 17:20:03 +00001909 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001911 Op->CC.Val = CC;
1912 Op->StartLoc = S;
1913 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001914 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001915 }
1916
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001917 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001919 Op->Cop.Val = CopVal;
1920 Op->StartLoc = S;
1921 Op->EndLoc = S;
1922 return Op;
1923 }
1924
1925 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001927 Op->Cop.Val = CopVal;
1928 Op->StartLoc = S;
1929 Op->EndLoc = S;
1930 return Op;
1931 }
1932
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001933 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1934 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1935 Op->Cop.Val = Val;
1936 Op->StartLoc = S;
1937 Op->EndLoc = E;
1938 return Op;
1939 }
1940
Jim Grosbachd67641b2010-12-06 18:21:12 +00001941 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001942 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001943 Op->Reg.RegNum = RegNum;
1944 Op->StartLoc = S;
1945 Op->EndLoc = S;
1946 return Op;
1947 }
1948
Chris Lattner3a697562010-10-28 17:20:03 +00001949 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001950 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001951 Op->Tok.Data = Str.data();
1952 Op->Tok.Length = Str.size();
1953 Op->StartLoc = S;
1954 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001955 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001956 }
1957
Bill Wendling50d0f582010-11-18 23:43:05 +00001958 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001960 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001961 Op->StartLoc = S;
1962 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001963 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001964 }
1965
Jim Grosbache8606dc2011-07-13 17:50:29 +00001966 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1967 unsigned SrcReg,
1968 unsigned ShiftReg,
1969 unsigned ShiftImm,
1970 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001971 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001972 Op->RegShiftedReg.ShiftTy = ShTy;
1973 Op->RegShiftedReg.SrcReg = SrcReg;
1974 Op->RegShiftedReg.ShiftReg = ShiftReg;
1975 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001976 Op->StartLoc = S;
1977 Op->EndLoc = E;
1978 return Op;
1979 }
1980
Owen Anderson92a20222011-07-21 18:54:16 +00001981 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1982 unsigned SrcReg,
1983 unsigned ShiftImm,
1984 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001986 Op->RegShiftedImm.ShiftTy = ShTy;
1987 Op->RegShiftedImm.SrcReg = SrcReg;
1988 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001989 Op->StartLoc = S;
1990 Op->EndLoc = E;
1991 return Op;
1992 }
1993
Jim Grosbach580f4a92011-07-25 22:20:28 +00001994 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001995 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001996 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001997 Op->ShifterImm.isASR = isASR;
1998 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001999 Op->StartLoc = S;
2000 Op->EndLoc = E;
2001 return Op;
2002 }
2003
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002004 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002005 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002006 Op->RotImm.Imm = Imm;
2007 Op->StartLoc = S;
2008 Op->EndLoc = E;
2009 return Op;
2010 }
2011
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002012 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2013 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002014 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002015 Op->Bitfield.LSB = LSB;
2016 Op->Bitfield.Width = Width;
2017 Op->StartLoc = S;
2018 Op->EndLoc = E;
2019 return Op;
2020 }
2021
Bill Wendling7729e062010-11-09 22:44:22 +00002022 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002023 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002024 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002025 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002026
Jim Grosbachd300b942011-09-13 22:56:44 +00002027 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002028 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002029 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002030 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002031 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002032
2033 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002034 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002035 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002036 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002037 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002038 Op->StartLoc = StartLoc;
2039 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002040 return Op;
2041 }
2042
Jim Grosbach862019c2011-10-18 23:02:30 +00002043 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002044 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002045 ARMOperand *Op = new ARMOperand(k_VectorList);
2046 Op->VectorList.RegNum = RegNum;
2047 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002048 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002049 Op->StartLoc = S;
2050 Op->EndLoc = E;
2051 return Op;
2052 }
2053
Jim Grosbach98b05a52011-11-30 01:09:44 +00002054 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002055 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002056 SMLoc S, SMLoc E) {
2057 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2058 Op->VectorList.RegNum = RegNum;
2059 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002060 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002061 Op->StartLoc = S;
2062 Op->EndLoc = E;
2063 return Op;
2064 }
2065
Jim Grosbach7636bf62011-12-02 00:35:16 +00002066 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002067 unsigned Index,
2068 bool isDoubleSpaced,
2069 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002070 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2071 Op->VectorList.RegNum = RegNum;
2072 Op->VectorList.Count = Count;
2073 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002074 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002075 Op->StartLoc = S;
2076 Op->EndLoc = E;
2077 return Op;
2078 }
2079
Jim Grosbach460a9052011-10-07 23:56:00 +00002080 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2081 MCContext &Ctx) {
2082 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2083 Op->VectorIndex.Val = Idx;
2084 Op->StartLoc = S;
2085 Op->EndLoc = E;
2086 return Op;
2087 }
2088
Chris Lattner3a697562010-10-28 17:20:03 +00002089 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002090 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002091 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002092 Op->StartLoc = S;
2093 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002094 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002095 }
2096
Jim Grosbach9d390362011-10-03 23:38:36 +00002097 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002098 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002099 Op->FPImm.Val = Val;
2100 Op->StartLoc = S;
2101 Op->EndLoc = S;
2102 return Op;
2103 }
2104
Jim Grosbach7ce05792011-08-03 23:50:40 +00002105 static ARMOperand *CreateMem(unsigned BaseRegNum,
2106 const MCConstantExpr *OffsetImm,
2107 unsigned OffsetRegNum,
2108 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002109 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002110 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002111 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002112 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002113 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002114 Op->Memory.BaseRegNum = BaseRegNum;
2115 Op->Memory.OffsetImm = OffsetImm;
2116 Op->Memory.OffsetRegNum = OffsetRegNum;
2117 Op->Memory.ShiftType = ShiftType;
2118 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002119 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002120 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002121 Op->StartLoc = S;
2122 Op->EndLoc = E;
2123 return Op;
2124 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002125
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002126 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2127 ARM_AM::ShiftOpc ShiftTy,
2128 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002129 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002130 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002131 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002132 Op->PostIdxReg.isAdd = isAdd;
2133 Op->PostIdxReg.ShiftTy = ShiftTy;
2134 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002135 Op->StartLoc = S;
2136 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002137 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002138 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002139
2140 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002141 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002142 Op->MBOpt.Val = Opt;
2143 Op->StartLoc = S;
2144 Op->EndLoc = S;
2145 return Op;
2146 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002147
2148 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002149 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002150 Op->IFlags.Val = IFlags;
2151 Op->StartLoc = S;
2152 Op->EndLoc = S;
2153 return Op;
2154 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002155
2156 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002157 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002158 Op->MMask.Val = MMask;
2159 Op->StartLoc = S;
2160 Op->EndLoc = S;
2161 return Op;
2162 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002163};
2164
2165} // end anonymous namespace.
2166
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002167void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002168 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002169 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002170 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2171 << ") >";
2172 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002173 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002174 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002175 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002176 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002177 OS << "<ccout " << getReg() << ">";
2178 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002179 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002180 static const char *MaskStr[] = {
2181 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2182 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2183 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002184 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2185 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2186 break;
2187 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002188 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002189 OS << "<coprocessor number: " << getCoproc() << ">";
2190 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002191 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002192 OS << "<coprocessor register: " << getCoproc() << ">";
2193 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002194 case k_CoprocOption:
2195 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2196 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002197 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002198 OS << "<mask: " << getMSRMask() << ">";
2199 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002200 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002201 getImm()->print(OS);
2202 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002203 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002204 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2205 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002206 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002207 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002208 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002209 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002210 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002211 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002212 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2213 << PostIdxReg.RegNum;
2214 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2215 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2216 << PostIdxReg.ShiftImm;
2217 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002218 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002219 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002220 OS << "<ARM_PROC::";
2221 unsigned IFlags = getProcIFlags();
2222 for (int i=2; i >= 0; --i)
2223 if (IFlags & (1 << i))
2224 OS << ARM_PROC::IFlagsToString(1 << i);
2225 OS << ">";
2226 break;
2227 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002229 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002230 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002231 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002232 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2233 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002234 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002235 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002236 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002237 << RegShiftedReg.SrcReg << " "
2238 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2239 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002240 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002241 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002242 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002243 << RegShiftedImm.SrcReg << " "
2244 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2245 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002246 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002247 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002248 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2249 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002250 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002251 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2252 << ", width: " << Bitfield.Width << ">";
2253 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002254 case k_RegisterList:
2255 case k_DPRRegisterList:
2256 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002257 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002258
Bill Wendling5fa22a12010-11-09 23:28:44 +00002259 const SmallVectorImpl<unsigned> &RegList = getRegList();
2260 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002261 I = RegList.begin(), E = RegList.end(); I != E; ) {
2262 OS << *I;
2263 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002264 }
2265
2266 OS << ">";
2267 break;
2268 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002269 case k_VectorList:
2270 OS << "<vector_list " << VectorList.Count << " * "
2271 << VectorList.RegNum << ">";
2272 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002273 case k_VectorListAllLanes:
2274 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2275 << VectorList.RegNum << ">";
2276 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002277 case k_VectorListIndexed:
2278 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2279 << VectorList.Count << " * " << VectorList.RegNum << ">";
2280 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002281 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002282 OS << "'" << getToken() << "'";
2283 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002284 case k_VectorIndex:
2285 OS << "<vectorindex " << getVectorIndex() << ">";
2286 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002287 }
2288}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002289
2290/// @name Auto-generated Match Functions
2291/// {
2292
2293static unsigned MatchRegisterName(StringRef Name);
2294
2295/// }
2296
Bob Wilson69df7232011-02-03 21:46:10 +00002297bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2298 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002299 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002300 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002301 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002302
2303 return (RegNo == (unsigned)-1);
2304}
2305
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002306/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002307/// and if it is a register name the token is eaten and the register number is
2308/// returned. Otherwise return -1.
2309///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002310int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002311 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002312 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002313
Benjamin Kramer59085362011-11-06 20:37:06 +00002314 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002315 unsigned RegNum = MatchRegisterName(lowerCase);
2316 if (!RegNum) {
2317 RegNum = StringSwitch<unsigned>(lowerCase)
2318 .Case("r13", ARM::SP)
2319 .Case("r14", ARM::LR)
2320 .Case("r15", ARM::PC)
2321 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002322 // Additional register name aliases for 'gas' compatibility.
2323 .Case("a1", ARM::R0)
2324 .Case("a2", ARM::R1)
2325 .Case("a3", ARM::R2)
2326 .Case("a4", ARM::R3)
2327 .Case("v1", ARM::R4)
2328 .Case("v2", ARM::R5)
2329 .Case("v3", ARM::R6)
2330 .Case("v4", ARM::R7)
2331 .Case("v5", ARM::R8)
2332 .Case("v6", ARM::R9)
2333 .Case("v7", ARM::R10)
2334 .Case("v8", ARM::R11)
2335 .Case("sb", ARM::R9)
2336 .Case("sl", ARM::R10)
2337 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002338 .Default(0);
2339 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002340 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002341 // Check for aliases registered via .req. Canonicalize to lower case.
2342 // That's more consistent since register names are case insensitive, and
2343 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2344 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002345 // If no match, return failure.
2346 if (Entry == RegisterReqs.end())
2347 return -1;
2348 Parser.Lex(); // Eat identifier token.
2349 return Entry->getValue();
2350 }
Bob Wilson69df7232011-02-03 21:46:10 +00002351
Chris Lattnere5658fa2010-10-30 04:09:10 +00002352 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002353
Chris Lattnere5658fa2010-10-30 04:09:10 +00002354 return RegNum;
2355}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002356
Jim Grosbach19906722011-07-13 18:49:30 +00002357// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2358// If a recoverable error occurs, return 1. If an irrecoverable error
2359// occurs, return -1. An irrecoverable error is one where tokens have been
2360// consumed in the process of trying to parse the shifter (i.e., when it is
2361// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002362int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002363 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2364 SMLoc S = Parser.getTok().getLoc();
2365 const AsmToken &Tok = Parser.getTok();
2366 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2367
Benjamin Kramer59085362011-11-06 20:37:06 +00002368 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002369 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002370 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002371 .Case("lsl", ARM_AM::lsl)
2372 .Case("lsr", ARM_AM::lsr)
2373 .Case("asr", ARM_AM::asr)
2374 .Case("ror", ARM_AM::ror)
2375 .Case("rrx", ARM_AM::rrx)
2376 .Default(ARM_AM::no_shift);
2377
2378 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002379 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002380
Jim Grosbache8606dc2011-07-13 17:50:29 +00002381 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002382
Jim Grosbache8606dc2011-07-13 17:50:29 +00002383 // The source register for the shift has already been added to the
2384 // operand list, so we need to pop it off and combine it into the shifted
2385 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002386 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002387 if (!PrevOp->isReg())
2388 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2389 int SrcReg = PrevOp->getReg();
2390 int64_t Imm = 0;
2391 int ShiftReg = 0;
2392 if (ShiftTy == ARM_AM::rrx) {
2393 // RRX Doesn't have an explicit shift amount. The encoder expects
2394 // the shift register to be the same as the source register. Seems odd,
2395 // but OK.
2396 ShiftReg = SrcReg;
2397 } else {
2398 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002399 if (Parser.getTok().is(AsmToken::Hash) ||
2400 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002401 Parser.Lex(); // Eat hash.
2402 SMLoc ImmLoc = Parser.getTok().getLoc();
2403 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002404 if (getParser().ParseExpression(ShiftExpr)) {
2405 Error(ImmLoc, "invalid immediate shift value");
2406 return -1;
2407 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002408 // The expression must be evaluatable as an immediate.
2409 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002410 if (!CE) {
2411 Error(ImmLoc, "invalid immediate shift value");
2412 return -1;
2413 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002414 // Range check the immediate.
2415 // lsl, ror: 0 <= imm <= 31
2416 // lsr, asr: 0 <= imm <= 32
2417 Imm = CE->getValue();
2418 if (Imm < 0 ||
2419 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2420 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002421 Error(ImmLoc, "immediate shift value out of range");
2422 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002423 }
2424 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002425 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002426 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002427 if (ShiftReg == -1) {
2428 Error (L, "expected immediate or register in shift operand");
2429 return -1;
2430 }
2431 } else {
2432 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002433 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002434 return -1;
2435 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002436 }
2437
Owen Anderson92a20222011-07-21 18:54:16 +00002438 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2439 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002440 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002441 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002442 else
2443 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2444 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002445
Jim Grosbach19906722011-07-13 18:49:30 +00002446 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002447}
2448
2449
Bill Wendling50d0f582010-11-18 23:43:05 +00002450/// Try to parse a register name. The token must be an Identifier when called.
2451/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2452/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002453///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002454/// TODO this is likely to change to allow different register types and or to
2455/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002456bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002457tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002458 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002459 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002460 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002461 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002462
Bill Wendling50d0f582010-11-18 23:43:05 +00002463 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002464
Chris Lattnere5658fa2010-10-30 04:09:10 +00002465 const AsmToken &ExclaimTok = Parser.getTok();
2466 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002467 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2468 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002469 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002470 return false;
2471 }
2472
2473 // Also check for an index operand. This is only legal for vector registers,
2474 // but that'll get caught OK in operand matching, so we don't need to
2475 // explicitly filter everything else out here.
2476 if (Parser.getTok().is(AsmToken::LBrac)) {
2477 SMLoc SIdx = Parser.getTok().getLoc();
2478 Parser.Lex(); // Eat left bracket token.
2479
2480 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002481 if (getParser().ParseExpression(ImmVal))
2482 return MatchOperand_ParseFail;
2483 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2484 if (!MCE) {
2485 TokError("immediate value expected for vector index");
2486 return MatchOperand_ParseFail;
2487 }
2488
2489 SMLoc E = Parser.getTok().getLoc();
2490 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2491 Error(E, "']' expected");
2492 return MatchOperand_ParseFail;
2493 }
2494
2495 Parser.Lex(); // Eat right bracket token.
2496
2497 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2498 SIdx, E,
2499 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002500 }
2501
Bill Wendling50d0f582010-11-18 23:43:05 +00002502 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002503}
2504
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002505/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2506/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2507/// "c5", ...
2508static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002509 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2510 // but efficient.
2511 switch (Name.size()) {
2512 default: break;
2513 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002514 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002515 return -1;
2516 switch (Name[1]) {
2517 default: return -1;
2518 case '0': return 0;
2519 case '1': return 1;
2520 case '2': return 2;
2521 case '3': return 3;
2522 case '4': return 4;
2523 case '5': return 5;
2524 case '6': return 6;
2525 case '7': return 7;
2526 case '8': return 8;
2527 case '9': return 9;
2528 }
2529 break;
2530 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002531 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002532 return -1;
2533 switch (Name[2]) {
2534 default: return -1;
2535 case '0': return 10;
2536 case '1': return 11;
2537 case '2': return 12;
2538 case '3': return 13;
2539 case '4': return 14;
2540 case '5': return 15;
2541 }
2542 break;
2543 }
2544
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002545 return -1;
2546}
2547
Jim Grosbach89df9962011-08-26 21:43:41 +00002548/// parseITCondCode - Try to parse a condition code for an IT instruction.
2549ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2550parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2551 SMLoc S = Parser.getTok().getLoc();
2552 const AsmToken &Tok = Parser.getTok();
2553 if (!Tok.is(AsmToken::Identifier))
2554 return MatchOperand_NoMatch;
2555 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2556 .Case("eq", ARMCC::EQ)
2557 .Case("ne", ARMCC::NE)
2558 .Case("hs", ARMCC::HS)
2559 .Case("cs", ARMCC::HS)
2560 .Case("lo", ARMCC::LO)
2561 .Case("cc", ARMCC::LO)
2562 .Case("mi", ARMCC::MI)
2563 .Case("pl", ARMCC::PL)
2564 .Case("vs", ARMCC::VS)
2565 .Case("vc", ARMCC::VC)
2566 .Case("hi", ARMCC::HI)
2567 .Case("ls", ARMCC::LS)
2568 .Case("ge", ARMCC::GE)
2569 .Case("lt", ARMCC::LT)
2570 .Case("gt", ARMCC::GT)
2571 .Case("le", ARMCC::LE)
2572 .Case("al", ARMCC::AL)
2573 .Default(~0U);
2574 if (CC == ~0U)
2575 return MatchOperand_NoMatch;
2576 Parser.Lex(); // Eat the token.
2577
2578 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2579
2580 return MatchOperand_Success;
2581}
2582
Jim Grosbach43904292011-07-25 20:14:50 +00002583/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002584/// token must be an Identifier when called, and if it is a coprocessor
2585/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002586ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002587parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002588 SMLoc S = Parser.getTok().getLoc();
2589 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002590 if (Tok.isNot(AsmToken::Identifier))
2591 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002592
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002593 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002594 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002595 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002596
2597 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002598 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002599 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002600}
2601
Jim Grosbach43904292011-07-25 20:14:50 +00002602/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002603/// token must be an Identifier when called, and if it is a coprocessor
2604/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002605ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002606parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002607 SMLoc S = Parser.getTok().getLoc();
2608 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002609 if (Tok.isNot(AsmToken::Identifier))
2610 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002611
2612 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2613 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002614 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002615
2616 Parser.Lex(); // Eat identifier token.
2617 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002618 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002619}
2620
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002621/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2622/// coproc_option : '{' imm0_255 '}'
2623ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2624parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2625 SMLoc S = Parser.getTok().getLoc();
2626
2627 // If this isn't a '{', this isn't a coprocessor immediate operand.
2628 if (Parser.getTok().isNot(AsmToken::LCurly))
2629 return MatchOperand_NoMatch;
2630 Parser.Lex(); // Eat the '{'
2631
2632 const MCExpr *Expr;
2633 SMLoc Loc = Parser.getTok().getLoc();
2634 if (getParser().ParseExpression(Expr)) {
2635 Error(Loc, "illegal expression");
2636 return MatchOperand_ParseFail;
2637 }
2638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2639 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2640 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2641 return MatchOperand_ParseFail;
2642 }
2643 int Val = CE->getValue();
2644
2645 // Check for and consume the closing '}'
2646 if (Parser.getTok().isNot(AsmToken::RCurly))
2647 return MatchOperand_ParseFail;
2648 SMLoc E = Parser.getTok().getLoc();
2649 Parser.Lex(); // Eat the '}'
2650
2651 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2652 return MatchOperand_Success;
2653}
2654
Jim Grosbachd0588e22011-09-14 18:08:35 +00002655// For register list parsing, we need to map from raw GPR register numbering
2656// to the enumeration values. The enumeration values aren't sorted by
2657// register number due to our using "sp", "lr" and "pc" as canonical names.
2658static unsigned getNextRegister(unsigned Reg) {
2659 // If this is a GPR, we need to do it manually, otherwise we can rely
2660 // on the sort ordering of the enumeration since the other reg-classes
2661 // are sane.
2662 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2663 return Reg + 1;
2664 switch(Reg) {
2665 default: assert(0 && "Invalid GPR number!");
2666 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2667 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2668 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2669 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2670 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2671 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2672 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2673 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2674 }
2675}
2676
Jim Grosbachce485e72011-11-11 21:27:40 +00002677// Return the low-subreg of a given Q register.
2678static unsigned getDRegFromQReg(unsigned QReg) {
2679 switch (QReg) {
2680 default: llvm_unreachable("expected a Q register!");
2681 case ARM::Q0: return ARM::D0;
2682 case ARM::Q1: return ARM::D2;
2683 case ARM::Q2: return ARM::D4;
2684 case ARM::Q3: return ARM::D6;
2685 case ARM::Q4: return ARM::D8;
2686 case ARM::Q5: return ARM::D10;
2687 case ARM::Q6: return ARM::D12;
2688 case ARM::Q7: return ARM::D14;
2689 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002690 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002691 case ARM::Q10: return ARM::D20;
2692 case ARM::Q11: return ARM::D22;
2693 case ARM::Q12: return ARM::D24;
2694 case ARM::Q13: return ARM::D26;
2695 case ARM::Q14: return ARM::D28;
2696 case ARM::Q15: return ARM::D30;
2697 }
2698}
2699
Jim Grosbachd0588e22011-09-14 18:08:35 +00002700/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002701bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002702parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002703 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002704 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002705 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002706 Parser.Lex(); // Eat '{' token.
2707 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002708
Jim Grosbachd0588e22011-09-14 18:08:35 +00002709 // Check the first register in the list to see what register class
2710 // this is a list of.
2711 int Reg = tryParseRegister();
2712 if (Reg == -1)
2713 return Error(RegLoc, "register expected");
2714
Jim Grosbachce485e72011-11-11 21:27:40 +00002715 // The reglist instructions have at most 16 registers, so reserve
2716 // space for that many.
2717 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2718
2719 // Allow Q regs and just interpret them as the two D sub-registers.
2720 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2721 Reg = getDRegFromQReg(Reg);
2722 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2723 ++Reg;
2724 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002725 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002726 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2727 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2728 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2729 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2730 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2731 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2732 else
2733 return Error(RegLoc, "invalid register in register list");
2734
Jim Grosbachce485e72011-11-11 21:27:40 +00002735 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002736 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002737
Jim Grosbachd0588e22011-09-14 18:08:35 +00002738 // This starts immediately after the first register token in the list,
2739 // so we can see either a comma or a minus (range separator) as a legal
2740 // next token.
2741 while (Parser.getTok().is(AsmToken::Comma) ||
2742 Parser.getTok().is(AsmToken::Minus)) {
2743 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002744 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002745 SMLoc EndLoc = Parser.getTok().getLoc();
2746 int EndReg = tryParseRegister();
2747 if (EndReg == -1)
2748 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002749 // Allow Q regs and just interpret them as the two D sub-registers.
2750 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2751 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002752 // If the register is the same as the start reg, there's nothing
2753 // more to do.
2754 if (Reg == EndReg)
2755 continue;
2756 // The register must be in the same register class as the first.
2757 if (!RC->contains(EndReg))
2758 return Error(EndLoc, "invalid register in register list");
2759 // Ranges must go from low to high.
2760 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2761 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002762
Jim Grosbachd0588e22011-09-14 18:08:35 +00002763 // Add all the registers in the range to the register list.
2764 while (Reg != EndReg) {
2765 Reg = getNextRegister(Reg);
2766 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2767 }
2768 continue;
2769 }
2770 Parser.Lex(); // Eat the comma.
2771 RegLoc = Parser.getTok().getLoc();
2772 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002773 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002774 Reg = tryParseRegister();
2775 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002776 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002777 // Allow Q regs and just interpret them as the two D sub-registers.
2778 bool isQReg = false;
2779 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2780 Reg = getDRegFromQReg(Reg);
2781 isQReg = true;
2782 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002783 // The register must be in the same register class as the first.
2784 if (!RC->contains(Reg))
2785 return Error(RegLoc, "invalid register in register list");
2786 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002787 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002788 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002789 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2790 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2791 ") in register list");
2792 continue;
2793 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002794 // VFP register lists must also be contiguous.
2795 // It's OK to use the enumeration values directly here rather, as the
2796 // VFP register classes have the enum sorted properly.
2797 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2798 Reg != OldReg + 1)
2799 return Error(RegLoc, "non-contiguous register range");
2800 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002801 if (isQReg)
2802 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002803 }
2804
Jim Grosbachd0588e22011-09-14 18:08:35 +00002805 SMLoc E = Parser.getTok().getLoc();
2806 if (Parser.getTok().isNot(AsmToken::RCurly))
2807 return Error(E, "'}' expected");
2808 Parser.Lex(); // Eat '}' token.
2809
Jim Grosbach27debd62011-12-13 21:48:29 +00002810 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002811 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002812
2813 // The ARM system instruction variants for LDM/STM have a '^' token here.
2814 if (Parser.getTok().is(AsmToken::Caret)) {
2815 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2816 Parser.Lex(); // Eat '^' token.
2817 }
2818
Bill Wendling50d0f582010-11-18 23:43:05 +00002819 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002820}
2821
Jim Grosbach98b05a52011-11-30 01:09:44 +00002822// Helper function to parse the lane index for vector lists.
2823ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002824parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2825 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002826 if (Parser.getTok().is(AsmToken::LBrac)) {
2827 Parser.Lex(); // Eat the '['.
2828 if (Parser.getTok().is(AsmToken::RBrac)) {
2829 // "Dn[]" is the 'all lanes' syntax.
2830 LaneKind = AllLanes;
2831 Parser.Lex(); // Eat the ']'.
2832 return MatchOperand_Success;
2833 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002834 const MCExpr *LaneIndex;
2835 SMLoc Loc = Parser.getTok().getLoc();
2836 if (getParser().ParseExpression(LaneIndex)) {
2837 Error(Loc, "illegal expression");
2838 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002839 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002840 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2841 if (!CE) {
2842 Error(Loc, "lane index must be empty or an integer");
2843 return MatchOperand_ParseFail;
2844 }
2845 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2846 Error(Parser.getTok().getLoc(), "']' expected");
2847 return MatchOperand_ParseFail;
2848 }
2849 Parser.Lex(); // Eat the ']'.
2850 int64_t Val = CE->getValue();
2851
2852 // FIXME: Make this range check context sensitive for .8, .16, .32.
2853 if (Val < 0 || Val > 7) {
2854 Error(Parser.getTok().getLoc(), "lane index out of range");
2855 return MatchOperand_ParseFail;
2856 }
2857 Index = Val;
2858 LaneKind = IndexedLane;
2859 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002860 }
2861 LaneKind = NoLanes;
2862 return MatchOperand_Success;
2863}
2864
Jim Grosbach862019c2011-10-18 23:02:30 +00002865// parse a vector register list
2866ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2867parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002868 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002869 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002870 SMLoc S = Parser.getTok().getLoc();
2871 // As an extension (to match gas), support a plain D register or Q register
2872 // (without encosing curly braces) as a single or double entry list,
2873 // respectively.
2874 if (Parser.getTok().is(AsmToken::Identifier)) {
2875 int Reg = tryParseRegister();
2876 if (Reg == -1)
2877 return MatchOperand_NoMatch;
2878 SMLoc E = Parser.getTok().getLoc();
2879 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002880 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002881 if (Res != MatchOperand_Success)
2882 return Res;
2883 switch (LaneKind) {
2884 default:
2885 assert(0 && "unexpected lane kind!");
2886 case NoLanes:
2887 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002888 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002889 break;
2890 case AllLanes:
2891 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002892 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2893 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002894 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002895 case IndexedLane:
2896 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002897 LaneIndex,
2898 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002899 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002900 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002901 return MatchOperand_Success;
2902 }
2903 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2904 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002905 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002906 if (Res != MatchOperand_Success)
2907 return Res;
2908 switch (LaneKind) {
2909 default:
2910 assert(0 && "unexpected lane kind!");
2911 case NoLanes:
2912 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002913 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002914 break;
2915 case AllLanes:
2916 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002917 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2918 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002919 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002920 case IndexedLane:
2921 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002922 LaneIndex,
2923 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002924 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002925 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002926 return MatchOperand_Success;
2927 }
2928 Error(S, "vector register expected");
2929 return MatchOperand_ParseFail;
2930 }
2931
2932 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002933 return MatchOperand_NoMatch;
2934
Jim Grosbach862019c2011-10-18 23:02:30 +00002935 Parser.Lex(); // Eat '{' token.
2936 SMLoc RegLoc = Parser.getTok().getLoc();
2937
2938 int Reg = tryParseRegister();
2939 if (Reg == -1) {
2940 Error(RegLoc, "register expected");
2941 return MatchOperand_ParseFail;
2942 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002943 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002944 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002945 unsigned FirstReg = Reg;
2946 // The list is of D registers, but we also allow Q regs and just interpret
2947 // them as the two D sub-registers.
2948 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2949 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002950 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2951 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002952 ++Reg;
2953 ++Count;
2954 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002955 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002956 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002957
Jim Grosbache43862b2011-11-15 23:19:15 +00002958 while (Parser.getTok().is(AsmToken::Comma) ||
2959 Parser.getTok().is(AsmToken::Minus)) {
2960 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002961 if (!Spacing)
2962 Spacing = 1; // Register range implies a single spaced list.
2963 else if (Spacing == 2) {
2964 Error(Parser.getTok().getLoc(),
2965 "sequential registers in double spaced list");
2966 return MatchOperand_ParseFail;
2967 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002968 Parser.Lex(); // Eat the minus.
2969 SMLoc EndLoc = Parser.getTok().getLoc();
2970 int EndReg = tryParseRegister();
2971 if (EndReg == -1) {
2972 Error(EndLoc, "register expected");
2973 return MatchOperand_ParseFail;
2974 }
2975 // Allow Q regs and just interpret them as the two D sub-registers.
2976 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2977 EndReg = getDRegFromQReg(EndReg) + 1;
2978 // If the register is the same as the start reg, there's nothing
2979 // more to do.
2980 if (Reg == EndReg)
2981 continue;
2982 // The register must be in the same register class as the first.
2983 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2984 Error(EndLoc, "invalid register in register list");
2985 return MatchOperand_ParseFail;
2986 }
2987 // Ranges must go from low to high.
2988 if (Reg > EndReg) {
2989 Error(EndLoc, "bad range in register list");
2990 return MatchOperand_ParseFail;
2991 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002992 // Parse the lane specifier if present.
2993 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002994 unsigned NextLaneIndex;
2995 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002996 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002997 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002998 Error(EndLoc, "mismatched lane index in register list");
2999 return MatchOperand_ParseFail;
3000 }
3001 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003002
3003 // Add all the registers in the range to the register list.
3004 Count += EndReg - Reg;
3005 Reg = EndReg;
3006 continue;
3007 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003008 Parser.Lex(); // Eat the comma.
3009 RegLoc = Parser.getTok().getLoc();
3010 int OldReg = Reg;
3011 Reg = tryParseRegister();
3012 if (Reg == -1) {
3013 Error(RegLoc, "register expected");
3014 return MatchOperand_ParseFail;
3015 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003016 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003017 // It's OK to use the enumeration values directly here rather, as the
3018 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003019 //
3020 // The list is of D registers, but we also allow Q regs and just interpret
3021 // them as the two D sub-registers.
3022 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003023 if (!Spacing)
3024 Spacing = 1; // Register range implies a single spaced list.
3025 else if (Spacing == 2) {
3026 Error(RegLoc,
3027 "invalid register in double-spaced list (must be 'D' register')");
3028 return MatchOperand_ParseFail;
3029 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003030 Reg = getDRegFromQReg(Reg);
3031 if (Reg != OldReg + 1) {
3032 Error(RegLoc, "non-contiguous register range");
3033 return MatchOperand_ParseFail;
3034 }
3035 ++Reg;
3036 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003037 // Parse the lane specifier if present.
3038 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003039 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003040 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003041 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003042 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003043 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003044 Error(EndLoc, "mismatched lane index in register list");
3045 return MatchOperand_ParseFail;
3046 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003047 continue;
3048 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003049 // Normal D register.
3050 // Figure out the register spacing (single or double) of the list if
3051 // we don't know it already.
3052 if (!Spacing)
3053 Spacing = 1 + (Reg == OldReg + 2);
3054
3055 // Just check that it's contiguous and keep going.
3056 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003057 Error(RegLoc, "non-contiguous register range");
3058 return MatchOperand_ParseFail;
3059 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003060 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003061 // Parse the lane specifier if present.
3062 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003063 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003064 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003065 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003066 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003067 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003068 Error(EndLoc, "mismatched lane index in register list");
3069 return MatchOperand_ParseFail;
3070 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003071 }
3072
3073 SMLoc E = Parser.getTok().getLoc();
3074 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3075 Error(E, "'}' expected");
3076 return MatchOperand_ParseFail;
3077 }
3078 Parser.Lex(); // Eat '}' token.
3079
Jim Grosbach98b05a52011-11-30 01:09:44 +00003080 switch (LaneKind) {
3081 default:
3082 assert(0 && "unexpected lane kind in register list.");
3083 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003084 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3085 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003086 break;
3087 case AllLanes:
3088 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003089 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003090 S, E));
3091 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003092 case IndexedLane:
3093 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003094 LaneIndex,
3095 (Spacing == 2),
3096 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003097 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003098 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003099 return MatchOperand_Success;
3100}
3101
Jim Grosbach43904292011-07-25 20:14:50 +00003102/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003103ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003104parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003105 SMLoc S = Parser.getTok().getLoc();
3106 const AsmToken &Tok = Parser.getTok();
3107 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3108 StringRef OptStr = Tok.getString();
3109
3110 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3111 .Case("sy", ARM_MB::SY)
3112 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003113 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003114 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003115 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003116 .Case("ishst", ARM_MB::ISHST)
3117 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003118 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003119 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003120 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003121 .Case("osh", ARM_MB::OSH)
3122 .Case("oshst", ARM_MB::OSHST)
3123 .Default(~0U);
3124
3125 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003126 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003127
3128 Parser.Lex(); // Eat identifier token.
3129 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003130 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003131}
3132
Jim Grosbach43904292011-07-25 20:14:50 +00003133/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003134ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003135parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003136 SMLoc S = Parser.getTok().getLoc();
3137 const AsmToken &Tok = Parser.getTok();
3138 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3139 StringRef IFlagsStr = Tok.getString();
3140
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003141 // An iflags string of "none" is interpreted to mean that none of the AIF
3142 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003143 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003144 if (IFlagsStr != "none") {
3145 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3146 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3147 .Case("a", ARM_PROC::A)
3148 .Case("i", ARM_PROC::I)
3149 .Case("f", ARM_PROC::F)
3150 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003151
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003152 // If some specific iflag is already set, it means that some letter is
3153 // present more than once, this is not acceptable.
3154 if (Flag == ~0U || (IFlags & Flag))
3155 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003156
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003157 IFlags |= Flag;
3158 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003159 }
3160
3161 Parser.Lex(); // Eat identifier token.
3162 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3163 return MatchOperand_Success;
3164}
3165
Jim Grosbach43904292011-07-25 20:14:50 +00003166/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003167ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003168parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003169 SMLoc S = Parser.getTok().getLoc();
3170 const AsmToken &Tok = Parser.getTok();
3171 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3172 StringRef Mask = Tok.getString();
3173
James Molloyacad68d2011-09-28 14:21:38 +00003174 if (isMClass()) {
3175 // See ARMv6-M 10.1.1
3176 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3177 .Case("apsr", 0)
3178 .Case("iapsr", 1)
3179 .Case("eapsr", 2)
3180 .Case("xpsr", 3)
3181 .Case("ipsr", 5)
3182 .Case("epsr", 6)
3183 .Case("iepsr", 7)
3184 .Case("msp", 8)
3185 .Case("psp", 9)
3186 .Case("primask", 16)
3187 .Case("basepri", 17)
3188 .Case("basepri_max", 18)
3189 .Case("faultmask", 19)
3190 .Case("control", 20)
3191 .Default(~0U);
3192
3193 if (FlagsVal == ~0U)
3194 return MatchOperand_NoMatch;
3195
3196 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3197 // basepri, basepri_max and faultmask only valid for V7m.
3198 return MatchOperand_NoMatch;
3199
3200 Parser.Lex(); // Eat identifier token.
3201 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3202 return MatchOperand_Success;
3203 }
3204
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003205 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3206 size_t Start = 0, Next = Mask.find('_');
3207 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003208 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003209 if (Next != StringRef::npos)
3210 Flags = Mask.slice(Next+1, Mask.size());
3211
3212 // FlagsVal contains the complete mask:
3213 // 3-0: Mask
3214 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3215 unsigned FlagsVal = 0;
3216
3217 if (SpecReg == "apsr") {
3218 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003219 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003220 .Case("g", 0x4) // same as CPSR_s
3221 .Case("nzcvqg", 0xc) // same as CPSR_fs
3222 .Default(~0U);
3223
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003224 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003225 if (!Flags.empty())
3226 return MatchOperand_NoMatch;
3227 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003228 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003229 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003230 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003231 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3232 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003233 for (int i = 0, e = Flags.size(); i != e; ++i) {
3234 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3235 .Case("c", 1)
3236 .Case("x", 2)
3237 .Case("s", 4)
3238 .Case("f", 8)
3239 .Default(~0U);
3240
3241 // If some specific flag is already set, it means that some letter is
3242 // present more than once, this is not acceptable.
3243 if (FlagsVal == ~0U || (FlagsVal & Flag))
3244 return MatchOperand_NoMatch;
3245 FlagsVal |= Flag;
3246 }
3247 } else // No match for special register.
3248 return MatchOperand_NoMatch;
3249
Owen Anderson7784f1d2011-10-21 18:43:28 +00003250 // Special register without flags is NOT equivalent to "fc" flags.
3251 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3252 // two lines would enable gas compatibility at the expense of breaking
3253 // round-tripping.
3254 //
3255 // if (!FlagsVal)
3256 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003257
3258 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3259 if (SpecReg == "spsr")
3260 FlagsVal |= 16;
3261
3262 Parser.Lex(); // Eat identifier token.
3263 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3264 return MatchOperand_Success;
3265}
3266
Jim Grosbachf6c05252011-07-21 17:23:04 +00003267ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3268parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3269 int Low, int High) {
3270 const AsmToken &Tok = Parser.getTok();
3271 if (Tok.isNot(AsmToken::Identifier)) {
3272 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3273 return MatchOperand_ParseFail;
3274 }
3275 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003276 std::string LowerOp = Op.lower();
3277 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003278 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3279 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3280 return MatchOperand_ParseFail;
3281 }
3282 Parser.Lex(); // Eat shift type token.
3283
3284 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003285 if (Parser.getTok().isNot(AsmToken::Hash) &&
3286 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003287 Error(Parser.getTok().getLoc(), "'#' expected");
3288 return MatchOperand_ParseFail;
3289 }
3290 Parser.Lex(); // Eat hash token.
3291
3292 const MCExpr *ShiftAmount;
3293 SMLoc Loc = Parser.getTok().getLoc();
3294 if (getParser().ParseExpression(ShiftAmount)) {
3295 Error(Loc, "illegal expression");
3296 return MatchOperand_ParseFail;
3297 }
3298 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3299 if (!CE) {
3300 Error(Loc, "constant expression expected");
3301 return MatchOperand_ParseFail;
3302 }
3303 int Val = CE->getValue();
3304 if (Val < Low || Val > High) {
3305 Error(Loc, "immediate value out of range");
3306 return MatchOperand_ParseFail;
3307 }
3308
3309 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3310
3311 return MatchOperand_Success;
3312}
3313
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003314ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3315parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3316 const AsmToken &Tok = Parser.getTok();
3317 SMLoc S = Tok.getLoc();
3318 if (Tok.isNot(AsmToken::Identifier)) {
3319 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3320 return MatchOperand_ParseFail;
3321 }
3322 int Val = StringSwitch<int>(Tok.getString())
3323 .Case("be", 1)
3324 .Case("le", 0)
3325 .Default(-1);
3326 Parser.Lex(); // Eat the token.
3327
3328 if (Val == -1) {
3329 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3330 return MatchOperand_ParseFail;
3331 }
3332 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3333 getContext()),
3334 S, Parser.getTok().getLoc()));
3335 return MatchOperand_Success;
3336}
3337
Jim Grosbach580f4a92011-07-25 22:20:28 +00003338/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3339/// instructions. Legal values are:
3340/// lsl #n 'n' in [0,31]
3341/// asr #n 'n' in [1,32]
3342/// n == 32 encoded as n == 0.
3343ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3344parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3345 const AsmToken &Tok = Parser.getTok();
3346 SMLoc S = Tok.getLoc();
3347 if (Tok.isNot(AsmToken::Identifier)) {
3348 Error(S, "shift operator 'asr' or 'lsl' expected");
3349 return MatchOperand_ParseFail;
3350 }
3351 StringRef ShiftName = Tok.getString();
3352 bool isASR;
3353 if (ShiftName == "lsl" || ShiftName == "LSL")
3354 isASR = false;
3355 else if (ShiftName == "asr" || ShiftName == "ASR")
3356 isASR = true;
3357 else {
3358 Error(S, "shift operator 'asr' or 'lsl' expected");
3359 return MatchOperand_ParseFail;
3360 }
3361 Parser.Lex(); // Eat the operator.
3362
3363 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003364 if (Parser.getTok().isNot(AsmToken::Hash) &&
3365 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003366 Error(Parser.getTok().getLoc(), "'#' expected");
3367 return MatchOperand_ParseFail;
3368 }
3369 Parser.Lex(); // Eat hash token.
3370
3371 const MCExpr *ShiftAmount;
3372 SMLoc E = Parser.getTok().getLoc();
3373 if (getParser().ParseExpression(ShiftAmount)) {
3374 Error(E, "malformed shift expression");
3375 return MatchOperand_ParseFail;
3376 }
3377 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3378 if (!CE) {
3379 Error(E, "shift amount must be an immediate");
3380 return MatchOperand_ParseFail;
3381 }
3382
3383 int64_t Val = CE->getValue();
3384 if (isASR) {
3385 // Shift amount must be in [1,32]
3386 if (Val < 1 || Val > 32) {
3387 Error(E, "'asr' shift amount must be in range [1,32]");
3388 return MatchOperand_ParseFail;
3389 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003390 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3391 if (isThumb() && Val == 32) {
3392 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3393 return MatchOperand_ParseFail;
3394 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003395 if (Val == 32) Val = 0;
3396 } else {
3397 // Shift amount must be in [1,32]
3398 if (Val < 0 || Val > 31) {
3399 Error(E, "'lsr' shift amount must be in range [0,31]");
3400 return MatchOperand_ParseFail;
3401 }
3402 }
3403
3404 E = Parser.getTok().getLoc();
3405 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3406
3407 return MatchOperand_Success;
3408}
3409
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003410/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3411/// of instructions. Legal values are:
3412/// ror #n 'n' in {0, 8, 16, 24}
3413ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3414parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3415 const AsmToken &Tok = Parser.getTok();
3416 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003417 if (Tok.isNot(AsmToken::Identifier))
3418 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003419 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003420 if (ShiftName != "ror" && ShiftName != "ROR")
3421 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003422 Parser.Lex(); // Eat the operator.
3423
3424 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003425 if (Parser.getTok().isNot(AsmToken::Hash) &&
3426 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003427 Error(Parser.getTok().getLoc(), "'#' expected");
3428 return MatchOperand_ParseFail;
3429 }
3430 Parser.Lex(); // Eat hash token.
3431
3432 const MCExpr *ShiftAmount;
3433 SMLoc E = Parser.getTok().getLoc();
3434 if (getParser().ParseExpression(ShiftAmount)) {
3435 Error(E, "malformed rotate expression");
3436 return MatchOperand_ParseFail;
3437 }
3438 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3439 if (!CE) {
3440 Error(E, "rotate amount must be an immediate");
3441 return MatchOperand_ParseFail;
3442 }
3443
3444 int64_t Val = CE->getValue();
3445 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3446 // normally, zero is represented in asm by omitting the rotate operand
3447 // entirely.
3448 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3449 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3450 return MatchOperand_ParseFail;
3451 }
3452
3453 E = Parser.getTok().getLoc();
3454 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3455
3456 return MatchOperand_Success;
3457}
3458
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003459ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3460parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3461 SMLoc S = Parser.getTok().getLoc();
3462 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003463 if (Parser.getTok().isNot(AsmToken::Hash) &&
3464 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003465 Error(Parser.getTok().getLoc(), "'#' expected");
3466 return MatchOperand_ParseFail;
3467 }
3468 Parser.Lex(); // Eat hash token.
3469
3470 const MCExpr *LSBExpr;
3471 SMLoc E = Parser.getTok().getLoc();
3472 if (getParser().ParseExpression(LSBExpr)) {
3473 Error(E, "malformed immediate expression");
3474 return MatchOperand_ParseFail;
3475 }
3476 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3477 if (!CE) {
3478 Error(E, "'lsb' operand must be an immediate");
3479 return MatchOperand_ParseFail;
3480 }
3481
3482 int64_t LSB = CE->getValue();
3483 // The LSB must be in the range [0,31]
3484 if (LSB < 0 || LSB > 31) {
3485 Error(E, "'lsb' operand must be in the range [0,31]");
3486 return MatchOperand_ParseFail;
3487 }
3488 E = Parser.getTok().getLoc();
3489
3490 // Expect another immediate operand.
3491 if (Parser.getTok().isNot(AsmToken::Comma)) {
3492 Error(Parser.getTok().getLoc(), "too few operands");
3493 return MatchOperand_ParseFail;
3494 }
3495 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003496 if (Parser.getTok().isNot(AsmToken::Hash) &&
3497 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003498 Error(Parser.getTok().getLoc(), "'#' expected");
3499 return MatchOperand_ParseFail;
3500 }
3501 Parser.Lex(); // Eat hash token.
3502
3503 const MCExpr *WidthExpr;
3504 if (getParser().ParseExpression(WidthExpr)) {
3505 Error(E, "malformed immediate expression");
3506 return MatchOperand_ParseFail;
3507 }
3508 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3509 if (!CE) {
3510 Error(E, "'width' operand must be an immediate");
3511 return MatchOperand_ParseFail;
3512 }
3513
3514 int64_t Width = CE->getValue();
3515 // The LSB must be in the range [1,32-lsb]
3516 if (Width < 1 || Width > 32 - LSB) {
3517 Error(E, "'width' operand must be in the range [1,32-lsb]");
3518 return MatchOperand_ParseFail;
3519 }
3520 E = Parser.getTok().getLoc();
3521
3522 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3523
3524 return MatchOperand_Success;
3525}
3526
Jim Grosbach7ce05792011-08-03 23:50:40 +00003527ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3528parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3529 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003530 // postidx_reg := '+' register {, shift}
3531 // | '-' register {, shift}
3532 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003533
3534 // This method must return MatchOperand_NoMatch without consuming any tokens
3535 // in the case where there is no match, as other alternatives take other
3536 // parse methods.
3537 AsmToken Tok = Parser.getTok();
3538 SMLoc S = Tok.getLoc();
3539 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003540 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003541 int Reg = -1;
3542 if (Tok.is(AsmToken::Plus)) {
3543 Parser.Lex(); // Eat the '+' token.
3544 haveEaten = true;
3545 } else if (Tok.is(AsmToken::Minus)) {
3546 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003547 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003548 haveEaten = true;
3549 }
3550 if (Parser.getTok().is(AsmToken::Identifier))
3551 Reg = tryParseRegister();
3552 if (Reg == -1) {
3553 if (!haveEaten)
3554 return MatchOperand_NoMatch;
3555 Error(Parser.getTok().getLoc(), "register expected");
3556 return MatchOperand_ParseFail;
3557 }
3558 SMLoc E = Parser.getTok().getLoc();
3559
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003560 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3561 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003562 if (Parser.getTok().is(AsmToken::Comma)) {
3563 Parser.Lex(); // Eat the ','.
3564 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3565 return MatchOperand_ParseFail;
3566 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003567
3568 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3569 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003570
3571 return MatchOperand_Success;
3572}
3573
Jim Grosbach251bf252011-08-10 21:56:18 +00003574ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3575parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3576 // Check for a post-index addressing register operand. Specifically:
3577 // am3offset := '+' register
3578 // | '-' register
3579 // | register
3580 // | # imm
3581 // | # + imm
3582 // | # - imm
3583
3584 // This method must return MatchOperand_NoMatch without consuming any tokens
3585 // in the case where there is no match, as other alternatives take other
3586 // parse methods.
3587 AsmToken Tok = Parser.getTok();
3588 SMLoc S = Tok.getLoc();
3589
3590 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003591 if (Parser.getTok().is(AsmToken::Hash) ||
3592 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003593 Parser.Lex(); // Eat the '#'.
3594 // Explicitly look for a '-', as we need to encode negative zero
3595 // differently.
3596 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3597 const MCExpr *Offset;
3598 if (getParser().ParseExpression(Offset))
3599 return MatchOperand_ParseFail;
3600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3601 if (!CE) {
3602 Error(S, "constant expression expected");
3603 return MatchOperand_ParseFail;
3604 }
3605 SMLoc E = Tok.getLoc();
3606 // Negative zero is encoded as the flag value INT32_MIN.
3607 int32_t Val = CE->getValue();
3608 if (isNegative && Val == 0)
3609 Val = INT32_MIN;
3610
3611 Operands.push_back(
3612 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3613
3614 return MatchOperand_Success;
3615 }
3616
3617
3618 bool haveEaten = false;
3619 bool isAdd = true;
3620 int Reg = -1;
3621 if (Tok.is(AsmToken::Plus)) {
3622 Parser.Lex(); // Eat the '+' token.
3623 haveEaten = true;
3624 } else if (Tok.is(AsmToken::Minus)) {
3625 Parser.Lex(); // Eat the '-' token.
3626 isAdd = false;
3627 haveEaten = true;
3628 }
3629 if (Parser.getTok().is(AsmToken::Identifier))
3630 Reg = tryParseRegister();
3631 if (Reg == -1) {
3632 if (!haveEaten)
3633 return MatchOperand_NoMatch;
3634 Error(Parser.getTok().getLoc(), "register expected");
3635 return MatchOperand_ParseFail;
3636 }
3637 SMLoc E = Parser.getTok().getLoc();
3638
3639 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3640 0, S, E));
3641
3642 return MatchOperand_Success;
3643}
3644
Jim Grosbacha77295d2011-09-08 22:07:06 +00003645/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3646/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3647/// when they refer multiple MIOperands inside a single one.
3648bool ARMAsmParser::
3649cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3650 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3651 // Rt, Rt2
3652 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3653 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3654 // Create a writeback register dummy placeholder.
3655 Inst.addOperand(MCOperand::CreateReg(0));
3656 // addr
3657 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3658 // pred
3659 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3660 return true;
3661}
3662
3663/// cvtT2StrdPre - Convert parsed operands to MCInst.
3664/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3665/// when they refer multiple MIOperands inside a single one.
3666bool ARMAsmParser::
3667cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3668 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3669 // Create a writeback register dummy placeholder.
3670 Inst.addOperand(MCOperand::CreateReg(0));
3671 // Rt, Rt2
3672 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3673 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3674 // addr
3675 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3676 // pred
3677 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3678 return true;
3679}
3680
Jim Grosbacheeec0252011-09-08 00:39:19 +00003681/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3682/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3683/// when they refer multiple MIOperands inside a single one.
3684bool ARMAsmParser::
3685cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3686 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3687 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3688
3689 // Create a writeback register dummy placeholder.
3690 Inst.addOperand(MCOperand::CreateImm(0));
3691
3692 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3693 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3694 return true;
3695}
3696
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003697/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3698/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3699/// when they refer multiple MIOperands inside a single one.
3700bool ARMAsmParser::
3701cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3702 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3703 // Create a writeback register dummy placeholder.
3704 Inst.addOperand(MCOperand::CreateImm(0));
3705 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3706 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3707 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3708 return true;
3709}
3710
Jim Grosbach1355cf12011-07-26 17:10:22 +00003711/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003712/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3713/// when they refer multiple MIOperands inside a single one.
3714bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003715cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003716 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3717 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3718
3719 // Create a writeback register dummy placeholder.
3720 Inst.addOperand(MCOperand::CreateImm(0));
3721
Jim Grosbach7ce05792011-08-03 23:50:40 +00003722 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003723 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3724 return true;
3725}
3726
Owen Anderson9ab0f252011-08-26 20:43:14 +00003727/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3728/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3729/// when they refer multiple MIOperands inside a single one.
3730bool ARMAsmParser::
3731cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3732 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3733 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3734
3735 // Create a writeback register dummy placeholder.
3736 Inst.addOperand(MCOperand::CreateImm(0));
3737
3738 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3739 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3740 return true;
3741}
3742
3743
Jim Grosbach548340c2011-08-11 19:22:40 +00003744/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3745/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3746/// when they refer multiple MIOperands inside a single one.
3747bool ARMAsmParser::
3748cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3749 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3750 // Create a writeback register dummy placeholder.
3751 Inst.addOperand(MCOperand::CreateImm(0));
3752 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3753 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3754 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3755 return true;
3756}
3757
Jim Grosbach1355cf12011-07-26 17:10:22 +00003758/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003759/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3760/// when they refer multiple MIOperands inside a single one.
3761bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003762cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003763 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3764 // Create a writeback register dummy placeholder.
3765 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003766 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3767 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3768 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003769 return true;
3770}
3771
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003772/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3773/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3774/// when they refer multiple MIOperands inside a single one.
3775bool ARMAsmParser::
3776cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3777 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3778 // Create a writeback register dummy placeholder.
3779 Inst.addOperand(MCOperand::CreateImm(0));
3780 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3781 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3782 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3783 return true;
3784}
3785
Jim Grosbach7ce05792011-08-03 23:50:40 +00003786/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3787/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3788/// when they refer multiple MIOperands inside a single one.
3789bool ARMAsmParser::
3790cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3791 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3792 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003793 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003794 // Create a writeback register dummy placeholder.
3795 Inst.addOperand(MCOperand::CreateImm(0));
3796 // addr
3797 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3798 // offset
3799 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3800 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003801 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3802 return true;
3803}
3804
Jim Grosbach7ce05792011-08-03 23:50:40 +00003805/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003806/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3807/// when they refer multiple MIOperands inside a single one.
3808bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003809cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3810 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3811 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003812 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003813 // Create a writeback register dummy placeholder.
3814 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003815 // addr
3816 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3817 // offset
3818 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3819 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003820 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3821 return true;
3822}
3823
Jim Grosbach7ce05792011-08-03 23:50:40 +00003824/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003825/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3826/// when they refer multiple MIOperands inside a single one.
3827bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003828cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3829 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003830 // Create a writeback register dummy placeholder.
3831 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003832 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003833 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003834 // addr
3835 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3836 // offset
3837 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3838 // pred
3839 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3840 return true;
3841}
3842
3843/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3844/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3845/// when they refer multiple MIOperands inside a single one.
3846bool ARMAsmParser::
3847cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3848 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3849 // Create a writeback register dummy placeholder.
3850 Inst.addOperand(MCOperand::CreateImm(0));
3851 // Rt
3852 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3853 // addr
3854 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3855 // offset
3856 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3857 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003858 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3859 return true;
3860}
3861
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003862/// cvtLdrdPre - Convert parsed operands to MCInst.
3863/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3864/// when they refer multiple MIOperands inside a single one.
3865bool ARMAsmParser::
3866cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3867 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3868 // Rt, Rt2
3869 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3870 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3871 // Create a writeback register dummy placeholder.
3872 Inst.addOperand(MCOperand::CreateImm(0));
3873 // addr
3874 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3875 // pred
3876 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3877 return true;
3878}
3879
Jim Grosbach14605d12011-08-11 20:28:23 +00003880/// cvtStrdPre - Convert parsed operands to MCInst.
3881/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3882/// when they refer multiple MIOperands inside a single one.
3883bool ARMAsmParser::
3884cvtStrdPre(MCInst &Inst, unsigned Opcode,
3885 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3886 // Create a writeback register dummy placeholder.
3887 Inst.addOperand(MCOperand::CreateImm(0));
3888 // Rt, Rt2
3889 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3890 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3891 // addr
3892 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3893 // pred
3894 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3895 return true;
3896}
3897
Jim Grosbach623a4542011-08-10 22:42:16 +00003898/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3899/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3900/// when they refer multiple MIOperands inside a single one.
3901bool ARMAsmParser::
3902cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3903 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3904 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3905 // Create a writeback register dummy placeholder.
3906 Inst.addOperand(MCOperand::CreateImm(0));
3907 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3908 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3909 return true;
3910}
3911
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003912/// cvtThumbMultiple- Convert parsed operands to MCInst.
3913/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3914/// when they refer multiple MIOperands inside a single one.
3915bool ARMAsmParser::
3916cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3917 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3918 // The second source operand must be the same register as the destination
3919 // operand.
3920 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003921 (((ARMOperand*)Operands[3])->getReg() !=
3922 ((ARMOperand*)Operands[5])->getReg()) &&
3923 (((ARMOperand*)Operands[3])->getReg() !=
3924 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003925 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003926 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003927 return false;
3928 }
3929 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3930 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003931 // If we have a three-operand form, make sure to set Rn to be the operand
3932 // that isn't the same as Rd.
3933 unsigned RegOp = 4;
3934 if (Operands.size() == 6 &&
3935 ((ARMOperand*)Operands[4])->getReg() ==
3936 ((ARMOperand*)Operands[3])->getReg())
3937 RegOp = 5;
3938 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3939 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003940 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3941
3942 return true;
3943}
Jim Grosbach623a4542011-08-10 22:42:16 +00003944
Jim Grosbach12431322011-10-24 22:16:58 +00003945bool ARMAsmParser::
3946cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3947 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3948 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003949 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003950 // Create a writeback register dummy placeholder.
3951 Inst.addOperand(MCOperand::CreateImm(0));
3952 // Vn
3953 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3954 // pred
3955 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3956 return true;
3957}
3958
3959bool ARMAsmParser::
3960cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3961 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3962 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003963 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003964 // Create a writeback register dummy placeholder.
3965 Inst.addOperand(MCOperand::CreateImm(0));
3966 // Vn
3967 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3968 // Vm
3969 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3970 // pred
3971 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3972 return true;
3973}
3974
Jim Grosbach4334e032011-10-31 21:50:31 +00003975bool ARMAsmParser::
3976cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3977 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3978 // Create a writeback register dummy placeholder.
3979 Inst.addOperand(MCOperand::CreateImm(0));
3980 // Vn
3981 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3982 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003983 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003984 // pred
3985 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3986 return true;
3987}
3988
3989bool ARMAsmParser::
3990cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3991 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3992 // Create a writeback register dummy placeholder.
3993 Inst.addOperand(MCOperand::CreateImm(0));
3994 // Vn
3995 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3996 // Vm
3997 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3998 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003999 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004000 // pred
4001 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4002 return true;
4003}
4004
Bill Wendlinge7176102010-11-06 22:36:58 +00004005/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004006/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004007bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004008parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004009 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004010 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004011 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004012 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004013 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004014
Sean Callanan18b83232010-01-19 21:44:56 +00004015 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004016 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004017 if (BaseRegNum == -1)
4018 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004019
Daniel Dunbar05710932011-01-18 05:34:17 +00004020 // The next token must either be a comma or a closing bracket.
4021 const AsmToken &Tok = Parser.getTok();
4022 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004023 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004024
Jim Grosbach7ce05792011-08-03 23:50:40 +00004025 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004026 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004027 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004028
Jim Grosbach7ce05792011-08-03 23:50:40 +00004029 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004030 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004031
Jim Grosbachfb12f352011-09-19 18:42:21 +00004032 // If there's a pre-indexing writeback marker, '!', just add it as a token
4033 // operand. It's rather odd, but syntactically valid.
4034 if (Parser.getTok().is(AsmToken::Exclaim)) {
4035 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4036 Parser.Lex(); // Eat the '!'.
4037 }
4038
Jim Grosbach7ce05792011-08-03 23:50:40 +00004039 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004040 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004041
Jim Grosbach7ce05792011-08-03 23:50:40 +00004042 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4043 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004044
Jim Grosbach57dcb852011-10-11 17:29:55 +00004045 // If we have a ':', it's an alignment specifier.
4046 if (Parser.getTok().is(AsmToken::Colon)) {
4047 Parser.Lex(); // Eat the ':'.
4048 E = Parser.getTok().getLoc();
4049
4050 const MCExpr *Expr;
4051 if (getParser().ParseExpression(Expr))
4052 return true;
4053
4054 // The expression has to be a constant. Memory references with relocations
4055 // don't come through here, as they use the <label> forms of the relevant
4056 // instructions.
4057 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4058 if (!CE)
4059 return Error (E, "constant expression expected");
4060
4061 unsigned Align = 0;
4062 switch (CE->getValue()) {
4063 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004064 return Error(E,
4065 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4066 case 16: Align = 2; break;
4067 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004068 case 64: Align = 8; break;
4069 case 128: Align = 16; break;
4070 case 256: Align = 32; break;
4071 }
4072
4073 // Now we should have the closing ']'
4074 E = Parser.getTok().getLoc();
4075 if (Parser.getTok().isNot(AsmToken::RBrac))
4076 return Error(E, "']' expected");
4077 Parser.Lex(); // Eat right bracket token.
4078
4079 // Don't worry about range checking the value here. That's handled by
4080 // the is*() predicates.
4081 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4082 ARM_AM::no_shift, 0, Align,
4083 false, S, E));
4084
4085 // If there's a pre-indexing writeback marker, '!', just add it as a token
4086 // operand.
4087 if (Parser.getTok().is(AsmToken::Exclaim)) {
4088 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4089 Parser.Lex(); // Eat the '!'.
4090 }
4091
4092 return false;
4093 }
4094
4095 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004096 // offset. Be friendly and also accept a plain integer (without a leading
4097 // hash) for gas compatibility.
4098 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004099 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004100 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004101 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004102 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004103 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004104
Owen Anderson0da10cf2011-08-29 19:36:44 +00004105 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004106 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004107 if (getParser().ParseExpression(Offset))
4108 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004109
4110 // The expression has to be a constant. Memory references with relocations
4111 // don't come through here, as they use the <label> forms of the relevant
4112 // instructions.
4113 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4114 if (!CE)
4115 return Error (E, "constant expression expected");
4116
Owen Anderson0da10cf2011-08-29 19:36:44 +00004117 // If the constant was #-0, represent it as INT32_MIN.
4118 int32_t Val = CE->getValue();
4119 if (isNegative && Val == 0)
4120 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4121
Jim Grosbach7ce05792011-08-03 23:50:40 +00004122 // Now we should have the closing ']'
4123 E = Parser.getTok().getLoc();
4124 if (Parser.getTok().isNot(AsmToken::RBrac))
4125 return Error(E, "']' expected");
4126 Parser.Lex(); // Eat right bracket token.
4127
4128 // Don't worry about range checking the value here. That's handled by
4129 // the is*() predicates.
4130 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004131 ARM_AM::no_shift, 0, 0,
4132 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004133
4134 // If there's a pre-indexing writeback marker, '!', just add it as a token
4135 // operand.
4136 if (Parser.getTok().is(AsmToken::Exclaim)) {
4137 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4138 Parser.Lex(); // Eat the '!'.
4139 }
4140
4141 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004142 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004143
4144 // The register offset is optionally preceded by a '+' or '-'
4145 bool isNegative = false;
4146 if (Parser.getTok().is(AsmToken::Minus)) {
4147 isNegative = true;
4148 Parser.Lex(); // Eat the '-'.
4149 } else if (Parser.getTok().is(AsmToken::Plus)) {
4150 // Nothing to do.
4151 Parser.Lex(); // Eat the '+'.
4152 }
4153
4154 E = Parser.getTok().getLoc();
4155 int OffsetRegNum = tryParseRegister();
4156 if (OffsetRegNum == -1)
4157 return Error(E, "register expected");
4158
4159 // If there's a shift operator, handle it.
4160 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004161 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004162 if (Parser.getTok().is(AsmToken::Comma)) {
4163 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004164 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004165 return true;
4166 }
4167
4168 // Now we should have the closing ']'
4169 E = Parser.getTok().getLoc();
4170 if (Parser.getTok().isNot(AsmToken::RBrac))
4171 return Error(E, "']' expected");
4172 Parser.Lex(); // Eat right bracket token.
4173
4174 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004175 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176 S, E));
4177
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004178 // If there's a pre-indexing writeback marker, '!', just add it as a token
4179 // operand.
4180 if (Parser.getTok().is(AsmToken::Exclaim)) {
4181 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4182 Parser.Lex(); // Eat the '!'.
4183 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004184
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004185 return false;
4186}
4187
Jim Grosbach7ce05792011-08-03 23:50:40 +00004188/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004189/// ( lsl | lsr | asr | ror ) , # shift_amount
4190/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004191/// return true if it parses a shift otherwise it returns false.
4192bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4193 unsigned &Amount) {
4194 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004195 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004196 if (Tok.isNot(AsmToken::Identifier))
4197 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004198 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004199 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4200 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004201 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004202 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004203 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004204 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004205 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004206 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004207 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004208 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004209 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004210 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004211 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004212 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004213
Jim Grosbach7ce05792011-08-03 23:50:40 +00004214 // rrx stands alone.
4215 Amount = 0;
4216 if (St != ARM_AM::rrx) {
4217 Loc = Parser.getTok().getLoc();
4218 // A '#' and a shift amount.
4219 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004220 if (HashTok.isNot(AsmToken::Hash) &&
4221 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004222 return Error(HashTok.getLoc(), "'#' expected");
4223 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004224
Jim Grosbach7ce05792011-08-03 23:50:40 +00004225 const MCExpr *Expr;
4226 if (getParser().ParseExpression(Expr))
4227 return true;
4228 // Range check the immediate.
4229 // lsl, ror: 0 <= imm <= 31
4230 // lsr, asr: 0 <= imm <= 32
4231 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4232 if (!CE)
4233 return Error(Loc, "shift amount must be an immediate");
4234 int64_t Imm = CE->getValue();
4235 if (Imm < 0 ||
4236 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4237 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4238 return Error(Loc, "immediate shift value out of range");
4239 Amount = Imm;
4240 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004241
4242 return false;
4243}
4244
Jim Grosbach9d390362011-10-03 23:38:36 +00004245/// parseFPImm - A floating point immediate expression operand.
4246ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4247parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4248 SMLoc S = Parser.getTok().getLoc();
4249
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004250 if (Parser.getTok().isNot(AsmToken::Hash) &&
4251 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004252 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004253
4254 // Disambiguate the VMOV forms that can accept an FP immediate.
4255 // vmov.f32 <sreg>, #imm
4256 // vmov.f64 <dreg>, #imm
4257 // vmov.f32 <dreg>, #imm @ vector f32x2
4258 // vmov.f32 <qreg>, #imm @ vector f32x4
4259 //
4260 // There are also the NEON VMOV instructions which expect an
4261 // integer constant. Make sure we don't try to parse an FPImm
4262 // for these:
4263 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4264 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4265 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4266 TyOp->getToken() != ".f64"))
4267 return MatchOperand_NoMatch;
4268
Jim Grosbach9d390362011-10-03 23:38:36 +00004269 Parser.Lex(); // Eat the '#'.
4270
4271 // Handle negation, as that still comes through as a separate token.
4272 bool isNegative = false;
4273 if (Parser.getTok().is(AsmToken::Minus)) {
4274 isNegative = true;
4275 Parser.Lex();
4276 }
4277 const AsmToken &Tok = Parser.getTok();
4278 if (Tok.is(AsmToken::Real)) {
4279 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4280 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4281 // If we had a '-' in front, toggle the sign bit.
4282 IntVal ^= (uint64_t)isNegative << 63;
4283 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4284 Parser.Lex(); // Eat the token.
4285 if (Val == -1) {
4286 TokError("floating point value out of range");
4287 return MatchOperand_ParseFail;
4288 }
4289 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4290 return MatchOperand_Success;
4291 }
4292 if (Tok.is(AsmToken::Integer)) {
4293 int64_t Val = Tok.getIntVal();
4294 Parser.Lex(); // Eat the token.
4295 if (Val > 255 || Val < 0) {
4296 TokError("encoded floating point value out of range");
4297 return MatchOperand_ParseFail;
4298 }
4299 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4300 return MatchOperand_Success;
4301 }
4302
4303 TokError("invalid floating point immediate");
4304 return MatchOperand_ParseFail;
4305}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004306/// Parse a arm instruction operand. For now this parses the operand regardless
4307/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004308bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004309 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004310 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004311
4312 // Check if the current operand has a custom associated parser, if so, try to
4313 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004314 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4315 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004316 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004317 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4318 // there was a match, but an error occurred, in which case, just return that
4319 // the operand parsing failed.
4320 if (ResTy == MatchOperand_ParseFail)
4321 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004322
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004323 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004324 default:
4325 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004326 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004327 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004328 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004329 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004330 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004331 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004332 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004333 else if (Res == -1) // irrecoverable error
4334 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004335 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004336 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4337 S = Parser.getTok().getLoc();
4338 Parser.Lex();
4339 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4340 return false;
4341 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004342
4343 // Fall though for the Identifier case that is not a register or a
4344 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004345 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004346 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004347 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004348 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004349 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004350 // This was not a register so parse other operands that start with an
4351 // identifier (like labels) as expressions and create them as immediates.
4352 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004353 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004354 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004355 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004356 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004357 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4358 return false;
4359 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004360 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004361 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004362 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004363 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004364 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004365 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004366 // #42 -> immediate.
4367 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004368 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004369 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004370 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004371 const MCExpr *ImmVal;
4372 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004373 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004375 if (CE) {
4376 int32_t Val = CE->getValue();
4377 if (isNegative && Val == 0)
4378 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004379 }
Sean Callanan76264762010-04-02 22:27:05 +00004380 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004381 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4382 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004383 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004384 case AsmToken::Colon: {
4385 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004386 // FIXME: Check it's an expression prefix,
4387 // e.g. (FOO - :lower16:BAR) isn't legal.
4388 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004389 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004390 return true;
4391
Evan Cheng75972122011-01-13 07:58:56 +00004392 const MCExpr *SubExprVal;
4393 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004394 return true;
4395
Evan Cheng75972122011-01-13 07:58:56 +00004396 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4397 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004398 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004399 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004400 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004401 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004402 }
4403}
4404
Jim Grosbach1355cf12011-07-26 17:10:22 +00004405// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004406// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004407bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004408 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004409
4410 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004411 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004412 Parser.Lex(); // Eat ':'
4413
4414 if (getLexer().isNot(AsmToken::Identifier)) {
4415 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4416 return true;
4417 }
4418
4419 StringRef IDVal = Parser.getTok().getIdentifier();
4420 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004421 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004422 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004423 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004424 } else {
4425 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4426 return true;
4427 }
4428 Parser.Lex();
4429
4430 if (getLexer().isNot(AsmToken::Colon)) {
4431 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4432 return true;
4433 }
4434 Parser.Lex(); // Eat the last ':'
4435 return false;
4436}
4437
Daniel Dunbar352e1482011-01-11 15:59:50 +00004438/// \brief Given a mnemonic, split out possible predication code and carry
4439/// setting letters to form a canonical mnemonic and flags.
4440//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004441// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004442// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004443StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004444 unsigned &PredicationCode,
4445 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004446 unsigned &ProcessorIMod,
4447 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004448 PredicationCode = ARMCC::AL;
4449 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004450 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004451
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004452 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004453 //
4454 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004455 if ((Mnemonic == "movs" && isThumb()) ||
4456 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4457 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4458 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4459 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4460 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4461 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004462 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4463 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004464 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004465
Jim Grosbach3f00e312011-07-11 17:09:57 +00004466 // First, split out any predication code. Ignore mnemonics we know aren't
4467 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004468 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004469 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004470 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004471 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004472 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4473 .Case("eq", ARMCC::EQ)
4474 .Case("ne", ARMCC::NE)
4475 .Case("hs", ARMCC::HS)
4476 .Case("cs", ARMCC::HS)
4477 .Case("lo", ARMCC::LO)
4478 .Case("cc", ARMCC::LO)
4479 .Case("mi", ARMCC::MI)
4480 .Case("pl", ARMCC::PL)
4481 .Case("vs", ARMCC::VS)
4482 .Case("vc", ARMCC::VC)
4483 .Case("hi", ARMCC::HI)
4484 .Case("ls", ARMCC::LS)
4485 .Case("ge", ARMCC::GE)
4486 .Case("lt", ARMCC::LT)
4487 .Case("gt", ARMCC::GT)
4488 .Case("le", ARMCC::LE)
4489 .Case("al", ARMCC::AL)
4490 .Default(~0U);
4491 if (CC != ~0U) {
4492 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4493 PredicationCode = CC;
4494 }
Bill Wendling52925b62010-10-29 23:50:21 +00004495 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004496
Daniel Dunbar352e1482011-01-11 15:59:50 +00004497 // Next, determine if we have a carry setting bit. We explicitly ignore all
4498 // the instructions we know end in 's'.
4499 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004500 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004501 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4502 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4503 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004504 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004505 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004506 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004507 Mnemonic == "fmuls" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004508 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004509 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4510 CarrySetting = true;
4511 }
4512
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004513 // The "cps" instruction can have a interrupt mode operand which is glued into
4514 // the mnemonic. Check if this is the case, split it and parse the imod op
4515 if (Mnemonic.startswith("cps")) {
4516 // Split out any imod code.
4517 unsigned IMod =
4518 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4519 .Case("ie", ARM_PROC::IE)
4520 .Case("id", ARM_PROC::ID)
4521 .Default(~0U);
4522 if (IMod != ~0U) {
4523 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4524 ProcessorIMod = IMod;
4525 }
4526 }
4527
Jim Grosbach89df9962011-08-26 21:43:41 +00004528 // The "it" instruction has the condition mask on the end of the mnemonic.
4529 if (Mnemonic.startswith("it")) {
4530 ITMask = Mnemonic.slice(2, Mnemonic.size());
4531 Mnemonic = Mnemonic.slice(0, 2);
4532 }
4533
Daniel Dunbar352e1482011-01-11 15:59:50 +00004534 return Mnemonic;
4535}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004536
4537/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4538/// inclusion of carry set or predication code operands.
4539//
4540// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004541void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004542getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004543 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004544 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4545 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004546 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004547 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004548 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004549 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004550 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004551 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004552 Mnemonic == "mla" || Mnemonic == "smlal" ||
4553 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004554 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004555 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004556 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004557
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004558 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4559 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4560 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4561 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004562 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4563 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004564 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004565 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4566 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4567 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004568 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4569 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004570 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004571 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004572 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004573 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004574
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004575 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004576 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004577 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004578 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004579 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004580}
4581
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004582bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4583 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004584 // FIXME: This is all horribly hacky. We really need a better way to deal
4585 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004586
4587 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4588 // another does not. Specifically, the MOVW instruction does not. So we
4589 // special case it here and remove the defaulted (non-setting) cc_out
4590 // operand if that's the instruction we're trying to match.
4591 //
4592 // We do this as post-processing of the explicit operands rather than just
4593 // conditionally adding the cc_out in the first place because we need
4594 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004595 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004596 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4597 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4598 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4599 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004600
4601 // Register-register 'add' for thumb does not have a cc_out operand
4602 // when there are only two register operands.
4603 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4604 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4605 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4606 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4607 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004608 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004609 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4610 // have to check the immediate range here since Thumb2 has a variant
4611 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004612 if (((isThumb() && Mnemonic == "add") ||
4613 (isThumbTwo() && Mnemonic == "sub")) &&
4614 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004615 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4616 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4617 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004618 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4619 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4620 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004621 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004622 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4623 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004624 // selecting via the generic "add" mnemonic, so to know that we
4625 // should remove the cc_out operand, we have to explicitly check that
4626 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004627 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4628 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004629 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4630 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4631 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4632 // Nest conditions rather than one big 'if' statement for readability.
4633 //
4634 // If either register is a high reg, it's either one of the SP
4635 // variants (handled above) or a 32-bit encoding, so we just
4636 // check against T3.
4637 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4638 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4639 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4640 return false;
4641 // If both registers are low, we're in an IT block, and the immediate is
4642 // in range, we should use encoding T1 instead, which has a cc_out.
4643 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004644 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004645 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4646 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4647 return false;
4648
4649 // Otherwise, we use encoding T4, which does not have a cc_out
4650 // operand.
4651 return true;
4652 }
4653
Jim Grosbach64944f42011-09-14 21:00:40 +00004654 // The thumb2 multiply instruction doesn't have a CCOut register, so
4655 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4656 // use the 16-bit encoding or not.
4657 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4658 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4659 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4660 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4661 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4662 // If the registers aren't low regs, the destination reg isn't the
4663 // same as one of the source regs, or the cc_out operand is zero
4664 // outside of an IT block, we have to use the 32-bit encoding, so
4665 // remove the cc_out operand.
4666 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4667 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004668 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004669 !inITBlock() ||
4670 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4671 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4672 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4673 static_cast<ARMOperand*>(Operands[4])->getReg())))
4674 return true;
4675
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004676 // Also check the 'mul' syntax variant that doesn't specify an explicit
4677 // destination register.
4678 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4679 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4680 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4681 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4682 // If the registers aren't low regs or the cc_out operand is zero
4683 // outside of an IT block, we have to use the 32-bit encoding, so
4684 // remove the cc_out operand.
4685 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4686 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4687 !inITBlock()))
4688 return true;
4689
Jim Grosbach64944f42011-09-14 21:00:40 +00004690
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004691
Jim Grosbachf69c8042011-08-24 21:42:27 +00004692 // Register-register 'add/sub' for thumb does not have a cc_out operand
4693 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4694 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4695 // right, this will result in better diagnostics (which operand is off)
4696 // anyway.
4697 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4698 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004699 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4700 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4701 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4702 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004703
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004704 return false;
4705}
4706
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004707static bool isDataTypeToken(StringRef Tok) {
4708 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4709 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4710 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4711 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4712 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4713 Tok == ".f" || Tok == ".d";
4714}
4715
4716// FIXME: This bit should probably be handled via an explicit match class
4717// in the .td files that matches the suffix instead of having it be
4718// a literal string token the way it is now.
4719static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4720 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4721}
4722
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004723static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004724/// Parse an arm instruction mnemonic followed by its operands.
4725bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4726 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004727 // Apply mnemonic aliases before doing anything else, as the destination
4728 // mnemnonic may include suffices and we want to handle them normally.
4729 // The generic tblgen'erated code does this later, at the start of
4730 // MatchInstructionImpl(), but that's too late for aliases that include
4731 // any sort of suffix.
4732 unsigned AvailableFeatures = getAvailableFeatures();
4733 applyMnemonicAliases(Name, AvailableFeatures);
4734
Jim Grosbacha39cda72011-12-14 02:16:11 +00004735 // First check for the ARM-specific .req directive.
4736 if (Parser.getTok().is(AsmToken::Identifier) &&
4737 Parser.getTok().getIdentifier() == ".req") {
4738 parseDirectiveReq(Name, NameLoc);
4739 // We always return 'error' for this, as we're done with this
4740 // statement and don't need to match the 'instruction."
4741 return true;
4742 }
4743
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004744 // Create the leading tokens for the mnemonic, split by '.' characters.
4745 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004746 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004747
Daniel Dunbar352e1482011-01-11 15:59:50 +00004748 // Split out the predication code and carry setting flag from the mnemonic.
4749 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004750 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004751 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004752 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004753 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004754 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004755
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004756 // In Thumb1, only the branch (B) instruction can be predicated.
4757 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4758 Parser.EatToEndOfStatement();
4759 return Error(NameLoc, "conditional execution not supported in Thumb1");
4760 }
4761
Jim Grosbachffa32252011-07-19 19:13:28 +00004762 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4763
Jim Grosbach89df9962011-08-26 21:43:41 +00004764 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4765 // is the mask as it will be for the IT encoding if the conditional
4766 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4767 // where the conditional bit0 is zero, the instruction post-processing
4768 // will adjust the mask accordingly.
4769 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004770 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4771 if (ITMask.size() > 3) {
4772 Parser.EatToEndOfStatement();
4773 return Error(Loc, "too many conditions on IT instruction");
4774 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004775 unsigned Mask = 8;
4776 for (unsigned i = ITMask.size(); i != 0; --i) {
4777 char pos = ITMask[i - 1];
4778 if (pos != 't' && pos != 'e') {
4779 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004780 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004781 }
4782 Mask >>= 1;
4783 if (ITMask[i - 1] == 't')
4784 Mask |= 8;
4785 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004786 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004787 }
4788
Jim Grosbachffa32252011-07-19 19:13:28 +00004789 // FIXME: This is all a pretty gross hack. We should automatically handle
4790 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004791
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004792 // Next, add the CCOut and ConditionCode operands, if needed.
4793 //
4794 // For mnemonics which can ever incorporate a carry setting bit or predication
4795 // code, our matching model involves us always generating CCOut and
4796 // ConditionCode operands to match the mnemonic "as written" and then we let
4797 // the matcher deal with finding the right instruction or generating an
4798 // appropriate error.
4799 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004800 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004801
Jim Grosbach33c16a22011-07-14 22:04:21 +00004802 // If we had a carry-set on an instruction that can't do that, issue an
4803 // error.
4804 if (!CanAcceptCarrySet && CarrySetting) {
4805 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004806 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004807 "' can not set flags, but 's' suffix specified");
4808 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004809 // If we had a predication code on an instruction that can't do that, issue an
4810 // error.
4811 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4812 Parser.EatToEndOfStatement();
4813 return Error(NameLoc, "instruction '" + Mnemonic +
4814 "' is not predicable, but condition code specified");
4815 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004816
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004817 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004818 if (CanAcceptCarrySet) {
4819 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004820 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004821 Loc));
4822 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004823
4824 // Add the predication code operand, if necessary.
4825 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004826 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4827 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004828 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004829 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004830 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004831
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004832 // Add the processor imod operand, if necessary.
4833 if (ProcessorIMod) {
4834 Operands.push_back(ARMOperand::CreateImm(
4835 MCConstantExpr::Create(ProcessorIMod, getContext()),
4836 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004837 }
4838
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004839 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004840 while (Next != StringRef::npos) {
4841 Start = Next;
4842 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004843 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004844
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004845 // Some NEON instructions have an optional datatype suffix that is
4846 // completely ignored. Check for that.
4847 if (isDataTypeToken(ExtraToken) &&
4848 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4849 continue;
4850
Jim Grosbach81d2e392011-09-07 16:06:04 +00004851 if (ExtraToken != ".n") {
4852 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4853 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4854 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004855 }
4856
4857 // Read the remaining operands.
4858 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004859 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004860 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004861 Parser.EatToEndOfStatement();
4862 return true;
4863 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004864
4865 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004866 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004867
4868 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004869 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004870 Parser.EatToEndOfStatement();
4871 return true;
4872 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004873 }
4874 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004875
Chris Lattnercbf8a982010-09-11 16:18:25 +00004876 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004877 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004878 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004879 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004880 }
Bill Wendling146018f2010-11-06 21:42:12 +00004881
Chris Lattner34e53142010-09-08 05:10:46 +00004882 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004883
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004884 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4885 // do and don't have a cc_out optional-def operand. With some spot-checks
4886 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004887 // parse and adjust accordingly before actually matching. We shouldn't ever
4888 // try to remove a cc_out operand that was explicitly set on the the
4889 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4890 // table driven matcher doesn't fit well with the ARM instruction set.
4891 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004892 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4893 Operands.erase(Operands.begin() + 1);
4894 delete Op;
4895 }
4896
Jim Grosbachcf121c32011-07-28 21:57:55 +00004897 // ARM mode 'blx' need special handling, as the register operand version
4898 // is predicable, but the label operand version is not. So, we can't rely
4899 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004900 // a k_CondCode operand in the list. If we're trying to match the label
4901 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004902 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4903 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4904 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4905 Operands.erase(Operands.begin() + 1);
4906 delete Op;
4907 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004908
4909 // The vector-compare-to-zero instructions have a literal token "#0" at
4910 // the end that comes to here as an immediate operand. Convert it to a
4911 // token to play nicely with the matcher.
4912 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4913 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4914 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4915 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4916 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4917 if (CE && CE->getValue() == 0) {
4918 Operands.erase(Operands.begin() + 5);
4919 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4920 delete Op;
4921 }
4922 }
Jim Grosbach68259142011-10-03 22:30:24 +00004923 // VCMP{E} does the same thing, but with a different operand count.
4924 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4925 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4926 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4928 if (CE && CE->getValue() == 0) {
4929 Operands.erase(Operands.begin() + 4);
4930 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4931 delete Op;
4932 }
4933 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004934 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004935 // end. Convert it to a token here. Take care not to convert those
4936 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004937 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004938 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4939 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004940 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4941 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4942 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004943 if (CE && CE->getValue() == 0 &&
4944 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004945 // The cc_out operand matches the IT block.
4946 ((inITBlock() != CarrySetting) &&
4947 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004948 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004949 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004950 Operands.erase(Operands.begin() + 5);
4951 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4952 delete Op;
4953 }
4954 }
4955
Chris Lattner98986712010-01-14 22:21:20 +00004956 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004957}
4958
Jim Grosbach189610f2011-07-26 18:25:39 +00004959// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004960
4961// return 'true' if register list contains non-low GPR registers,
4962// 'false' otherwise. If Reg is in the register list or is HiReg, set
4963// 'containsReg' to true.
4964static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4965 unsigned HiReg, bool &containsReg) {
4966 containsReg = false;
4967 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4968 unsigned OpReg = Inst.getOperand(i).getReg();
4969 if (OpReg == Reg)
4970 containsReg = true;
4971 // Anything other than a low register isn't legal here.
4972 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4973 return true;
4974 }
4975 return false;
4976}
4977
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004978// Check if the specified regisgter is in the register list of the inst,
4979// starting at the indicated operand number.
4980static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4981 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4982 unsigned OpReg = Inst.getOperand(i).getReg();
4983 if (OpReg == Reg)
4984 return true;
4985 }
4986 return false;
4987}
4988
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004989// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4990// the ARMInsts array) instead. Getting that here requires awkward
4991// API changes, though. Better way?
4992namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004993extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004994}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004995static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004996 return ARMInsts[Opcode];
4997}
4998
Jim Grosbach189610f2011-07-26 18:25:39 +00004999// FIXME: We would really like to be able to tablegen'erate this.
5000bool ARMAsmParser::
5001validateInstruction(MCInst &Inst,
5002 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005003 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005004 SMLoc Loc = Operands[0]->getStartLoc();
5005 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005006 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5007 // being allowed in IT blocks, but not being predicable. It just always
5008 // executes.
5009 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005010 unsigned bit = 1;
5011 if (ITState.FirstCond)
5012 ITState.FirstCond = false;
5013 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005014 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005015 // The instruction must be predicable.
5016 if (!MCID.isPredicable())
5017 return Error(Loc, "instructions in IT block must be predicable");
5018 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5019 unsigned ITCond = bit ? ITState.Cond :
5020 ARMCC::getOppositeCondition(ITState.Cond);
5021 if (Cond != ITCond) {
5022 // Find the condition code Operand to get its SMLoc information.
5023 SMLoc CondLoc;
5024 for (unsigned i = 1; i < Operands.size(); ++i)
5025 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5026 CondLoc = Operands[i]->getStartLoc();
5027 return Error(CondLoc, "incorrect condition in IT block; got '" +
5028 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5029 "', but expected '" +
5030 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5031 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005032 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005033 } else if (isThumbTwo() && MCID.isPredicable() &&
5034 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005035 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5036 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005037 return Error(Loc, "predicated instructions must be in IT block");
5038
Jim Grosbach189610f2011-07-26 18:25:39 +00005039 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005040 case ARM::LDRD:
5041 case ARM::LDRD_PRE:
5042 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005043 case ARM::LDREXD: {
5044 // Rt2 must be Rt + 1.
5045 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5046 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5047 if (Rt2 != Rt + 1)
5048 return Error(Operands[3]->getStartLoc(),
5049 "destination operands must be sequential");
5050 return false;
5051 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005052 case ARM::STRD: {
5053 // Rt2 must be Rt + 1.
5054 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5055 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5056 if (Rt2 != Rt + 1)
5057 return Error(Operands[3]->getStartLoc(),
5058 "source operands must be sequential");
5059 return false;
5060 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005061 case ARM::STRD_PRE:
5062 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005063 case ARM::STREXD: {
5064 // Rt2 must be Rt + 1.
5065 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5066 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5067 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005068 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005069 "source operands must be sequential");
5070 return false;
5071 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005072 case ARM::SBFX:
5073 case ARM::UBFX: {
5074 // width must be in range [1, 32-lsb]
5075 unsigned lsb = Inst.getOperand(2).getImm();
5076 unsigned widthm1 = Inst.getOperand(3).getImm();
5077 if (widthm1 >= 32 - lsb)
5078 return Error(Operands[5]->getStartLoc(),
5079 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005080 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005081 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005082 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005083 // If we're parsing Thumb2, the .w variant is available and handles
5084 // most cases that are normally illegal for a Thumb1 LDM
5085 // instruction. We'll make the transformation in processInstruction()
5086 // if necessary.
5087 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005088 // Thumb LDM instructions are writeback iff the base register is not
5089 // in the register list.
5090 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005091 bool hasWritebackToken =
5092 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5093 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005094 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005095 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005096 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5097 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005098 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005099 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005100 return Error(Operands[2]->getStartLoc(),
5101 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005102 // If we should not have writeback, there must not be a '!'. This is
5103 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005104 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005105 return Error(Operands[3]->getStartLoc(),
5106 "writeback operator '!' not allowed when base register "
5107 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005108
5109 break;
5110 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005111 case ARM::t2LDMIA_UPD: {
5112 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5113 return Error(Operands[4]->getStartLoc(),
5114 "writeback operator '!' not allowed when base register "
5115 "in register list");
5116 break;
5117 }
Jim Grosbach54026372011-11-10 23:17:11 +00005118 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5119 // so only issue a diagnostic for thumb1. The instructions will be
5120 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005121 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005122 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005123 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5124 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005125 return Error(Operands[2]->getStartLoc(),
5126 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005127 break;
5128 }
5129 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005130 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005131 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5132 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005133 return Error(Operands[2]->getStartLoc(),
5134 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005135 break;
5136 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005137 case ARM::tSTMIA_UPD: {
5138 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005139 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005140 return Error(Operands[4]->getStartLoc(),
5141 "registers must be in range r0-r7");
5142 break;
5143 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005144 }
5145
5146 return false;
5147}
5148
Jim Grosbach5b484312011-12-20 20:46:29 +00005149static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005150 switch(Opc) {
5151 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005152 // VST1LN
5153 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5154 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5155 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005156 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005157 return ARM::VST1LNd8_UPD;
5158 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5159 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5160 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005161 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005162 return ARM::VST1LNd16_UPD;
5163 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5164 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5165 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005166 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005167 return ARM::VST1LNd32_UPD;
5168 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5169 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5170 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005171 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005172 return ARM::VST1LNd8_UPD;
5173 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5174 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5175 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005176 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005177 return ARM::VST1LNd16_UPD;
5178 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5179 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5180 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005181 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005182 return ARM::VST1LNd32_UPD;
5183 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5184 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5185 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005186 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005187 return ARM::VST1LNd8;
5188 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5189 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5190 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005191 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005192 return ARM::VST1LNd16;
5193 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5194 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5195 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005196 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005197 return ARM::VST1LNd32;
5198
5199 // VST2LN
5200 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5201 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5202 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005203 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005204 return ARM::VST2LNd8_UPD;
5205 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5206 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5207 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005208 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005209 return ARM::VST2LNd16_UPD;
5210 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5211 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5212 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005213 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005214 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005215 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5216 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5217 case ARM::VST2LNqWB_fixed_Asm_U16:
5218 Spacing = 2;
5219 return ARM::VST2LNq16_UPD;
5220 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5221 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5222 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5223 Spacing = 2;
5224 return ARM::VST2LNq32_UPD;
5225
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005226 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5227 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5228 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005229 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005230 return ARM::VST2LNd8_UPD;
5231 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5232 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5233 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005234 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005235 return ARM::VST2LNd16_UPD;
5236 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5237 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5238 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005239 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005240 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005241 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5242 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5243 case ARM::VST2LNqWB_register_Asm_U16:
5244 Spacing = 2;
5245 return ARM::VST2LNq16_UPD;
5246 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5247 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5248 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5249 Spacing = 2;
5250 return ARM::VST2LNq32_UPD;
5251
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005252 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5253 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5254 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005255 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005256 return ARM::VST2LNd8;
5257 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5258 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5259 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005260 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005261 return ARM::VST2LNd16;
5262 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5263 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5264 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005265 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005266 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005267 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5268 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5269 case ARM::VST2LNqAsm_U16:
5270 Spacing = 2;
5271 return ARM::VST2LNq16;
5272 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5273 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5274 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5275 Spacing = 2;
5276 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005277 }
5278}
5279
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005280static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005281 switch(Opc) {
5282 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005283 // VLD1LN
5284 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5285 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5286 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005287 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005288 return ARM::VLD1LNd8_UPD;
5289 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5290 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5291 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005292 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005293 return ARM::VLD1LNd16_UPD;
5294 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5295 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5296 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005297 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005298 return ARM::VLD1LNd32_UPD;
5299 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5300 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5301 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005302 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005303 return ARM::VLD1LNd8_UPD;
5304 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5305 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5306 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005307 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005308 return ARM::VLD1LNd16_UPD;
5309 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5310 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5311 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005312 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005313 return ARM::VLD1LNd32_UPD;
5314 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5315 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5316 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005317 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005318 return ARM::VLD1LNd8;
5319 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5320 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5321 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005322 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005323 return ARM::VLD1LNd16;
5324 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5325 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5326 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005327 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005328 return ARM::VLD1LNd32;
5329
5330 // VLD2LN
5331 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5332 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5333 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005334 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005335 return ARM::VLD2LNd8_UPD;
5336 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5337 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5338 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005339 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005340 return ARM::VLD2LNd16_UPD;
5341 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5342 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5343 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005344 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005345 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005346 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5347 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5348 case ARM::VLD2LNqWB_fixed_Asm_U16:
5349 Spacing = 1;
5350 return ARM::VLD2LNq16_UPD;
5351 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5352 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5353 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5354 Spacing = 2;
5355 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005356 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5357 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5358 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005359 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005360 return ARM::VLD2LNd8_UPD;
5361 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5362 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5363 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005364 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005365 return ARM::VLD2LNd16_UPD;
5366 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5367 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5368 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005369 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005370 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005371 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5372 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5373 case ARM::VLD2LNqWB_register_Asm_U16:
5374 Spacing = 2;
5375 return ARM::VLD2LNq16_UPD;
5376 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5377 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5378 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5379 Spacing = 2;
5380 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005381 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5382 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5383 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005384 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005385 return ARM::VLD2LNd8;
5386 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5387 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5388 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005389 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005390 return ARM::VLD2LNd16;
5391 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5392 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5393 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005394 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005395 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005396 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5397 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5398 case ARM::VLD2LNqAsm_U16:
5399 Spacing = 2;
5400 return ARM::VLD2LNq16;
5401 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5402 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5403 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5404 Spacing = 2;
5405 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005406 }
5407}
5408
Jim Grosbach83ec8772011-11-10 23:42:14 +00005409bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005410processInstruction(MCInst &Inst,
5411 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5412 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005413 // Handle NEON VST complex aliases.
5414 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5415 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5416 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5417 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5418 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5419 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5420 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5421 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005422 MCInst TmpInst;
5423 // Shuffle the operands around so the lane index operand is in the
5424 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005425 unsigned Spacing;
5426 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005427 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5428 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5429 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5430 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5431 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5432 TmpInst.addOperand(Inst.getOperand(1)); // lane
5433 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5434 TmpInst.addOperand(Inst.getOperand(6));
5435 Inst = TmpInst;
5436 return true;
5437 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005438
Jim Grosbach5b484312011-12-20 20:46:29 +00005439 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5440 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5441 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005442 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5443 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005444 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005445 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005446 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5447 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5448 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5449 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5450 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5451 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5452 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005453 MCInst TmpInst;
5454 // Shuffle the operands around so the lane index operand is in the
5455 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005456 unsigned Spacing;
5457 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005458 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5459 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5460 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5461 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5462 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005463 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5464 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005465 TmpInst.addOperand(Inst.getOperand(1)); // lane
5466 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5467 TmpInst.addOperand(Inst.getOperand(6));
5468 Inst = TmpInst;
5469 return true;
5470 }
5471 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5472 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5473 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5474 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5475 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5476 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5477 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5478 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005479 MCInst TmpInst;
5480 // Shuffle the operands around so the lane index operand is in the
5481 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005482 unsigned Spacing;
5483 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005484 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5485 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5486 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5487 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5488 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5489 TmpInst.addOperand(Inst.getOperand(1)); // lane
5490 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5491 TmpInst.addOperand(Inst.getOperand(5));
5492 Inst = TmpInst;
5493 return true;
5494 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005495
Jim Grosbach5b484312011-12-20 20:46:29 +00005496 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5497 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5498 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005499 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5500 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005501 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005502 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005503 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5504 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5505 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5506 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5507 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5508 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5509 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005510 MCInst TmpInst;
5511 // Shuffle the operands around so the lane index operand is in the
5512 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005513 unsigned Spacing;
5514 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005515 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5516 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5517 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5518 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5519 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005520 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5521 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005522 TmpInst.addOperand(Inst.getOperand(1)); // lane
5523 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5524 TmpInst.addOperand(Inst.getOperand(5));
5525 Inst = TmpInst;
5526 return true;
5527 }
5528 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5529 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5530 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5531 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5532 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005533 case ARM::VST1LNdAsm_U32: {
5534 MCInst TmpInst;
5535 // Shuffle the operands around so the lane index operand is in the
5536 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005537 unsigned Spacing;
5538 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005539 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5540 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5541 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5542 TmpInst.addOperand(Inst.getOperand(1)); // lane
5543 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5544 TmpInst.addOperand(Inst.getOperand(5));
5545 Inst = TmpInst;
5546 return true;
5547 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005548
Jim Grosbach5b484312011-12-20 20:46:29 +00005549 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5550 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005551 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005552 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005553 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005554 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5555 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5556 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5557 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005558 MCInst TmpInst;
5559 // Shuffle the operands around so the lane index operand is in the
5560 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005561 unsigned Spacing;
5562 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005563 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5564 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5565 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005566 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5567 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005568 TmpInst.addOperand(Inst.getOperand(1)); // lane
5569 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5570 TmpInst.addOperand(Inst.getOperand(5));
5571 Inst = TmpInst;
5572 return true;
5573 }
5574 // Handle NEON VLD complex aliases.
5575 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5576 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5577 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5578 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5579 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5580 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5581 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5582 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005583 MCInst TmpInst;
5584 // Shuffle the operands around so the lane index operand is in the
5585 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005586 unsigned Spacing;
5587 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005588 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5589 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5590 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5591 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5592 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5593 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5594 TmpInst.addOperand(Inst.getOperand(1)); // lane
5595 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5596 TmpInst.addOperand(Inst.getOperand(6));
5597 Inst = TmpInst;
5598 return true;
5599 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005600
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005601 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5602 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5603 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005604 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5605 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005606 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005607 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005608 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005609 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5610 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5611 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5612 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5613 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5614 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005615 MCInst TmpInst;
5616 // Shuffle the operands around so the lane index operand is in the
5617 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005618 unsigned Spacing;
5619 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005620 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005621 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5622 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005623 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5624 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5625 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5626 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5627 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005628 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5629 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005630 TmpInst.addOperand(Inst.getOperand(1)); // lane
5631 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5632 TmpInst.addOperand(Inst.getOperand(6));
5633 Inst = TmpInst;
5634 return true;
5635 }
5636
5637 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5638 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5639 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5640 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5641 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5642 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5643 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5644 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005645 MCInst TmpInst;
5646 // Shuffle the operands around so the lane index operand is in the
5647 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005648 unsigned Spacing;
5649 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005650 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5651 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5652 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5653 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5654 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5655 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5656 TmpInst.addOperand(Inst.getOperand(1)); // lane
5657 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5658 TmpInst.addOperand(Inst.getOperand(5));
5659 Inst = TmpInst;
5660 return true;
5661 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005662
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005663 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5664 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5665 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005666 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5667 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005668 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005669 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005670 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005671 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5672 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5673 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5674 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5675 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5676 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005677 MCInst TmpInst;
5678 // Shuffle the operands around so the lane index operand is in the
5679 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005680 unsigned Spacing;
5681 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005682 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005683 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5684 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005685 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5686 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5687 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5688 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5689 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005690 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5691 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005692 TmpInst.addOperand(Inst.getOperand(1)); // lane
5693 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5694 TmpInst.addOperand(Inst.getOperand(5));
5695 Inst = TmpInst;
5696 return true;
5697 }
5698
Jim Grosbach5b484312011-12-20 20:46:29 +00005699 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5700 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005701 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005702 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005703 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005704 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005705 MCInst TmpInst;
5706 // Shuffle the operands around so the lane index operand is in the
5707 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005708 unsigned Spacing;
5709 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005710 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5711 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5712 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5713 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5714 TmpInst.addOperand(Inst.getOperand(1)); // lane
5715 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5716 TmpInst.addOperand(Inst.getOperand(5));
5717 Inst = TmpInst;
5718 return true;
5719 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005720
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005721 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5722 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005723 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005724 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005725 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005726 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5727 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5728 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5729 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5730 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005731 MCInst TmpInst;
5732 // Shuffle the operands around so the lane index operand is in the
5733 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005734 unsigned Spacing;
5735 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005736 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005737 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5738 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005739 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5740 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5741 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005742 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5743 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005744 TmpInst.addOperand(Inst.getOperand(1)); // lane
5745 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5746 TmpInst.addOperand(Inst.getOperand(5));
5747 Inst = TmpInst;
5748 return true;
5749 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005750 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00005751 case ARM::t2MOVsr:
5752 case ARM::t2MOVSsr: {
5753 // Which instruction to expand to depends on the CCOut operand and
5754 // whether we're in an IT block if the register operands are low
5755 // registers.
5756 bool isNarrow = false;
5757 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5758 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5759 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5760 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5761 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5762 isNarrow = true;
5763 MCInst TmpInst;
5764 unsigned newOpc;
5765 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5766 default: llvm_unreachable("unexpected opcode!");
5767 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5768 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5769 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5770 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5771 }
5772 TmpInst.setOpcode(newOpc);
5773 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5774 if (isNarrow)
5775 TmpInst.addOperand(MCOperand::CreateReg(
5776 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5777 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5778 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5779 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5780 TmpInst.addOperand(Inst.getOperand(5));
5781 if (!isNarrow)
5782 TmpInst.addOperand(MCOperand::CreateReg(
5783 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5784 Inst = TmpInst;
5785 return true;
5786 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005787 case ARM::t2MOVsi:
5788 case ARM::t2MOVSsi: {
5789 // Which instruction to expand to depends on the CCOut operand and
5790 // whether we're in an IT block if the register operands are low
5791 // registers.
5792 bool isNarrow = false;
5793 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5794 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5795 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5796 isNarrow = true;
5797 MCInst TmpInst;
5798 unsigned newOpc;
5799 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5800 default: llvm_unreachable("unexpected opcode!");
5801 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5802 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5803 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5804 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5805 }
5806 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5807 if (Ammount == 32) Ammount = 0;
5808 TmpInst.setOpcode(newOpc);
5809 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5810 if (isNarrow)
5811 TmpInst.addOperand(MCOperand::CreateReg(
5812 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5813 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5814 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5815 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5816 TmpInst.addOperand(Inst.getOperand(4));
5817 if (!isNarrow)
5818 TmpInst.addOperand(MCOperand::CreateReg(
5819 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5820 Inst = TmpInst;
5821 return true;
5822 }
5823 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005824 case ARM::ASRr:
5825 case ARM::LSRr:
5826 case ARM::LSLr:
5827 case ARM::RORr: {
5828 ARM_AM::ShiftOpc ShiftTy;
5829 switch(Inst.getOpcode()) {
5830 default: llvm_unreachable("unexpected opcode!");
5831 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5832 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5833 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5834 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5835 }
5836 // A shift by zero is a plain MOVr, not a MOVsi.
5837 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5838 MCInst TmpInst;
5839 TmpInst.setOpcode(ARM::MOVsr);
5840 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5841 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5842 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5843 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5844 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5845 TmpInst.addOperand(Inst.getOperand(4));
5846 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5847 Inst = TmpInst;
5848 return true;
5849 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005850 case ARM::ASRi:
5851 case ARM::LSRi:
5852 case ARM::LSLi:
5853 case ARM::RORi: {
5854 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005855 switch(Inst.getOpcode()) {
5856 default: llvm_unreachable("unexpected opcode!");
5857 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5858 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5859 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5860 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5861 }
5862 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005863 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005864 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5865 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005866 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005867 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005868 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5869 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005870 if (Opc == ARM::MOVsi)
5871 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005872 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5873 TmpInst.addOperand(Inst.getOperand(4));
5874 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5875 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005876 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005877 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005878 case ARM::RRXi: {
5879 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5880 MCInst TmpInst;
5881 TmpInst.setOpcode(ARM::MOVsi);
5882 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5883 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5884 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5885 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5886 TmpInst.addOperand(Inst.getOperand(3));
5887 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5888 Inst = TmpInst;
5889 return true;
5890 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005891 case ARM::t2LDMIA_UPD: {
5892 // If this is a load of a single register, then we should use
5893 // a post-indexed LDR instruction instead, per the ARM ARM.
5894 if (Inst.getNumOperands() != 5)
5895 return false;
5896 MCInst TmpInst;
5897 TmpInst.setOpcode(ARM::t2LDR_POST);
5898 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5899 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5900 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5901 TmpInst.addOperand(MCOperand::CreateImm(4));
5902 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5903 TmpInst.addOperand(Inst.getOperand(3));
5904 Inst = TmpInst;
5905 return true;
5906 }
5907 case ARM::t2STMDB_UPD: {
5908 // If this is a store of a single register, then we should use
5909 // a pre-indexed STR instruction instead, per the ARM ARM.
5910 if (Inst.getNumOperands() != 5)
5911 return false;
5912 MCInst TmpInst;
5913 TmpInst.setOpcode(ARM::t2STR_PRE);
5914 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5915 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5916 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5917 TmpInst.addOperand(MCOperand::CreateImm(-4));
5918 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5919 TmpInst.addOperand(Inst.getOperand(3));
5920 Inst = TmpInst;
5921 return true;
5922 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005923 case ARM::LDMIA_UPD:
5924 // If this is a load of a single register via a 'pop', then we should use
5925 // a post-indexed LDR instruction instead, per the ARM ARM.
5926 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5927 Inst.getNumOperands() == 5) {
5928 MCInst TmpInst;
5929 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5930 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5931 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5932 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5933 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5934 TmpInst.addOperand(MCOperand::CreateImm(4));
5935 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5936 TmpInst.addOperand(Inst.getOperand(3));
5937 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005938 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005939 }
5940 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005941 case ARM::STMDB_UPD:
5942 // If this is a store of a single register via a 'push', then we should use
5943 // a pre-indexed STR instruction instead, per the ARM ARM.
5944 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5945 Inst.getNumOperands() == 5) {
5946 MCInst TmpInst;
5947 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5948 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5949 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5950 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5951 TmpInst.addOperand(MCOperand::CreateImm(-4));
5952 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5953 TmpInst.addOperand(Inst.getOperand(3));
5954 Inst = TmpInst;
5955 }
5956 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005957 case ARM::t2ADDri12:
5958 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5959 // mnemonic was used (not "addw"), encoding T3 is preferred.
5960 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5961 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5962 break;
5963 Inst.setOpcode(ARM::t2ADDri);
5964 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5965 break;
5966 case ARM::t2SUBri12:
5967 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5968 // mnemonic was used (not "subw"), encoding T3 is preferred.
5969 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5970 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5971 break;
5972 Inst.setOpcode(ARM::t2SUBri);
5973 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5974 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005975 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005976 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5977 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5978 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5979 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005980 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005981 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005982 return true;
5983 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005984 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005985 case ARM::tSUBi8:
5986 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5987 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5988 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5989 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005990 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005991 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005992 return true;
5993 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005994 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005995 case ARM::t2ADDrr: {
5996 // If the destination and first source operand are the same, and
5997 // there's no setting of the flags, use encoding T2 instead of T3.
5998 // Note that this is only for ADD, not SUB. This mirrors the system
5999 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6000 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6001 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006002 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6003 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006004 break;
6005 MCInst TmpInst;
6006 TmpInst.setOpcode(ARM::tADDhirr);
6007 TmpInst.addOperand(Inst.getOperand(0));
6008 TmpInst.addOperand(Inst.getOperand(0));
6009 TmpInst.addOperand(Inst.getOperand(2));
6010 TmpInst.addOperand(Inst.getOperand(3));
6011 TmpInst.addOperand(Inst.getOperand(4));
6012 Inst = TmpInst;
6013 return true;
6014 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006015 case ARM::tB:
6016 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006017 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006018 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006019 return true;
6020 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006021 break;
6022 case ARM::t2B:
6023 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006024 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006025 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006026 return true;
6027 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006028 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006029 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006030 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006031 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006032 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006033 return true;
6034 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006035 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006036 case ARM::tBcc:
6037 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006038 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006039 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006040 return true;
6041 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006042 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006043 case ARM::tLDMIA: {
6044 // If the register list contains any high registers, or if the writeback
6045 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6046 // instead if we're in Thumb2. Otherwise, this should have generated
6047 // an error in validateInstruction().
6048 unsigned Rn = Inst.getOperand(0).getReg();
6049 bool hasWritebackToken =
6050 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6051 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6052 bool listContainsBase;
6053 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6054 (!listContainsBase && !hasWritebackToken) ||
6055 (listContainsBase && hasWritebackToken)) {
6056 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6057 assert (isThumbTwo());
6058 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6059 // If we're switching to the updating version, we need to insert
6060 // the writeback tied operand.
6061 if (hasWritebackToken)
6062 Inst.insert(Inst.begin(),
6063 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006064 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006065 }
6066 break;
6067 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006068 case ARM::tSTMIA_UPD: {
6069 // If the register list contains any high registers, we need to use
6070 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6071 // should have generated an error in validateInstruction().
6072 unsigned Rn = Inst.getOperand(0).getReg();
6073 bool listContainsBase;
6074 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6075 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6076 assert (isThumbTwo());
6077 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006078 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006079 }
6080 break;
6081 }
Jim Grosbach54026372011-11-10 23:17:11 +00006082 case ARM::tPOP: {
6083 bool listContainsBase;
6084 // If the register list contains any high registers, we need to use
6085 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6086 // should have generated an error in validateInstruction().
6087 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006088 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006089 assert (isThumbTwo());
6090 Inst.setOpcode(ARM::t2LDMIA_UPD);
6091 // Add the base register and writeback operands.
6092 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6093 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006094 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006095 }
6096 case ARM::tPUSH: {
6097 bool listContainsBase;
6098 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006099 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006100 assert (isThumbTwo());
6101 Inst.setOpcode(ARM::t2STMDB_UPD);
6102 // Add the base register and writeback operands.
6103 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6104 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006105 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006106 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006107 case ARM::t2MOVi: {
6108 // If we can use the 16-bit encoding and the user didn't explicitly
6109 // request the 32-bit variant, transform it here.
6110 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6111 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006112 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6113 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6114 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006115 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6116 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6117 // The operands aren't in the same order for tMOVi8...
6118 MCInst TmpInst;
6119 TmpInst.setOpcode(ARM::tMOVi8);
6120 TmpInst.addOperand(Inst.getOperand(0));
6121 TmpInst.addOperand(Inst.getOperand(4));
6122 TmpInst.addOperand(Inst.getOperand(1));
6123 TmpInst.addOperand(Inst.getOperand(2));
6124 TmpInst.addOperand(Inst.getOperand(3));
6125 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006126 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006127 }
6128 break;
6129 }
6130 case ARM::t2MOVr: {
6131 // If we can use the 16-bit encoding and the user didn't explicitly
6132 // request the 32-bit variant, transform it here.
6133 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6134 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6135 Inst.getOperand(2).getImm() == ARMCC::AL &&
6136 Inst.getOperand(4).getReg() == ARM::CPSR &&
6137 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6138 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6139 // The operands aren't the same for tMOV[S]r... (no cc_out)
6140 MCInst TmpInst;
6141 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6142 TmpInst.addOperand(Inst.getOperand(0));
6143 TmpInst.addOperand(Inst.getOperand(1));
6144 TmpInst.addOperand(Inst.getOperand(2));
6145 TmpInst.addOperand(Inst.getOperand(3));
6146 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006147 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006148 }
6149 break;
6150 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006151 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006152 case ARM::t2SXTB:
6153 case ARM::t2UXTH:
6154 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006155 // If we can use the 16-bit encoding and the user didn't explicitly
6156 // request the 32-bit variant, transform it here.
6157 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6158 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6159 Inst.getOperand(2).getImm() == 0 &&
6160 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6161 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006162 unsigned NewOpc;
6163 switch (Inst.getOpcode()) {
6164 default: llvm_unreachable("Illegal opcode!");
6165 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6166 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6167 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6168 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6169 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006170 // The operands aren't the same for thumb1 (no rotate operand).
6171 MCInst TmpInst;
6172 TmpInst.setOpcode(NewOpc);
6173 TmpInst.addOperand(Inst.getOperand(0));
6174 TmpInst.addOperand(Inst.getOperand(1));
6175 TmpInst.addOperand(Inst.getOperand(3));
6176 TmpInst.addOperand(Inst.getOperand(4));
6177 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006178 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006179 }
6180 break;
6181 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006182 case ARM::MOVsi: {
6183 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6184 if (SOpc == ARM_AM::rrx) return false;
6185 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6186 // Shifting by zero is accepted as a vanilla 'MOVr'
6187 MCInst TmpInst;
6188 TmpInst.setOpcode(ARM::MOVr);
6189 TmpInst.addOperand(Inst.getOperand(0));
6190 TmpInst.addOperand(Inst.getOperand(1));
6191 TmpInst.addOperand(Inst.getOperand(3));
6192 TmpInst.addOperand(Inst.getOperand(4));
6193 TmpInst.addOperand(Inst.getOperand(5));
6194 Inst = TmpInst;
6195 return true;
6196 }
6197 return false;
6198 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006199 case ARM::t2IT: {
6200 // The mask bits for all but the first condition are represented as
6201 // the low bit of the condition code value implies 't'. We currently
6202 // always have 1 implies 't', so XOR toggle the bits if the low bit
6203 // of the condition code is zero. The encoding also expects the low
6204 // bit of the condition to be encoded as bit 4 of the mask operand,
6205 // so mask that in if needed
6206 MCOperand &MO = Inst.getOperand(1);
6207 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006208 unsigned OrigMask = Mask;
6209 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006210 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006211 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6212 for (unsigned i = 3; i != TZ; --i)
6213 Mask ^= 1 << i;
6214 } else
6215 Mask |= 0x10;
6216 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006217
6218 // Set up the IT block state according to the IT instruction we just
6219 // matched.
6220 assert(!inITBlock() && "nested IT blocks?!");
6221 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6222 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6223 ITState.CurPosition = 0;
6224 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006225 break;
6226 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006227 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006228 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006229}
6230
Jim Grosbach47a0d522011-08-16 20:45:50 +00006231unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6232 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6233 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006234 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006235 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006236 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6237 assert(MCID.hasOptionalDef() &&
6238 "optionally flag setting instruction missing optional def operand");
6239 assert(MCID.NumOperands == Inst.getNumOperands() &&
6240 "operand count mismatch!");
6241 // Find the optional-def operand (cc_out).
6242 unsigned OpNo;
6243 for (OpNo = 0;
6244 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6245 ++OpNo)
6246 ;
6247 // If we're parsing Thumb1, reject it completely.
6248 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6249 return Match_MnemonicFail;
6250 // If we're parsing Thumb2, which form is legal depends on whether we're
6251 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006252 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6253 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006254 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006255 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6256 inITBlock())
6257 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006258 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006259 // Some high-register supporting Thumb1 encodings only allow both registers
6260 // to be from r0-r7 when in Thumb2.
6261 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6262 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6263 isARMLowRegister(Inst.getOperand(2).getReg()))
6264 return Match_RequiresThumb2;
6265 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006266 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006267 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6268 isARMLowRegister(Inst.getOperand(1).getReg()))
6269 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006270 return Match_Success;
6271}
6272
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006273bool ARMAsmParser::
6274MatchAndEmitInstruction(SMLoc IDLoc,
6275 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6276 MCStreamer &Out) {
6277 MCInst Inst;
6278 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006279 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006280 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006281 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006282 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006283 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006284 // Context sensitive operand constraints aren't handled by the matcher,
6285 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006286 if (validateInstruction(Inst, Operands)) {
6287 // Still progress the IT block, otherwise one wrong condition causes
6288 // nasty cascading errors.
6289 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006290 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006291 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006292
Jim Grosbachf8fce712011-08-11 17:35:48 +00006293 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006294 // encoding is selected. Loop on it while changes happen so the
6295 // individual transformations can chain off each other. E.g.,
6296 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6297 while (processInstruction(Inst, Operands))
6298 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006299
Jim Grosbacha1109882011-09-02 23:22:08 +00006300 // Only move forward at the very end so that everything in validate
6301 // and process gets a consistent answer about whether we're in an IT
6302 // block.
6303 forwardITPosition();
6304
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006305 Out.EmitInstruction(Inst);
6306 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006307 case Match_MissingFeature:
6308 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6309 return true;
6310 case Match_InvalidOperand: {
6311 SMLoc ErrorLoc = IDLoc;
6312 if (ErrorInfo != ~0U) {
6313 if (ErrorInfo >= Operands.size())
6314 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006315
Chris Lattnere73d4f82010-10-28 21:41:58 +00006316 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6317 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6318 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006319
Chris Lattnere73d4f82010-10-28 21:41:58 +00006320 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006321 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006322 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006323 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006324 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006325 // The converter function will have already emited a diagnostic.
6326 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006327 case Match_RequiresNotITBlock:
6328 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006329 case Match_RequiresITBlock:
6330 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006331 case Match_RequiresV6:
6332 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6333 case Match_RequiresThumb2:
6334 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006335 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006336
Eric Christopherc223e2b2010-10-29 09:26:59 +00006337 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006338 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006339}
6340
Jim Grosbach1355cf12011-07-26 17:10:22 +00006341/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006342bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6343 StringRef IDVal = DirectiveID.getIdentifier();
6344 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006345 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006346 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006347 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006348 else if (IDVal == ".arm")
6349 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006350 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006351 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006352 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006353 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006354 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006355 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006356 else if (IDVal == ".unreq")
6357 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006358 else if (IDVal == ".arch")
6359 return parseDirectiveArch(DirectiveID.getLoc());
6360 else if (IDVal == ".eabi_attribute")
6361 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006362 return true;
6363}
6364
Jim Grosbach1355cf12011-07-26 17:10:22 +00006365/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006366/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006367bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006368 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6369 for (;;) {
6370 const MCExpr *Value;
6371 if (getParser().ParseExpression(Value))
6372 return true;
6373
Chris Lattneraaec2052010-01-19 19:46:13 +00006374 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006375
6376 if (getLexer().is(AsmToken::EndOfStatement))
6377 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006378
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006379 // FIXME: Improve diagnostic.
6380 if (getLexer().isNot(AsmToken::Comma))
6381 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006382 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006383 }
6384 }
6385
Sean Callananb9a25b72010-01-19 20:27:46 +00006386 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006387 return false;
6388}
6389
Jim Grosbach1355cf12011-07-26 17:10:22 +00006390/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006391/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006392bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006393 if (getLexer().isNot(AsmToken::EndOfStatement))
6394 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006395 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006396
Jim Grosbach9a70df92011-12-07 18:04:19 +00006397 if (!isThumb())
6398 SwitchMode();
6399 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6400 return false;
6401}
6402
6403/// parseDirectiveARM
6404/// ::= .arm
6405bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6406 if (getLexer().isNot(AsmToken::EndOfStatement))
6407 return Error(L, "unexpected token in directive");
6408 Parser.Lex();
6409
6410 if (isThumb())
6411 SwitchMode();
6412 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006413 return false;
6414}
6415
Jim Grosbach1355cf12011-07-26 17:10:22 +00006416/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006417/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006418bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006419 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6420 bool isMachO = MAI.hasSubsectionsViaSymbols();
6421 StringRef Name;
6422
6423 // Darwin asm has function name after .thumb_func direction
6424 // ELF doesn't
6425 if (isMachO) {
6426 const AsmToken &Tok = Parser.getTok();
6427 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6428 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00006429 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006430 Parser.Lex(); // Consume the identifier token.
6431 }
6432
Jim Grosbachd475f862011-11-10 20:48:53 +00006433 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006434 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006435 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006436
Rafael Espindola64695402011-05-16 16:17:21 +00006437 // FIXME: assuming function name will be the line following .thumb_func
6438 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006439 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006440 }
6441
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006442 // Mark symbol as a thumb symbol.
6443 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6444 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006445 return false;
6446}
6447
Jim Grosbach1355cf12011-07-26 17:10:22 +00006448/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006449/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006450bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006451 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006452 if (Tok.isNot(AsmToken::Identifier))
6453 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006454 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006455 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006456 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006457 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006458 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006459 else
6460 return Error(L, "unrecognized syntax mode in .syntax directive");
6461
6462 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006463 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006464 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006465
6466 // TODO tell the MC streamer the mode
6467 // getParser().getStreamer().Emit???();
6468 return false;
6469}
6470
Jim Grosbach1355cf12011-07-26 17:10:22 +00006471/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006472/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006473bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006474 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006475 if (Tok.isNot(AsmToken::Integer))
6476 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006477 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006478 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006479 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006480 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006481 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006482 else
6483 return Error(L, "invalid operand to .code directive");
6484
6485 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006486 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006487 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006488
Evan Cheng32869202011-07-08 22:36:29 +00006489 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006490 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006491 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006492 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006493 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006494 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006495 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006496 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006497 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006498
Kevin Enderby515d5092009-10-15 20:48:48 +00006499 return false;
6500}
6501
Jim Grosbacha39cda72011-12-14 02:16:11 +00006502/// parseDirectiveReq
6503/// ::= name .req registername
6504bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6505 Parser.Lex(); // Eat the '.req' token.
6506 unsigned Reg;
6507 SMLoc SRegLoc, ERegLoc;
6508 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6509 Parser.EatToEndOfStatement();
6510 return Error(SRegLoc, "register name expected");
6511 }
6512
6513 // Shouldn't be anything else.
6514 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6515 Parser.EatToEndOfStatement();
6516 return Error(Parser.getTok().getLoc(),
6517 "unexpected input in .req directive.");
6518 }
6519
6520 Parser.Lex(); // Consume the EndOfStatement
6521
6522 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6523 return Error(SRegLoc, "redefinition of '" + Name +
6524 "' does not match original.");
6525
6526 return false;
6527}
6528
6529/// parseDirectiveUneq
6530/// ::= .unreq registername
6531bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6532 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6533 Parser.EatToEndOfStatement();
6534 return Error(L, "unexpected input in .unreq directive.");
6535 }
6536 RegisterReqs.erase(Parser.getTok().getIdentifier());
6537 Parser.Lex(); // Eat the identifier.
6538 return false;
6539}
6540
Jason W Kimd7c9e082011-12-20 17:38:12 +00006541/// parseDirectiveArch
6542/// ::= .arch token
6543bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6544 return true;
6545}
6546
6547/// parseDirectiveEabiAttr
6548/// ::= .eabi_attribute int, int
6549bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6550 return true;
6551}
6552
Sean Callanan90b70972010-04-07 20:29:34 +00006553extern "C" void LLVMInitializeARMAsmLexer();
6554
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006555/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006556extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006557 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6558 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006559 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006560}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006561
Chris Lattner0692ee62010-09-06 19:11:01 +00006562#define GET_REGISTER_MATCHER
6563#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006564#include "ARMGenAsmMatcher.inc"