blob: 9bc4e60863df6f131a977b6d2f95e5117e5719de [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_MemBarrierOpt,
274 k_Memory,
275 k_PostIndexRegister,
276 k_MSRMask,
277 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000278 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_Register,
280 k_RegisterList,
281 k_DPRRegisterList,
282 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000283 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000284 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000285 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000286 k_ShiftedRegister,
287 k_ShiftedImmediate,
288 k_ShifterImmediate,
289 k_RotateImmediate,
290 k_BitfieldDescriptor,
291 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000292 } Kind;
293
Sean Callanan76264762010-04-02 22:27:05 +0000294 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000295 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296
297 union {
298 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000299 ARMCC::CondCodes Val;
300 } CC;
301
302 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000303 unsigned Val;
304 } Cop;
305
306 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000307 unsigned Val;
308 } CoprocOption;
309
310 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000311 unsigned Mask:4;
312 } ITMask;
313
314 struct {
315 ARM_MB::MemBOpt Val;
316 } MBOpt;
317
318 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000319 ARM_PROC::IFlags Val;
320 } IFlags;
321
322 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000323 unsigned Val;
324 } MMask;
325
326 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 const char *Data;
328 unsigned Length;
329 } Tok;
330
331 struct {
332 unsigned RegNum;
333 } Reg;
334
Jim Grosbach862019c2011-10-18 23:02:30 +0000335 // A vector register list is a sequential list of 1 to 4 registers.
336 struct {
337 unsigned RegNum;
338 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000339 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000340 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000341 } VectorList;
342
Bill Wendling8155e5b2010-11-06 22:19:43 +0000343 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000344 unsigned Val;
345 } VectorIndex;
346
347 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000348 const MCExpr *Val;
349 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000350
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000351 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000352 struct {
353 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000354 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
355 // was specified.
356 const MCConstantExpr *OffsetImm; // Offset immediate value
357 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
358 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000359 unsigned ShiftImm; // shift for OffsetReg.
360 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000361 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000362 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000363 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000364
365 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000366 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000367 bool isAdd;
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000370 } PostIdxReg;
371
372 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000373 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000374 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000375 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftReg;
380 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000381 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000382 struct {
383 ARM_AM::ShiftOpc ShiftTy;
384 unsigned SrcReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000387 struct {
388 unsigned Imm;
389 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000390 struct {
391 unsigned LSB;
392 unsigned Width;
393 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000394 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000395
Bill Wendling146018f2010-11-06 21:42:12 +0000396 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
397public:
Sean Callanan76264762010-04-02 22:27:05 +0000398 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
399 Kind = o.Kind;
400 StartLoc = o.StartLoc;
401 EndLoc = o.EndLoc;
402 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000404 CC = o.CC;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000407 ITMask = o.ITMask;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000410 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_CCOut:
413 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000414 Reg = o.Reg;
415 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_RegisterList:
417 case k_DPRRegisterList:
418 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000419 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000420 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000422 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000423 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000424 VectorList = o.VectorList;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_CoprocNum:
427 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000428 Cop = o.Cop;
429 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000430 case k_CoprocOption:
431 CoprocOption = o.CoprocOption;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000434 Imm = o.Imm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000504 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach460a9052011-10-07 23:56:00 +0000508 unsigned getVectorIndex() const {
509 assert(Kind == k_VectorIndex && "Invalid access!");
510 return VectorIndex.Val;
511 }
512
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000513 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000514 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000515 return MBOpt.Val;
516 }
517
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000518 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000520 return IFlags.Val;
521 }
522
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000523 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000525 return MMask.Val;
526 }
527
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 bool isCoprocNum() const { return Kind == k_CoprocNum; }
529 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000530 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000531 bool isCondCode() const { return Kind == k_CondCode; }
532 bool isCCOut() const { return Kind == k_CCOut; }
533 bool isITMask() const { return Kind == k_ITCondMask; }
534 bool isITCondCode() const { return Kind == k_CondCode; }
535 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000536 bool isFPImm() const {
537 if (!isImm()) return false;
538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
539 if (!CE) return false;
540 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
541 return Val != -1;
542 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000543 bool isFBits16() const {
544 if (!isImm()) return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return Value >= 0 && Value <= 16;
549 }
550 bool isFBits32() const {
551 if (!isImm()) return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return Value >= 1 && Value <= 32;
556 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000557 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000558 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
563 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000564 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
570 }
571 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000572 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
577 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000578 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return Value >= 0 && Value < 256;
584 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000585 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 2;
591 }
592 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000593 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
595 if (!CE) return false;
596 int64_t Value = CE->getValue();
597 return Value >= 0 && Value < 4;
598 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000599 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000607 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 16;
612 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000613 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 32;
619 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000620 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000627 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value == 8;
633 }
634 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000635 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000636 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
637 if (!CE) return false;
638 int64_t Value = CE->getValue();
639 return Value == 16;
640 }
641 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000642 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value == 32;
647 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000648 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 8;
654 }
655 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000656 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 16;
661 }
662 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000663 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000664 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665 if (!CE) return false;
666 int64_t Value = CE->getValue();
667 return Value > 0 && Value <= 32;
668 }
669 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000670 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value <= 64;
675 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000676 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value < 8;
682 }
683 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000684 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
686 if (!CE) return false;
687 int64_t Value = CE->getValue();
688 return Value > 0 && Value < 16;
689 }
690 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000691 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000692 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693 if (!CE) return false;
694 int64_t Value = CE->getValue();
695 return Value > 0 && Value < 32;
696 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000697 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 17;
703 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000704 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 33;
710 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000711 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value >= 0 && Value < 33;
717 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000718 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 65536;
724 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000725 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 // If it's not a constant expression, it'll generate a fixup and be
729 // handled later.
730 if (!CE) return true;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 65536;
733 }
Jim Grosbached838482011-07-26 16:24:27 +0000734 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value <= 0xffffff;
740 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000741 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value > 0 && Value < 33;
747 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000748 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 32;
754 }
755 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value > 0 && Value <= 32;
761 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000762 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return ARM_AM::getSOImmVal(Value) != -1;
768 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000769 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return ARM_AM::getSOImmVal(~Value) != -1;
775 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000776 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779 if (!CE) return false;
780 int64_t Value = CE->getValue();
781 return ARM_AM::getSOImmVal(-Value) != -1;
782 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000783 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getT2SOImmVal(Value) != -1;
789 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000790 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getT2SOImmVal(~Value) != -1;
796 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000797 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800 if (!CE) return false;
801 int64_t Value = CE->getValue();
802 return ARM_AM::getT2SOImmVal(-Value) != -1;
803 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000804 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return Value == 1 || Value == 0;
810 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000811 bool isReg() const { return Kind == k_Register; }
812 bool isRegList() const { return Kind == k_RegisterList; }
813 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
814 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
815 bool isToken() const { return Kind == k_Token; }
816 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
817 bool isMemory() const { return Kind == k_Memory; }
818 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
819 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
820 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
821 bool isRotImm() const { return Kind == k_RotateImmediate; }
822 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
823 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000824 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000825 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000826 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000828 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000829 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
832 (alignOK || Memory.Alignment == 0);
833 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000834 bool isMemPCRelImm12() const {
835 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
836 return false;
837 // Base register must be PC.
838 if (Memory.BaseRegNum != ARM::PC)
839 return false;
840 // Immediate offset in range [-4095, 4095].
841 if (!Memory.OffsetImm) return true;
842 int64_t Val = Memory.OffsetImm->getValue();
843 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
844 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 bool isAlignedMemory() const {
846 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000847 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000848 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000849 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000850 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000852 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000853 if (!Memory.OffsetImm) return true;
854 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000855 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000856 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000857 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000858 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000859 // Immediate offset in range [-4095, 4095].
860 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
861 if (!CE) return false;
862 int64_t Val = CE->getValue();
863 return Val > -4096 && Val < 4096;
864 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000865 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000866 // If we have an immediate that's not a constant, treat it as a label
867 // reference needing a fixup. If it is a constant, it's something else
868 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000869 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000870 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000871 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000872 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000873 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000874 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000875 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000876 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (!Memory.OffsetImm) return true;
878 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000879 return Val > -256 && Val < 256;
880 }
881 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000882 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000884 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
886 // Immediate offset in range [-255, 255].
887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
888 if (!CE) return false;
889 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000890 // Special case, #-0 is INT32_MIN.
891 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000892 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000894 // If we have an immediate that's not a constant, treat it as a label
895 // reference needing a fixup. If it is a constant, it's something else
896 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000897 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000898 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000899 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000900 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000901 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000902 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000905 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000906 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000907 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000908 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000910 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000911 return false;
912 return true;
913 }
914 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
917 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000918 return false;
919 return true;
920 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000923 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000924 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000925 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000926 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000927 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
928 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000929 return false;
930 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000931 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000932 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000933 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000934 return false;
935 return true;
936 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000937 bool isMemThumbRR() const {
938 // Thumb reg+reg addressing is simple. Just two registers, a base and
939 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000940 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000942 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 return isARMLowRegister(Memory.BaseRegNum) &&
944 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000945 }
946 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000949 return false;
950 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000953 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
954 }
Jim Grosbach38466302011-08-19 18:55:51 +0000955 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000958 return false;
959 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000962 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
963 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000964 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000966 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000967 return false;
968 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000969 if (!Memory.OffsetImm) return true;
970 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000971 return Val >= 0 && Val <= 31;
972 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000973 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000974 if (!isMemory() || Memory.OffsetRegNum != 0 ||
975 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000976 return false;
977 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000978 if (!Memory.OffsetImm) return true;
979 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000980 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000981 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000982 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000983 // If we have an immediate that's not a constant, treat it as a label
984 // reference needing a fixup. If it is a constant, it's something else
985 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000986 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000987 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000988 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000989 return false;
990 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000991 if (!Memory.OffsetImm) return true;
992 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
994 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000995 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000996 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000997 return false;
998 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!Memory.OffsetImm) return true;
1000 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1002 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001003 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001004 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001005 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001006 // Base reg of PC isn't allowed for these encodings.
1007 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001008 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001009 if (!Memory.OffsetImm) return true;
1010 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001011 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001013 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001014 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001015 return false;
1016 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001017 if (!Memory.OffsetImm) return true;
1018 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return Val >= 0 && Val < 256;
1020 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001021 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001022 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001023 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001024 // Base reg of PC isn't allowed for these encodings.
1025 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001026 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001027 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001028 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001029 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001030 }
1031 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001032 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001033 return false;
1034 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001035 if (!Memory.OffsetImm) return true;
1036 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001037 return (Val >= 0 && Val < 4096);
1038 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001039 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001040 // If we have an immediate that's not a constant, treat it as a label
1041 // reference needing a fixup. If it is a constant, it's something else
1042 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001043 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001044 return true;
1045
Jim Grosbach57dcb852011-10-11 17:29:55 +00001046 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001047 return false;
1048 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001049 if (!Memory.OffsetImm) return true;
1050 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001051 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001052 }
1053 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001054 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 if (!CE) return false;
1057 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001058 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001059 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001060 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001061 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001062 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1063 if (!CE) return false;
1064 int64_t Val = CE->getValue();
1065 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1066 (Val == INT32_MIN);
1067 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001068
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 bool isMSRMask() const { return Kind == k_MSRMask; }
1070 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001071
Jim Grosbach0e387b22011-10-17 22:26:03 +00001072 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001073 bool isSingleSpacedVectorList() const {
1074 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1075 }
1076 bool isDoubleSpacedVectorList() const {
1077 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1078 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001079 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001080 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001081 return VectorList.Count == 1;
1082 }
1083
Jim Grosbach280dfad2011-10-21 18:54:25 +00001084 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001085 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001086 return VectorList.Count == 2;
1087 }
1088
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001089 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001091 return VectorList.Count == 3;
1092 }
1093
Jim Grosbachb6310312011-10-21 20:35:01 +00001094 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001096 return VectorList.Count == 4;
1097 }
1098
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001099 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001100 if (!isDoubleSpacedVectorList()) return false;
1101 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001102 }
1103
Jim Grosbachc387fc62012-01-23 23:20:46 +00001104 bool isVecListThreeQ() const {
1105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 3;
1107 }
1108
Jim Grosbach7945ead2012-01-24 00:43:12 +00001109 bool isVecListFourQ() const {
1110 if (!isDoubleSpacedVectorList()) return false;
1111 return VectorList.Count == 4;
1112 }
1113
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001114 bool isSingleSpacedVectorAllLanes() const {
1115 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1116 }
1117 bool isDoubleSpacedVectorAllLanes() const {
1118 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1119 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001120 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001121 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001122 return VectorList.Count == 1;
1123 }
1124
Jim Grosbach13af2222011-11-30 18:21:25 +00001125 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001126 if (!isSingleSpacedVectorAllLanes()) return false;
1127 return VectorList.Count == 2;
1128 }
1129
1130 bool isVecListTwoQAllLanes() const {
1131 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001132 return VectorList.Count == 2;
1133 }
1134
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001135 bool isSingleSpacedVectorIndexed() const {
1136 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1137 }
1138 bool isDoubleSpacedVectorIndexed() const {
1139 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1140 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001141 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001142 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001143 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1144 }
1145
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001146 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001147 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001148 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1149 }
1150
1151 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001152 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001153 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1154 }
1155
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001156 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001157 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001158 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1159 }
1160
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001161 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001162 if (!isSingleSpacedVectorIndexed()) return false;
1163 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1164 }
1165
1166 bool isVecListTwoQWordIndexed() const {
1167 if (!isDoubleSpacedVectorIndexed()) return false;
1168 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1169 }
1170
1171 bool isVecListTwoQHWordIndexed() const {
1172 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001173 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1174 }
1175
1176 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001177 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001178 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1179 }
1180
Jim Grosbach3a678af2012-01-23 21:53:26 +00001181 bool isVecListThreeDByteIndexed() const {
1182 if (!isSingleSpacedVectorIndexed()) return false;
1183 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1184 }
1185
1186 bool isVecListThreeDHWordIndexed() const {
1187 if (!isSingleSpacedVectorIndexed()) return false;
1188 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1189 }
1190
1191 bool isVecListThreeQWordIndexed() const {
1192 if (!isDoubleSpacedVectorIndexed()) return false;
1193 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1194 }
1195
1196 bool isVecListThreeQHWordIndexed() const {
1197 if (!isDoubleSpacedVectorIndexed()) return false;
1198 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1199 }
1200
1201 bool isVecListThreeDWordIndexed() const {
1202 if (!isSingleSpacedVectorIndexed()) return false;
1203 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1204 }
1205
Jim Grosbache983a132012-01-24 18:37:25 +00001206 bool isVecListFourDByteIndexed() const {
1207 if (!isSingleSpacedVectorIndexed()) return false;
1208 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1209 }
1210
1211 bool isVecListFourDHWordIndexed() const {
1212 if (!isSingleSpacedVectorIndexed()) return false;
1213 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1214 }
1215
1216 bool isVecListFourQWordIndexed() const {
1217 if (!isDoubleSpacedVectorIndexed()) return false;
1218 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1219 }
1220
1221 bool isVecListFourQHWordIndexed() const {
1222 if (!isDoubleSpacedVectorIndexed()) return false;
1223 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1224 }
1225
1226 bool isVecListFourDWordIndexed() const {
1227 if (!isSingleSpacedVectorIndexed()) return false;
1228 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1229 }
1230
Jim Grosbach460a9052011-10-07 23:56:00 +00001231 bool isVectorIndex8() const {
1232 if (Kind != k_VectorIndex) return false;
1233 return VectorIndex.Val < 8;
1234 }
1235 bool isVectorIndex16() const {
1236 if (Kind != k_VectorIndex) return false;
1237 return VectorIndex.Val < 4;
1238 }
1239 bool isVectorIndex32() const {
1240 if (Kind != k_VectorIndex) return false;
1241 return VectorIndex.Val < 2;
1242 }
1243
Jim Grosbach0e387b22011-10-17 22:26:03 +00001244 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001245 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1247 // Must be a constant.
1248 if (!CE) return false;
1249 int64_t Value = CE->getValue();
1250 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1251 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001252 return Value >= 0 && Value < 256;
1253 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001254
Jim Grosbachea461102011-10-17 23:09:09 +00001255 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001256 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001257 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1258 // Must be a constant.
1259 if (!CE) return false;
1260 int64_t Value = CE->getValue();
1261 // i16 value in the range [0,255] or [0x0100, 0xff00]
1262 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1263 }
1264
Jim Grosbach6248a542011-10-18 00:22:00 +00001265 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001266 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001267 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1268 // Must be a constant.
1269 if (!CE) return false;
1270 int64_t Value = CE->getValue();
1271 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1272 return (Value >= 0 && Value < 256) ||
1273 (Value >= 0x0100 && Value <= 0xff00) ||
1274 (Value >= 0x010000 && Value <= 0xff0000) ||
1275 (Value >= 0x01000000 && Value <= 0xff000000);
1276 }
1277
1278 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001279 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001280 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1281 // Must be a constant.
1282 if (!CE) return false;
1283 int64_t Value = CE->getValue();
1284 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1285 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1286 return (Value >= 0 && Value < 256) ||
1287 (Value >= 0x0100 && Value <= 0xff00) ||
1288 (Value >= 0x010000 && Value <= 0xff0000) ||
1289 (Value >= 0x01000000 && Value <= 0xff000000) ||
1290 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1291 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1292 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001293 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001294 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001295 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1296 // Must be a constant.
1297 if (!CE) return false;
1298 int64_t Value = ~CE->getValue();
1299 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1300 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1301 return (Value >= 0 && Value < 256) ||
1302 (Value >= 0x0100 && Value <= 0xff00) ||
1303 (Value >= 0x010000 && Value <= 0xff0000) ||
1304 (Value >= 0x01000000 && Value <= 0xff000000) ||
1305 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1306 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1307 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001308
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001309 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001310 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001311 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1312 // Must be a constant.
1313 if (!CE) return false;
1314 uint64_t Value = CE->getValue();
1315 // i64 value with each byte being either 0 or 0xff.
1316 for (unsigned i = 0; i < 8; ++i)
1317 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1318 return true;
1319 }
1320
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001321 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001322 // Add as immediates when possible. Null MCExpr = 0.
1323 if (Expr == 0)
1324 Inst.addOperand(MCOperand::CreateImm(0));
1325 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001326 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1327 else
1328 Inst.addOperand(MCOperand::CreateExpr(Expr));
1329 }
1330
Daniel Dunbar8462b302010-08-11 06:36:53 +00001331 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001332 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001333 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001334 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1335 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001336 }
1337
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001338 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1341 }
1342
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001343 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
1345 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1346 }
1347
1348 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1351 }
1352
Jim Grosbach89df9962011-08-26 21:43:41 +00001353 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1354 assert(N == 1 && "Invalid number of operands!");
1355 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1356 }
1357
1358 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
1360 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1361 }
1362
Jim Grosbachd67641b2010-12-06 18:21:12 +00001363 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 Inst.addOperand(MCOperand::CreateReg(getReg()));
1366 }
1367
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001368 void addRegOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 Inst.addOperand(MCOperand::CreateReg(getReg()));
1371 }
1372
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001373 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001374 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001375 assert(isRegShiftedReg() &&
1376 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001377 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1378 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001379 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001380 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001381 }
1382
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001383 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001384 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001385 assert(isRegShiftedImm() &&
1386 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001387 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001388 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001389 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001390 }
1391
Jim Grosbach580f4a92011-07-25 22:20:28 +00001392 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001393 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001394 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1395 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001396 }
1397
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001398 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001399 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001400 const SmallVectorImpl<unsigned> &RegList = getRegList();
1401 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001402 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1403 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001404 }
1405
Bill Wendling0f630752010-11-17 04:32:08 +00001406 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1407 addRegListOperands(Inst, N);
1408 }
1409
1410 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1411 addRegListOperands(Inst, N);
1412 }
1413
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001414 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1417 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1418 }
1419
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001420 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1421 assert(N == 1 && "Invalid number of operands!");
1422 // Munge the lsb/width into a bitfield mask.
1423 unsigned lsb = Bitfield.LSB;
1424 unsigned width = Bitfield.Width;
1425 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1426 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1427 (32 - (lsb + width)));
1428 Inst.addOperand(MCOperand::CreateImm(Mask));
1429 }
1430
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001431 void addImmOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
1433 addExpr(Inst, getImm());
1434 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001435
Jim Grosbach4050bc42011-12-22 22:19:05 +00001436 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1439 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1440 }
1441
1442 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1443 assert(N == 1 && "Invalid number of operands!");
1444 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1445 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1446 }
1447
Jim Grosbach9d390362011-10-03 23:38:36 +00001448 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1449 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001450 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1451 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1452 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001453 }
1454
Jim Grosbacha77295d2011-09-08 22:07:06 +00001455 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
1457 // FIXME: We really want to scale the value here, but the LDRD/STRD
1458 // instruction don't encode operands that way yet.
1459 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1460 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1461 }
1462
Jim Grosbach72f39f82011-08-24 21:22:15 +00001463 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 1 && "Invalid number of operands!");
1465 // The immediate is scaled by four in the encoding and is stored
1466 // in the MCInst as such. Lop off the low two bits here.
1467 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1468 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1469 }
1470
1471 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473 // The immediate is scaled by four in the encoding and is stored
1474 // in the MCInst as such. Lop off the low two bits here.
1475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1476 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1477 }
1478
Jim Grosbachf4943352011-07-25 23:09:14 +00001479 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 // The constant encodes as the immediate-1, and we store in the instruction
1482 // the bits as encoded, so subtract off one here.
1483 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1484 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1485 }
1486
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001487 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 // The constant encodes as the immediate-1, and we store in the instruction
1490 // the bits as encoded, so subtract off one here.
1491 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1492 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1493 }
1494
Jim Grosbach70939ee2011-08-17 21:51:27 +00001495 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 // The constant encodes as the immediate, except for 32, which encodes as
1498 // zero.
1499 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1500 unsigned Imm = CE->getValue();
1501 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1502 }
1503
Jim Grosbachf6c05252011-07-21 17:23:04 +00001504 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1507 // the instruction as well.
1508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1509 int Val = CE->getValue();
1510 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1511 }
1512
Jim Grosbach89a63372011-10-28 22:36:30 +00001513 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 1 && "Invalid number of operands!");
1515 // The operand is actually a t2_so_imm, but we have its bitwise
1516 // negation in the assembly source, so twiddle it here.
1517 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1518 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1519 }
1520
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001521 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1522 assert(N == 1 && "Invalid number of operands!");
1523 // The operand is actually a t2_so_imm, but we have its
1524 // negation in the assembly source, so twiddle it here.
1525 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1526 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1527 }
1528
Jim Grosbache70ec842011-10-28 22:50:54 +00001529 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1530 assert(N == 1 && "Invalid number of operands!");
1531 // The operand is actually a so_imm, but we have its bitwise
1532 // negation in the assembly source, so twiddle it here.
1533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1534 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1535 }
1536
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001537 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 // The operand is actually a so_imm, but we have its
1540 // negation in the assembly source, so twiddle it here.
1541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1542 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1543 }
1544
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001545 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1548 }
1549
Jim Grosbach7ce05792011-08-03 23:50:40 +00001550 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001552 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001553 }
1554
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001555 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 int32_t Imm = Memory.OffsetImm->getValue();
1558 // FIXME: Handle #-0
1559 if (Imm == INT32_MIN) Imm = 0;
1560 Inst.addOperand(MCOperand::CreateImm(Imm));
1561 }
1562
Jim Grosbach57dcb852011-10-11 17:29:55 +00001563 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1564 assert(N == 2 && "Invalid number of operands!");
1565 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1566 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1567 }
1568
Jim Grosbach7ce05792011-08-03 23:50:40 +00001569 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1570 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001571 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1572 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001573 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1574 // Special case for #-0
1575 if (Val == INT32_MIN) Val = 0;
1576 if (Val < 0) Val = -Val;
1577 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1578 } else {
1579 // For register offset, we encode the shift type and negation flag
1580 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001581 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1582 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001583 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001584 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1585 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001586 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001587 }
1588
Jim Grosbach039c2e12011-08-04 23:01:30 +00001589 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 2 && "Invalid number of operands!");
1591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1592 assert(CE && "non-constant AM2OffsetImm operand!");
1593 int32_t Val = CE->getValue();
1594 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1595 // Special case for #-0
1596 if (Val == INT32_MIN) Val = 0;
1597 if (Val < 0) Val = -Val;
1598 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1599 Inst.addOperand(MCOperand::CreateReg(0));
1600 Inst.addOperand(MCOperand::CreateImm(Val));
1601 }
1602
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001603 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1604 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001605 // If we have an immediate that's not a constant, treat it as a label
1606 // reference needing a fixup. If it is a constant, it's something else
1607 // and we reject it.
1608 if (isImm()) {
1609 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1610 Inst.addOperand(MCOperand::CreateReg(0));
1611 Inst.addOperand(MCOperand::CreateImm(0));
1612 return;
1613 }
1614
Jim Grosbache53c87b2011-10-11 15:59:20 +00001615 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1616 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001617 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1618 // Special case for #-0
1619 if (Val == INT32_MIN) Val = 0;
1620 if (Val < 0) Val = -Val;
1621 Val = ARM_AM::getAM3Opc(AddSub, Val);
1622 } else {
1623 // For register offset, we encode the shift type and negation flag
1624 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001625 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001626 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001627 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1628 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001629 Inst.addOperand(MCOperand::CreateImm(Val));
1630 }
1631
1632 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1633 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001634 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001635 int32_t Val =
1636 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1637 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1638 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001639 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001640 }
1641
1642 // Constant offset.
1643 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1644 int32_t Val = CE->getValue();
1645 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1646 // Special case for #-0
1647 if (Val == INT32_MIN) Val = 0;
1648 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001649 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001650 Inst.addOperand(MCOperand::CreateReg(0));
1651 Inst.addOperand(MCOperand::CreateImm(Val));
1652 }
1653
Jim Grosbach7ce05792011-08-03 23:50:40 +00001654 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1655 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001656 // If we have an immediate that's not a constant, treat it as a label
1657 // reference needing a fixup. If it is a constant, it's something else
1658 // and we reject it.
1659 if (isImm()) {
1660 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1661 Inst.addOperand(MCOperand::CreateImm(0));
1662 return;
1663 }
1664
Jim Grosbach7ce05792011-08-03 23:50:40 +00001665 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001666 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001667 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1668 // Special case for #-0
1669 if (Val == INT32_MIN) Val = 0;
1670 if (Val < 0) Val = -Val;
1671 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001672 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001673 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001674 }
1675
Jim Grosbacha77295d2011-09-08 22:07:06 +00001676 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1677 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001678 // If we have an immediate that's not a constant, treat it as a label
1679 // reference needing a fixup. If it is a constant, it's something else
1680 // and we reject it.
1681 if (isImm()) {
1682 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1683 Inst.addOperand(MCOperand::CreateImm(0));
1684 return;
1685 }
1686
Jim Grosbache53c87b2011-10-11 15:59:20 +00001687 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1688 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001689 Inst.addOperand(MCOperand::CreateImm(Val));
1690 }
1691
Jim Grosbachb6aed502011-09-09 18:37:27 +00001692 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 2 && "Invalid number of operands!");
1694 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001695 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1696 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001697 Inst.addOperand(MCOperand::CreateImm(Val));
1698 }
1699
Jim Grosbach7ce05792011-08-03 23:50:40 +00001700 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1701 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001702 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1703 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001704 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001705 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001706
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001707 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1708 addMemImm8OffsetOperands(Inst, N);
1709 }
1710
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001711 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001712 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001713 }
1714
1715 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 2 && "Invalid number of operands!");
1717 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001718 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001719 addExpr(Inst, getImm());
1720 Inst.addOperand(MCOperand::CreateImm(0));
1721 return;
1722 }
1723
1724 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001725 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1726 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001727 Inst.addOperand(MCOperand::CreateImm(Val));
1728 }
1729
Jim Grosbach7ce05792011-08-03 23:50:40 +00001730 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1731 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001732 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001733 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001734 addExpr(Inst, getImm());
1735 Inst.addOperand(MCOperand::CreateImm(0));
1736 return;
1737 }
1738
1739 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001740 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1741 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001742 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001743 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001744
Jim Grosbach7f739be2011-09-19 22:21:13 +00001745 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1746 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001747 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1748 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001749 }
1750
1751 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1752 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001753 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1754 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001755 }
1756
Jim Grosbach7ce05792011-08-03 23:50:40 +00001757 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1758 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001759 unsigned Val =
1760 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1761 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001762 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1763 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001764 Inst.addOperand(MCOperand::CreateImm(Val));
1765 }
1766
Jim Grosbachab899c12011-09-07 23:10:15 +00001767 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1768 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001769 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1770 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1771 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001772 }
1773
Jim Grosbach7ce05792011-08-03 23:50:40 +00001774 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1775 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001776 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1777 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001778 }
1779
Jim Grosbach60f91a32011-08-19 17:55:24 +00001780 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1781 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001782 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1783 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001784 Inst.addOperand(MCOperand::CreateImm(Val));
1785 }
1786
Jim Grosbach38466302011-08-19 18:55:51 +00001787 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1788 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001789 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1790 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001791 Inst.addOperand(MCOperand::CreateImm(Val));
1792 }
1793
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001794 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1795 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001796 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1797 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001798 Inst.addOperand(MCOperand::CreateImm(Val));
1799 }
1800
Jim Grosbachecd85892011-08-19 18:13:48 +00001801 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1802 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001803 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1804 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001805 Inst.addOperand(MCOperand::CreateImm(Val));
1806 }
1807
Jim Grosbach7ce05792011-08-03 23:50:40 +00001808 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1809 assert(N == 1 && "Invalid number of operands!");
1810 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1811 assert(CE && "non-constant post-idx-imm8 operand!");
1812 int Imm = CE->getValue();
1813 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001814 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001815 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1816 Inst.addOperand(MCOperand::CreateImm(Imm));
1817 }
1818
Jim Grosbach2bd01182011-10-11 21:55:36 +00001819 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1820 assert(N == 1 && "Invalid number of operands!");
1821 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1822 assert(CE && "non-constant post-idx-imm8s4 operand!");
1823 int Imm = CE->getValue();
1824 bool isAdd = Imm >= 0;
1825 if (Imm == INT32_MIN) Imm = 0;
1826 // Immediate is scaled by 4.
1827 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1828 Inst.addOperand(MCOperand::CreateImm(Imm));
1829 }
1830
Jim Grosbach7ce05792011-08-03 23:50:40 +00001831 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1832 assert(N == 2 && "Invalid number of operands!");
1833 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001834 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1835 }
1836
1837 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1838 assert(N == 2 && "Invalid number of operands!");
1839 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1840 // The sign, shift type, and shift amount are encoded in a single operand
1841 // using the AM2 encoding helpers.
1842 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1843 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1844 PostIdxReg.ShiftTy);
1845 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001846 }
1847
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001848 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1849 assert(N == 1 && "Invalid number of operands!");
1850 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1851 }
1852
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001853 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1854 assert(N == 1 && "Invalid number of operands!");
1855 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1856 }
1857
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001858 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001859 assert(N == 1 && "Invalid number of operands!");
1860 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1861 }
1862
Jim Grosbach7636bf62011-12-02 00:35:16 +00001863 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1864 assert(N == 2 && "Invalid number of operands!");
1865 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1866 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1867 }
1868
Jim Grosbach460a9052011-10-07 23:56:00 +00001869 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1870 assert(N == 1 && "Invalid number of operands!");
1871 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1872 }
1873
1874 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1875 assert(N == 1 && "Invalid number of operands!");
1876 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1877 }
1878
1879 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1880 assert(N == 1 && "Invalid number of operands!");
1881 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1882 }
1883
Jim Grosbach0e387b22011-10-17 22:26:03 +00001884 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1885 assert(N == 1 && "Invalid number of operands!");
1886 // The immediate encodes the type of constant as well as the value.
1887 // Mask in that this is an i8 splat.
1888 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1889 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1890 }
1891
Jim Grosbachea461102011-10-17 23:09:09 +00001892 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1893 assert(N == 1 && "Invalid number of operands!");
1894 // The immediate encodes the type of constant as well as the value.
1895 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1896 unsigned Value = CE->getValue();
1897 if (Value >= 256)
1898 Value = (Value >> 8) | 0xa00;
1899 else
1900 Value |= 0x800;
1901 Inst.addOperand(MCOperand::CreateImm(Value));
1902 }
1903
Jim Grosbach6248a542011-10-18 00:22:00 +00001904 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1905 assert(N == 1 && "Invalid number of operands!");
1906 // The immediate encodes the type of constant as well as the value.
1907 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1908 unsigned Value = CE->getValue();
1909 if (Value >= 256 && Value <= 0xff00)
1910 Value = (Value >> 8) | 0x200;
1911 else if (Value > 0xffff && Value <= 0xff0000)
1912 Value = (Value >> 16) | 0x400;
1913 else if (Value > 0xffffff)
1914 Value = (Value >> 24) | 0x600;
1915 Inst.addOperand(MCOperand::CreateImm(Value));
1916 }
1917
1918 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1919 assert(N == 1 && "Invalid number of operands!");
1920 // The immediate encodes the type of constant as well as the value.
1921 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1922 unsigned Value = CE->getValue();
1923 if (Value >= 256 && Value <= 0xffff)
1924 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1925 else if (Value > 0xffff && Value <= 0xffffff)
1926 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1927 else if (Value > 0xffffff)
1928 Value = (Value >> 24) | 0x600;
1929 Inst.addOperand(MCOperand::CreateImm(Value));
1930 }
1931
Jim Grosbach9b087852011-12-19 23:51:07 +00001932 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1933 assert(N == 1 && "Invalid number of operands!");
1934 // The immediate encodes the type of constant as well as the value.
1935 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1936 unsigned Value = ~CE->getValue();
1937 if (Value >= 256 && Value <= 0xffff)
1938 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1939 else if (Value > 0xffff && Value <= 0xffffff)
1940 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1941 else if (Value > 0xffffff)
1942 Value = (Value >> 24) | 0x600;
1943 Inst.addOperand(MCOperand::CreateImm(Value));
1944 }
1945
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001946 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1947 assert(N == 1 && "Invalid number of operands!");
1948 // The immediate encodes the type of constant as well as the value.
1949 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1950 uint64_t Value = CE->getValue();
1951 unsigned Imm = 0;
1952 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1953 Imm |= (Value & 1) << i;
1954 }
1955 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1956 }
1957
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001958 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001959
Jim Grosbach89df9962011-08-26 21:43:41 +00001960 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001961 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001962 Op->ITMask.Mask = Mask;
1963 Op->StartLoc = S;
1964 Op->EndLoc = S;
1965 return Op;
1966 }
1967
Chris Lattner3a697562010-10-28 17:20:03 +00001968 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001970 Op->CC.Val = CC;
1971 Op->StartLoc = S;
1972 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001973 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001974 }
1975
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001976 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001977 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001978 Op->Cop.Val = CopVal;
1979 Op->StartLoc = S;
1980 Op->EndLoc = S;
1981 return Op;
1982 }
1983
1984 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001986 Op->Cop.Val = CopVal;
1987 Op->StartLoc = S;
1988 Op->EndLoc = S;
1989 return Op;
1990 }
1991
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001992 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1993 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1994 Op->Cop.Val = Val;
1995 Op->StartLoc = S;
1996 Op->EndLoc = E;
1997 return Op;
1998 }
1999
Jim Grosbachd67641b2010-12-06 18:21:12 +00002000 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002001 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002002 Op->Reg.RegNum = RegNum;
2003 Op->StartLoc = S;
2004 Op->EndLoc = S;
2005 return Op;
2006 }
2007
Chris Lattner3a697562010-10-28 17:20:03 +00002008 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002009 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002010 Op->Tok.Data = Str.data();
2011 Op->Tok.Length = Str.size();
2012 Op->StartLoc = S;
2013 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002014 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002015 }
2016
Bill Wendling50d0f582010-11-18 23:43:05 +00002017 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002018 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002019 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002020 Op->StartLoc = S;
2021 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002022 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002023 }
2024
Jim Grosbache8606dc2011-07-13 17:50:29 +00002025 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2026 unsigned SrcReg,
2027 unsigned ShiftReg,
2028 unsigned ShiftImm,
2029 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002030 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002031 Op->RegShiftedReg.ShiftTy = ShTy;
2032 Op->RegShiftedReg.SrcReg = SrcReg;
2033 Op->RegShiftedReg.ShiftReg = ShiftReg;
2034 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002035 Op->StartLoc = S;
2036 Op->EndLoc = E;
2037 return Op;
2038 }
2039
Owen Anderson92a20222011-07-21 18:54:16 +00002040 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2041 unsigned SrcReg,
2042 unsigned ShiftImm,
2043 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002044 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002045 Op->RegShiftedImm.ShiftTy = ShTy;
2046 Op->RegShiftedImm.SrcReg = SrcReg;
2047 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002048 Op->StartLoc = S;
2049 Op->EndLoc = E;
2050 return Op;
2051 }
2052
Jim Grosbach580f4a92011-07-25 22:20:28 +00002053 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002054 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002055 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002056 Op->ShifterImm.isASR = isASR;
2057 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002058 Op->StartLoc = S;
2059 Op->EndLoc = E;
2060 return Op;
2061 }
2062
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002063 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002064 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002065 Op->RotImm.Imm = Imm;
2066 Op->StartLoc = S;
2067 Op->EndLoc = E;
2068 return Op;
2069 }
2070
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002071 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2072 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002073 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002074 Op->Bitfield.LSB = LSB;
2075 Op->Bitfield.Width = Width;
2076 Op->StartLoc = S;
2077 Op->EndLoc = E;
2078 return Op;
2079 }
2080
Bill Wendling7729e062010-11-09 22:44:22 +00002081 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002082 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002083 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002084 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002085
Jim Grosbachd300b942011-09-13 22:56:44 +00002086 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002087 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002088 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002089 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002090 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002091
2092 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002093 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002094 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002095 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002096 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002097 Op->StartLoc = StartLoc;
2098 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002099 return Op;
2100 }
2101
Jim Grosbach862019c2011-10-18 23:02:30 +00002102 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002103 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002104 ARMOperand *Op = new ARMOperand(k_VectorList);
2105 Op->VectorList.RegNum = RegNum;
2106 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002107 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002108 Op->StartLoc = S;
2109 Op->EndLoc = E;
2110 return Op;
2111 }
2112
Jim Grosbach98b05a52011-11-30 01:09:44 +00002113 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002114 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002115 SMLoc S, SMLoc E) {
2116 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2117 Op->VectorList.RegNum = RegNum;
2118 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002119 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002120 Op->StartLoc = S;
2121 Op->EndLoc = E;
2122 return Op;
2123 }
2124
Jim Grosbach7636bf62011-12-02 00:35:16 +00002125 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002126 unsigned Index,
2127 bool isDoubleSpaced,
2128 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002129 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2130 Op->VectorList.RegNum = RegNum;
2131 Op->VectorList.Count = Count;
2132 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002133 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002134 Op->StartLoc = S;
2135 Op->EndLoc = E;
2136 return Op;
2137 }
2138
Jim Grosbach460a9052011-10-07 23:56:00 +00002139 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2140 MCContext &Ctx) {
2141 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2142 Op->VectorIndex.Val = Idx;
2143 Op->StartLoc = S;
2144 Op->EndLoc = E;
2145 return Op;
2146 }
2147
Chris Lattner3a697562010-10-28 17:20:03 +00002148 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002149 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002150 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002151 Op->StartLoc = S;
2152 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002153 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002154 }
2155
Jim Grosbach7ce05792011-08-03 23:50:40 +00002156 static ARMOperand *CreateMem(unsigned BaseRegNum,
2157 const MCConstantExpr *OffsetImm,
2158 unsigned OffsetRegNum,
2159 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002160 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002161 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002162 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002163 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002164 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002165 Op->Memory.BaseRegNum = BaseRegNum;
2166 Op->Memory.OffsetImm = OffsetImm;
2167 Op->Memory.OffsetRegNum = OffsetRegNum;
2168 Op->Memory.ShiftType = ShiftType;
2169 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002170 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002171 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002172 Op->StartLoc = S;
2173 Op->EndLoc = E;
2174 return Op;
2175 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002176
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002177 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2178 ARM_AM::ShiftOpc ShiftTy,
2179 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002180 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002181 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002182 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002183 Op->PostIdxReg.isAdd = isAdd;
2184 Op->PostIdxReg.ShiftTy = ShiftTy;
2185 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002186 Op->StartLoc = S;
2187 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002188 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002189 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002190
2191 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002192 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002193 Op->MBOpt.Val = Opt;
2194 Op->StartLoc = S;
2195 Op->EndLoc = S;
2196 return Op;
2197 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002198
2199 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002200 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002201 Op->IFlags.Val = IFlags;
2202 Op->StartLoc = S;
2203 Op->EndLoc = S;
2204 return Op;
2205 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002206
2207 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002208 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002209 Op->MMask.Val = MMask;
2210 Op->StartLoc = S;
2211 Op->EndLoc = S;
2212 return Op;
2213 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002214};
2215
2216} // end anonymous namespace.
2217
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002218void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002219 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002220 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002221 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002222 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002223 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002224 OS << "<ccout " << getReg() << ">";
2225 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002226 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002227 static const char *MaskStr[] = {
2228 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2229 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2230 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002231 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2232 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2233 break;
2234 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002235 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002236 OS << "<coprocessor number: " << getCoproc() << ">";
2237 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002238 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002239 OS << "<coprocessor register: " << getCoproc() << ">";
2240 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002241 case k_CoprocOption:
2242 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2243 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002244 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002245 OS << "<mask: " << getMSRMask() << ">";
2246 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002247 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002248 getImm()->print(OS);
2249 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002250 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002251 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2252 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002253 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002254 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002255 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002256 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002257 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002258 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002259 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2260 << PostIdxReg.RegNum;
2261 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2262 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2263 << PostIdxReg.ShiftImm;
2264 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002265 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002266 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002267 OS << "<ARM_PROC::";
2268 unsigned IFlags = getProcIFlags();
2269 for (int i=2; i >= 0; --i)
2270 if (IFlags & (1 << i))
2271 OS << ARM_PROC::IFlagsToString(1 << i);
2272 OS << ">";
2273 break;
2274 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002275 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002276 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002277 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002278 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002279 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2280 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002281 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002282 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002283 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002284 << RegShiftedReg.SrcReg << " "
2285 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2286 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002287 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002288 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002289 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002290 << RegShiftedImm.SrcReg << " "
2291 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2292 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002293 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002294 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002295 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2296 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002297 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002298 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2299 << ", width: " << Bitfield.Width << ">";
2300 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002301 case k_RegisterList:
2302 case k_DPRRegisterList:
2303 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002304 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002305
Bill Wendling5fa22a12010-11-09 23:28:44 +00002306 const SmallVectorImpl<unsigned> &RegList = getRegList();
2307 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002308 I = RegList.begin(), E = RegList.end(); I != E; ) {
2309 OS << *I;
2310 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002311 }
2312
2313 OS << ">";
2314 break;
2315 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002316 case k_VectorList:
2317 OS << "<vector_list " << VectorList.Count << " * "
2318 << VectorList.RegNum << ">";
2319 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002320 case k_VectorListAllLanes:
2321 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2322 << VectorList.RegNum << ">";
2323 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002324 case k_VectorListIndexed:
2325 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2326 << VectorList.Count << " * " << VectorList.RegNum << ">";
2327 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002328 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002329 OS << "'" << getToken() << "'";
2330 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002331 case k_VectorIndex:
2332 OS << "<vectorindex " << getVectorIndex() << ">";
2333 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002334 }
2335}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002336
2337/// @name Auto-generated Match Functions
2338/// {
2339
2340static unsigned MatchRegisterName(StringRef Name);
2341
2342/// }
2343
Bob Wilson69df7232011-02-03 21:46:10 +00002344bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2345 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002346 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002347 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002348 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002349
2350 return (RegNo == (unsigned)-1);
2351}
2352
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002353/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002354/// and if it is a register name the token is eaten and the register number is
2355/// returned. Otherwise return -1.
2356///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002357int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002358 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002359 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002360
Benjamin Kramer59085362011-11-06 20:37:06 +00002361 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002362 unsigned RegNum = MatchRegisterName(lowerCase);
2363 if (!RegNum) {
2364 RegNum = StringSwitch<unsigned>(lowerCase)
2365 .Case("r13", ARM::SP)
2366 .Case("r14", ARM::LR)
2367 .Case("r15", ARM::PC)
2368 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002369 // Additional register name aliases for 'gas' compatibility.
2370 .Case("a1", ARM::R0)
2371 .Case("a2", ARM::R1)
2372 .Case("a3", ARM::R2)
2373 .Case("a4", ARM::R3)
2374 .Case("v1", ARM::R4)
2375 .Case("v2", ARM::R5)
2376 .Case("v3", ARM::R6)
2377 .Case("v4", ARM::R7)
2378 .Case("v5", ARM::R8)
2379 .Case("v6", ARM::R9)
2380 .Case("v7", ARM::R10)
2381 .Case("v8", ARM::R11)
2382 .Case("sb", ARM::R9)
2383 .Case("sl", ARM::R10)
2384 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002385 .Default(0);
2386 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002387 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002388 // Check for aliases registered via .req. Canonicalize to lower case.
2389 // That's more consistent since register names are case insensitive, and
2390 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2391 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002392 // If no match, return failure.
2393 if (Entry == RegisterReqs.end())
2394 return -1;
2395 Parser.Lex(); // Eat identifier token.
2396 return Entry->getValue();
2397 }
Bob Wilson69df7232011-02-03 21:46:10 +00002398
Chris Lattnere5658fa2010-10-30 04:09:10 +00002399 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002400
Chris Lattnere5658fa2010-10-30 04:09:10 +00002401 return RegNum;
2402}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002403
Jim Grosbach19906722011-07-13 18:49:30 +00002404// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2405// If a recoverable error occurs, return 1. If an irrecoverable error
2406// occurs, return -1. An irrecoverable error is one where tokens have been
2407// consumed in the process of trying to parse the shifter (i.e., when it is
2408// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002409int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002410 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2411 SMLoc S = Parser.getTok().getLoc();
2412 const AsmToken &Tok = Parser.getTok();
2413 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2414
Benjamin Kramer59085362011-11-06 20:37:06 +00002415 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002416 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002417 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002418 .Case("lsl", ARM_AM::lsl)
2419 .Case("lsr", ARM_AM::lsr)
2420 .Case("asr", ARM_AM::asr)
2421 .Case("ror", ARM_AM::ror)
2422 .Case("rrx", ARM_AM::rrx)
2423 .Default(ARM_AM::no_shift);
2424
2425 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002426 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002427
Jim Grosbache8606dc2011-07-13 17:50:29 +00002428 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002429
Jim Grosbache8606dc2011-07-13 17:50:29 +00002430 // The source register for the shift has already been added to the
2431 // operand list, so we need to pop it off and combine it into the shifted
2432 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002433 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002434 if (!PrevOp->isReg())
2435 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2436 int SrcReg = PrevOp->getReg();
2437 int64_t Imm = 0;
2438 int ShiftReg = 0;
2439 if (ShiftTy == ARM_AM::rrx) {
2440 // RRX Doesn't have an explicit shift amount. The encoder expects
2441 // the shift register to be the same as the source register. Seems odd,
2442 // but OK.
2443 ShiftReg = SrcReg;
2444 } else {
2445 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002446 if (Parser.getTok().is(AsmToken::Hash) ||
2447 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002448 Parser.Lex(); // Eat hash.
2449 SMLoc ImmLoc = Parser.getTok().getLoc();
2450 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002451 if (getParser().ParseExpression(ShiftExpr)) {
2452 Error(ImmLoc, "invalid immediate shift value");
2453 return -1;
2454 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002455 // The expression must be evaluatable as an immediate.
2456 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002457 if (!CE) {
2458 Error(ImmLoc, "invalid immediate shift value");
2459 return -1;
2460 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002461 // Range check the immediate.
2462 // lsl, ror: 0 <= imm <= 31
2463 // lsr, asr: 0 <= imm <= 32
2464 Imm = CE->getValue();
2465 if (Imm < 0 ||
2466 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2467 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002468 Error(ImmLoc, "immediate shift value out of range");
2469 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002470 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002471 // shift by zero is a nop. Always send it through as lsl.
2472 // ('as' compatibility)
2473 if (Imm == 0)
2474 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002475 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002476 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002477 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002478 if (ShiftReg == -1) {
2479 Error (L, "expected immediate or register in shift operand");
2480 return -1;
2481 }
2482 } else {
2483 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002484 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002485 return -1;
2486 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002487 }
2488
Owen Anderson92a20222011-07-21 18:54:16 +00002489 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2490 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002491 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002492 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002493 else
2494 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2495 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002496
Jim Grosbach19906722011-07-13 18:49:30 +00002497 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002498}
2499
2500
Bill Wendling50d0f582010-11-18 23:43:05 +00002501/// Try to parse a register name. The token must be an Identifier when called.
2502/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2503/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002504///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002505/// TODO this is likely to change to allow different register types and or to
2506/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002507bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002508tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002509 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002510 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002511 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002512 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002513
Bill Wendling50d0f582010-11-18 23:43:05 +00002514 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002515
Chris Lattnere5658fa2010-10-30 04:09:10 +00002516 const AsmToken &ExclaimTok = Parser.getTok();
2517 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002518 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2519 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002520 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002521 return false;
2522 }
2523
2524 // Also check for an index operand. This is only legal for vector registers,
2525 // but that'll get caught OK in operand matching, so we don't need to
2526 // explicitly filter everything else out here.
2527 if (Parser.getTok().is(AsmToken::LBrac)) {
2528 SMLoc SIdx = Parser.getTok().getLoc();
2529 Parser.Lex(); // Eat left bracket token.
2530
2531 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002532 if (getParser().ParseExpression(ImmVal))
2533 return MatchOperand_ParseFail;
2534 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2535 if (!MCE) {
2536 TokError("immediate value expected for vector index");
2537 return MatchOperand_ParseFail;
2538 }
2539
2540 SMLoc E = Parser.getTok().getLoc();
2541 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2542 Error(E, "']' expected");
2543 return MatchOperand_ParseFail;
2544 }
2545
2546 Parser.Lex(); // Eat right bracket token.
2547
2548 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2549 SIdx, E,
2550 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002551 }
2552
Bill Wendling50d0f582010-11-18 23:43:05 +00002553 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002554}
2555
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002556/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2557/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2558/// "c5", ...
2559static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002560 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2561 // but efficient.
2562 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002563 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002564 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002565 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002566 return -1;
2567 switch (Name[1]) {
2568 default: return -1;
2569 case '0': return 0;
2570 case '1': return 1;
2571 case '2': return 2;
2572 case '3': return 3;
2573 case '4': return 4;
2574 case '5': return 5;
2575 case '6': return 6;
2576 case '7': return 7;
2577 case '8': return 8;
2578 case '9': return 9;
2579 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002580 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002581 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002582 return -1;
2583 switch (Name[2]) {
2584 default: return -1;
2585 case '0': return 10;
2586 case '1': return 11;
2587 case '2': return 12;
2588 case '3': return 13;
2589 case '4': return 14;
2590 case '5': return 15;
2591 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002592 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002593}
2594
Jim Grosbach89df9962011-08-26 21:43:41 +00002595/// parseITCondCode - Try to parse a condition code for an IT instruction.
2596ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2597parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2598 SMLoc S = Parser.getTok().getLoc();
2599 const AsmToken &Tok = Parser.getTok();
2600 if (!Tok.is(AsmToken::Identifier))
2601 return MatchOperand_NoMatch;
2602 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2603 .Case("eq", ARMCC::EQ)
2604 .Case("ne", ARMCC::NE)
2605 .Case("hs", ARMCC::HS)
2606 .Case("cs", ARMCC::HS)
2607 .Case("lo", ARMCC::LO)
2608 .Case("cc", ARMCC::LO)
2609 .Case("mi", ARMCC::MI)
2610 .Case("pl", ARMCC::PL)
2611 .Case("vs", ARMCC::VS)
2612 .Case("vc", ARMCC::VC)
2613 .Case("hi", ARMCC::HI)
2614 .Case("ls", ARMCC::LS)
2615 .Case("ge", ARMCC::GE)
2616 .Case("lt", ARMCC::LT)
2617 .Case("gt", ARMCC::GT)
2618 .Case("le", ARMCC::LE)
2619 .Case("al", ARMCC::AL)
2620 .Default(~0U);
2621 if (CC == ~0U)
2622 return MatchOperand_NoMatch;
2623 Parser.Lex(); // Eat the token.
2624
2625 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2626
2627 return MatchOperand_Success;
2628}
2629
Jim Grosbach43904292011-07-25 20:14:50 +00002630/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002631/// token must be an Identifier when called, and if it is a coprocessor
2632/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002633ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002634parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002635 SMLoc S = Parser.getTok().getLoc();
2636 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002637 if (Tok.isNot(AsmToken::Identifier))
2638 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002639
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002640 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002641 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002642 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002643
2644 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002645 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002646 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002647}
2648
Jim Grosbach43904292011-07-25 20:14:50 +00002649/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002650/// token must be an Identifier when called, and if it is a coprocessor
2651/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002652ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002653parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002654 SMLoc S = Parser.getTok().getLoc();
2655 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002656 if (Tok.isNot(AsmToken::Identifier))
2657 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002658
2659 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2660 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002661 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002662
2663 Parser.Lex(); // Eat identifier token.
2664 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002665 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002666}
2667
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002668/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2669/// coproc_option : '{' imm0_255 '}'
2670ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2671parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2672 SMLoc S = Parser.getTok().getLoc();
2673
2674 // If this isn't a '{', this isn't a coprocessor immediate operand.
2675 if (Parser.getTok().isNot(AsmToken::LCurly))
2676 return MatchOperand_NoMatch;
2677 Parser.Lex(); // Eat the '{'
2678
2679 const MCExpr *Expr;
2680 SMLoc Loc = Parser.getTok().getLoc();
2681 if (getParser().ParseExpression(Expr)) {
2682 Error(Loc, "illegal expression");
2683 return MatchOperand_ParseFail;
2684 }
2685 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2686 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2687 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2688 return MatchOperand_ParseFail;
2689 }
2690 int Val = CE->getValue();
2691
2692 // Check for and consume the closing '}'
2693 if (Parser.getTok().isNot(AsmToken::RCurly))
2694 return MatchOperand_ParseFail;
2695 SMLoc E = Parser.getTok().getLoc();
2696 Parser.Lex(); // Eat the '}'
2697
2698 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2699 return MatchOperand_Success;
2700}
2701
Jim Grosbachd0588e22011-09-14 18:08:35 +00002702// For register list parsing, we need to map from raw GPR register numbering
2703// to the enumeration values. The enumeration values aren't sorted by
2704// register number due to our using "sp", "lr" and "pc" as canonical names.
2705static unsigned getNextRegister(unsigned Reg) {
2706 // If this is a GPR, we need to do it manually, otherwise we can rely
2707 // on the sort ordering of the enumeration since the other reg-classes
2708 // are sane.
2709 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2710 return Reg + 1;
2711 switch(Reg) {
2712 default: assert(0 && "Invalid GPR number!");
2713 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2714 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2715 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2716 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2717 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2718 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2719 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2720 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2721 }
2722}
2723
Jim Grosbachce485e72011-11-11 21:27:40 +00002724// Return the low-subreg of a given Q register.
2725static unsigned getDRegFromQReg(unsigned QReg) {
2726 switch (QReg) {
2727 default: llvm_unreachable("expected a Q register!");
2728 case ARM::Q0: return ARM::D0;
2729 case ARM::Q1: return ARM::D2;
2730 case ARM::Q2: return ARM::D4;
2731 case ARM::Q3: return ARM::D6;
2732 case ARM::Q4: return ARM::D8;
2733 case ARM::Q5: return ARM::D10;
2734 case ARM::Q6: return ARM::D12;
2735 case ARM::Q7: return ARM::D14;
2736 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002737 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002738 case ARM::Q10: return ARM::D20;
2739 case ARM::Q11: return ARM::D22;
2740 case ARM::Q12: return ARM::D24;
2741 case ARM::Q13: return ARM::D26;
2742 case ARM::Q14: return ARM::D28;
2743 case ARM::Q15: return ARM::D30;
2744 }
2745}
2746
Jim Grosbachd0588e22011-09-14 18:08:35 +00002747/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002748bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002749parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002750 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002751 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002752 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002753 Parser.Lex(); // Eat '{' token.
2754 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002755
Jim Grosbachd0588e22011-09-14 18:08:35 +00002756 // Check the first register in the list to see what register class
2757 // this is a list of.
2758 int Reg = tryParseRegister();
2759 if (Reg == -1)
2760 return Error(RegLoc, "register expected");
2761
Jim Grosbachce485e72011-11-11 21:27:40 +00002762 // The reglist instructions have at most 16 registers, so reserve
2763 // space for that many.
2764 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2765
2766 // Allow Q regs and just interpret them as the two D sub-registers.
2767 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2768 Reg = getDRegFromQReg(Reg);
2769 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2770 ++Reg;
2771 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002772 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002773 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2774 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2775 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2776 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2777 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2778 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2779 else
2780 return Error(RegLoc, "invalid register in register list");
2781
Jim Grosbachce485e72011-11-11 21:27:40 +00002782 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002783 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002784
Jim Grosbachd0588e22011-09-14 18:08:35 +00002785 // This starts immediately after the first register token in the list,
2786 // so we can see either a comma or a minus (range separator) as a legal
2787 // next token.
2788 while (Parser.getTok().is(AsmToken::Comma) ||
2789 Parser.getTok().is(AsmToken::Minus)) {
2790 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002791 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002792 SMLoc EndLoc = Parser.getTok().getLoc();
2793 int EndReg = tryParseRegister();
2794 if (EndReg == -1)
2795 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002796 // Allow Q regs and just interpret them as the two D sub-registers.
2797 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2798 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002799 // If the register is the same as the start reg, there's nothing
2800 // more to do.
2801 if (Reg == EndReg)
2802 continue;
2803 // The register must be in the same register class as the first.
2804 if (!RC->contains(EndReg))
2805 return Error(EndLoc, "invalid register in register list");
2806 // Ranges must go from low to high.
2807 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2808 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002809
Jim Grosbachd0588e22011-09-14 18:08:35 +00002810 // Add all the registers in the range to the register list.
2811 while (Reg != EndReg) {
2812 Reg = getNextRegister(Reg);
2813 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2814 }
2815 continue;
2816 }
2817 Parser.Lex(); // Eat the comma.
2818 RegLoc = Parser.getTok().getLoc();
2819 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002820 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002821 Reg = tryParseRegister();
2822 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002823 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002824 // Allow Q regs and just interpret them as the two D sub-registers.
2825 bool isQReg = false;
2826 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2827 Reg = getDRegFromQReg(Reg);
2828 isQReg = true;
2829 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002830 // The register must be in the same register class as the first.
2831 if (!RC->contains(Reg))
2832 return Error(RegLoc, "invalid register in register list");
2833 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002834 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002835 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002836 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2837 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2838 ") in register list");
2839 continue;
2840 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002841 // VFP register lists must also be contiguous.
2842 // It's OK to use the enumeration values directly here rather, as the
2843 // VFP register classes have the enum sorted properly.
2844 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2845 Reg != OldReg + 1)
2846 return Error(RegLoc, "non-contiguous register range");
2847 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002848 if (isQReg)
2849 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002850 }
2851
Jim Grosbachd0588e22011-09-14 18:08:35 +00002852 SMLoc E = Parser.getTok().getLoc();
2853 if (Parser.getTok().isNot(AsmToken::RCurly))
2854 return Error(E, "'}' expected");
2855 Parser.Lex(); // Eat '}' token.
2856
Jim Grosbach27debd62011-12-13 21:48:29 +00002857 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002858 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002859
2860 // The ARM system instruction variants for LDM/STM have a '^' token here.
2861 if (Parser.getTok().is(AsmToken::Caret)) {
2862 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2863 Parser.Lex(); // Eat '^' token.
2864 }
2865
Bill Wendling50d0f582010-11-18 23:43:05 +00002866 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002867}
2868
Jim Grosbach98b05a52011-11-30 01:09:44 +00002869// Helper function to parse the lane index for vector lists.
2870ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002871parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2872 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002873 if (Parser.getTok().is(AsmToken::LBrac)) {
2874 Parser.Lex(); // Eat the '['.
2875 if (Parser.getTok().is(AsmToken::RBrac)) {
2876 // "Dn[]" is the 'all lanes' syntax.
2877 LaneKind = AllLanes;
2878 Parser.Lex(); // Eat the ']'.
2879 return MatchOperand_Success;
2880 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002881 const MCExpr *LaneIndex;
2882 SMLoc Loc = Parser.getTok().getLoc();
2883 if (getParser().ParseExpression(LaneIndex)) {
2884 Error(Loc, "illegal expression");
2885 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002886 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002887 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2888 if (!CE) {
2889 Error(Loc, "lane index must be empty or an integer");
2890 return MatchOperand_ParseFail;
2891 }
2892 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2893 Error(Parser.getTok().getLoc(), "']' expected");
2894 return MatchOperand_ParseFail;
2895 }
2896 Parser.Lex(); // Eat the ']'.
2897 int64_t Val = CE->getValue();
2898
2899 // FIXME: Make this range check context sensitive for .8, .16, .32.
2900 if (Val < 0 || Val > 7) {
2901 Error(Parser.getTok().getLoc(), "lane index out of range");
2902 return MatchOperand_ParseFail;
2903 }
2904 Index = Val;
2905 LaneKind = IndexedLane;
2906 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002907 }
2908 LaneKind = NoLanes;
2909 return MatchOperand_Success;
2910}
2911
Jim Grosbach862019c2011-10-18 23:02:30 +00002912// parse a vector register list
2913ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2914parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002915 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002916 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002917 SMLoc S = Parser.getTok().getLoc();
2918 // As an extension (to match gas), support a plain D register or Q register
2919 // (without encosing curly braces) as a single or double entry list,
2920 // respectively.
2921 if (Parser.getTok().is(AsmToken::Identifier)) {
2922 int Reg = tryParseRegister();
2923 if (Reg == -1)
2924 return MatchOperand_NoMatch;
2925 SMLoc E = Parser.getTok().getLoc();
2926 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002927 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002928 if (Res != MatchOperand_Success)
2929 return Res;
2930 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002931 case NoLanes:
2932 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002933 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002934 break;
2935 case AllLanes:
2936 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002937 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2938 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002939 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002940 case IndexedLane:
2941 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002942 LaneIndex,
2943 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002944 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002945 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002946 return MatchOperand_Success;
2947 }
2948 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2949 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002950 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002951 if (Res != MatchOperand_Success)
2952 return Res;
2953 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002954 case NoLanes:
2955 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002956 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002957 break;
2958 case AllLanes:
2959 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002960 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2961 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002962 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002963 case IndexedLane:
2964 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002965 LaneIndex,
2966 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002967 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002968 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002969 return MatchOperand_Success;
2970 }
2971 Error(S, "vector register expected");
2972 return MatchOperand_ParseFail;
2973 }
2974
2975 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002976 return MatchOperand_NoMatch;
2977
Jim Grosbach862019c2011-10-18 23:02:30 +00002978 Parser.Lex(); // Eat '{' token.
2979 SMLoc RegLoc = Parser.getTok().getLoc();
2980
2981 int Reg = tryParseRegister();
2982 if (Reg == -1) {
2983 Error(RegLoc, "register expected");
2984 return MatchOperand_ParseFail;
2985 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002986 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002987 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002988 unsigned FirstReg = Reg;
2989 // The list is of D registers, but we also allow Q regs and just interpret
2990 // them as the two D sub-registers.
2991 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2992 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002993 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2994 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002995 ++Reg;
2996 ++Count;
2997 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002998 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002999 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003000
Jim Grosbache43862b2011-11-15 23:19:15 +00003001 while (Parser.getTok().is(AsmToken::Comma) ||
3002 Parser.getTok().is(AsmToken::Minus)) {
3003 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003004 if (!Spacing)
3005 Spacing = 1; // Register range implies a single spaced list.
3006 else if (Spacing == 2) {
3007 Error(Parser.getTok().getLoc(),
3008 "sequential registers in double spaced list");
3009 return MatchOperand_ParseFail;
3010 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003011 Parser.Lex(); // Eat the minus.
3012 SMLoc EndLoc = Parser.getTok().getLoc();
3013 int EndReg = tryParseRegister();
3014 if (EndReg == -1) {
3015 Error(EndLoc, "register expected");
3016 return MatchOperand_ParseFail;
3017 }
3018 // Allow Q regs and just interpret them as the two D sub-registers.
3019 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3020 EndReg = getDRegFromQReg(EndReg) + 1;
3021 // If the register is the same as the start reg, there's nothing
3022 // more to do.
3023 if (Reg == EndReg)
3024 continue;
3025 // The register must be in the same register class as the first.
3026 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3027 Error(EndLoc, "invalid register in register list");
3028 return MatchOperand_ParseFail;
3029 }
3030 // Ranges must go from low to high.
3031 if (Reg > EndReg) {
3032 Error(EndLoc, "bad range in register list");
3033 return MatchOperand_ParseFail;
3034 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003035 // Parse the lane specifier if present.
3036 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003037 unsigned NextLaneIndex;
3038 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003039 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003040 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003041 Error(EndLoc, "mismatched lane index in register list");
3042 return MatchOperand_ParseFail;
3043 }
3044 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003045
3046 // Add all the registers in the range to the register list.
3047 Count += EndReg - Reg;
3048 Reg = EndReg;
3049 continue;
3050 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003051 Parser.Lex(); // Eat the comma.
3052 RegLoc = Parser.getTok().getLoc();
3053 int OldReg = Reg;
3054 Reg = tryParseRegister();
3055 if (Reg == -1) {
3056 Error(RegLoc, "register expected");
3057 return MatchOperand_ParseFail;
3058 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003059 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003060 // It's OK to use the enumeration values directly here rather, as the
3061 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003062 //
3063 // The list is of D registers, but we also allow Q regs and just interpret
3064 // them as the two D sub-registers.
3065 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003066 if (!Spacing)
3067 Spacing = 1; // Register range implies a single spaced list.
3068 else if (Spacing == 2) {
3069 Error(RegLoc,
3070 "invalid register in double-spaced list (must be 'D' register')");
3071 return MatchOperand_ParseFail;
3072 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003073 Reg = getDRegFromQReg(Reg);
3074 if (Reg != OldReg + 1) {
3075 Error(RegLoc, "non-contiguous register range");
3076 return MatchOperand_ParseFail;
3077 }
3078 ++Reg;
3079 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003080 // Parse the lane specifier if present.
3081 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003082 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003083 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003084 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003085 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003086 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003087 Error(EndLoc, "mismatched lane index in register list");
3088 return MatchOperand_ParseFail;
3089 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003090 continue;
3091 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003092 // Normal D register.
3093 // Figure out the register spacing (single or double) of the list if
3094 // we don't know it already.
3095 if (!Spacing)
3096 Spacing = 1 + (Reg == OldReg + 2);
3097
3098 // Just check that it's contiguous and keep going.
3099 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003100 Error(RegLoc, "non-contiguous register range");
3101 return MatchOperand_ParseFail;
3102 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003103 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003104 // Parse the lane specifier if present.
3105 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003106 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003107 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003108 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003109 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003110 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003111 Error(EndLoc, "mismatched lane index in register list");
3112 return MatchOperand_ParseFail;
3113 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003114 }
3115
3116 SMLoc E = Parser.getTok().getLoc();
3117 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3118 Error(E, "'}' expected");
3119 return MatchOperand_ParseFail;
3120 }
3121 Parser.Lex(); // Eat '}' token.
3122
Jim Grosbach98b05a52011-11-30 01:09:44 +00003123 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003124 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003125 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3126 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003127 break;
3128 case AllLanes:
3129 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003130 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003131 S, E));
3132 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003133 case IndexedLane:
3134 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003135 LaneIndex,
3136 (Spacing == 2),
3137 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003138 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003139 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003140 return MatchOperand_Success;
3141}
3142
Jim Grosbach43904292011-07-25 20:14:50 +00003143/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003144ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003145parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003146 SMLoc S = Parser.getTok().getLoc();
3147 const AsmToken &Tok = Parser.getTok();
3148 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3149 StringRef OptStr = Tok.getString();
3150
3151 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3152 .Case("sy", ARM_MB::SY)
3153 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003154 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003155 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003156 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003157 .Case("ishst", ARM_MB::ISHST)
3158 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003159 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003160 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003161 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003162 .Case("osh", ARM_MB::OSH)
3163 .Case("oshst", ARM_MB::OSHST)
3164 .Default(~0U);
3165
3166 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003167 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003168
3169 Parser.Lex(); // Eat identifier token.
3170 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003171 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003172}
3173
Jim Grosbach43904292011-07-25 20:14:50 +00003174/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003175ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003176parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003177 SMLoc S = Parser.getTok().getLoc();
3178 const AsmToken &Tok = Parser.getTok();
3179 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3180 StringRef IFlagsStr = Tok.getString();
3181
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003182 // An iflags string of "none" is interpreted to mean that none of the AIF
3183 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003184 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003185 if (IFlagsStr != "none") {
3186 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3187 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3188 .Case("a", ARM_PROC::A)
3189 .Case("i", ARM_PROC::I)
3190 .Case("f", ARM_PROC::F)
3191 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003192
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003193 // If some specific iflag is already set, it means that some letter is
3194 // present more than once, this is not acceptable.
3195 if (Flag == ~0U || (IFlags & Flag))
3196 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003197
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003198 IFlags |= Flag;
3199 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003200 }
3201
3202 Parser.Lex(); // Eat identifier token.
3203 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3204 return MatchOperand_Success;
3205}
3206
Jim Grosbach43904292011-07-25 20:14:50 +00003207/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003208ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003209parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003210 SMLoc S = Parser.getTok().getLoc();
3211 const AsmToken &Tok = Parser.getTok();
3212 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3213 StringRef Mask = Tok.getString();
3214
James Molloyacad68d2011-09-28 14:21:38 +00003215 if (isMClass()) {
3216 // See ARMv6-M 10.1.1
3217 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3218 .Case("apsr", 0)
3219 .Case("iapsr", 1)
3220 .Case("eapsr", 2)
3221 .Case("xpsr", 3)
3222 .Case("ipsr", 5)
3223 .Case("epsr", 6)
3224 .Case("iepsr", 7)
3225 .Case("msp", 8)
3226 .Case("psp", 9)
3227 .Case("primask", 16)
3228 .Case("basepri", 17)
3229 .Case("basepri_max", 18)
3230 .Case("faultmask", 19)
3231 .Case("control", 20)
3232 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003233
James Molloyacad68d2011-09-28 14:21:38 +00003234 if (FlagsVal == ~0U)
3235 return MatchOperand_NoMatch;
3236
3237 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3238 // basepri, basepri_max and faultmask only valid for V7m.
3239 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003240
James Molloyacad68d2011-09-28 14:21:38 +00003241 Parser.Lex(); // Eat identifier token.
3242 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3243 return MatchOperand_Success;
3244 }
3245
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003246 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3247 size_t Start = 0, Next = Mask.find('_');
3248 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003249 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003250 if (Next != StringRef::npos)
3251 Flags = Mask.slice(Next+1, Mask.size());
3252
3253 // FlagsVal contains the complete mask:
3254 // 3-0: Mask
3255 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3256 unsigned FlagsVal = 0;
3257
3258 if (SpecReg == "apsr") {
3259 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003260 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003261 .Case("g", 0x4) // same as CPSR_s
3262 .Case("nzcvqg", 0xc) // same as CPSR_fs
3263 .Default(~0U);
3264
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003265 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003266 if (!Flags.empty())
3267 return MatchOperand_NoMatch;
3268 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003269 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003270 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003271 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003272 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3273 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003274 for (int i = 0, e = Flags.size(); i != e; ++i) {
3275 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3276 .Case("c", 1)
3277 .Case("x", 2)
3278 .Case("s", 4)
3279 .Case("f", 8)
3280 .Default(~0U);
3281
3282 // If some specific flag is already set, it means that some letter is
3283 // present more than once, this is not acceptable.
3284 if (FlagsVal == ~0U || (FlagsVal & Flag))
3285 return MatchOperand_NoMatch;
3286 FlagsVal |= Flag;
3287 }
3288 } else // No match for special register.
3289 return MatchOperand_NoMatch;
3290
Owen Anderson7784f1d2011-10-21 18:43:28 +00003291 // Special register without flags is NOT equivalent to "fc" flags.
3292 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3293 // two lines would enable gas compatibility at the expense of breaking
3294 // round-tripping.
3295 //
3296 // if (!FlagsVal)
3297 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003298
3299 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3300 if (SpecReg == "spsr")
3301 FlagsVal |= 16;
3302
3303 Parser.Lex(); // Eat identifier token.
3304 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3305 return MatchOperand_Success;
3306}
3307
Jim Grosbachf6c05252011-07-21 17:23:04 +00003308ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3309parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3310 int Low, int High) {
3311 const AsmToken &Tok = Parser.getTok();
3312 if (Tok.isNot(AsmToken::Identifier)) {
3313 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3314 return MatchOperand_ParseFail;
3315 }
3316 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003317 std::string LowerOp = Op.lower();
3318 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003319 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3320 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3321 return MatchOperand_ParseFail;
3322 }
3323 Parser.Lex(); // Eat shift type token.
3324
3325 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003326 if (Parser.getTok().isNot(AsmToken::Hash) &&
3327 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003328 Error(Parser.getTok().getLoc(), "'#' expected");
3329 return MatchOperand_ParseFail;
3330 }
3331 Parser.Lex(); // Eat hash token.
3332
3333 const MCExpr *ShiftAmount;
3334 SMLoc Loc = Parser.getTok().getLoc();
3335 if (getParser().ParseExpression(ShiftAmount)) {
3336 Error(Loc, "illegal expression");
3337 return MatchOperand_ParseFail;
3338 }
3339 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3340 if (!CE) {
3341 Error(Loc, "constant expression expected");
3342 return MatchOperand_ParseFail;
3343 }
3344 int Val = CE->getValue();
3345 if (Val < Low || Val > High) {
3346 Error(Loc, "immediate value out of range");
3347 return MatchOperand_ParseFail;
3348 }
3349
3350 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3351
3352 return MatchOperand_Success;
3353}
3354
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003355ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3356parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3357 const AsmToken &Tok = Parser.getTok();
3358 SMLoc S = Tok.getLoc();
3359 if (Tok.isNot(AsmToken::Identifier)) {
3360 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3361 return MatchOperand_ParseFail;
3362 }
3363 int Val = StringSwitch<int>(Tok.getString())
3364 .Case("be", 1)
3365 .Case("le", 0)
3366 .Default(-1);
3367 Parser.Lex(); // Eat the token.
3368
3369 if (Val == -1) {
3370 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3371 return MatchOperand_ParseFail;
3372 }
3373 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3374 getContext()),
3375 S, Parser.getTok().getLoc()));
3376 return MatchOperand_Success;
3377}
3378
Jim Grosbach580f4a92011-07-25 22:20:28 +00003379/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3380/// instructions. Legal values are:
3381/// lsl #n 'n' in [0,31]
3382/// asr #n 'n' in [1,32]
3383/// n == 32 encoded as n == 0.
3384ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3385parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3386 const AsmToken &Tok = Parser.getTok();
3387 SMLoc S = Tok.getLoc();
3388 if (Tok.isNot(AsmToken::Identifier)) {
3389 Error(S, "shift operator 'asr' or 'lsl' expected");
3390 return MatchOperand_ParseFail;
3391 }
3392 StringRef ShiftName = Tok.getString();
3393 bool isASR;
3394 if (ShiftName == "lsl" || ShiftName == "LSL")
3395 isASR = false;
3396 else if (ShiftName == "asr" || ShiftName == "ASR")
3397 isASR = true;
3398 else {
3399 Error(S, "shift operator 'asr' or 'lsl' expected");
3400 return MatchOperand_ParseFail;
3401 }
3402 Parser.Lex(); // Eat the operator.
3403
3404 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003405 if (Parser.getTok().isNot(AsmToken::Hash) &&
3406 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003407 Error(Parser.getTok().getLoc(), "'#' expected");
3408 return MatchOperand_ParseFail;
3409 }
3410 Parser.Lex(); // Eat hash token.
3411
3412 const MCExpr *ShiftAmount;
3413 SMLoc E = Parser.getTok().getLoc();
3414 if (getParser().ParseExpression(ShiftAmount)) {
3415 Error(E, "malformed shift expression");
3416 return MatchOperand_ParseFail;
3417 }
3418 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3419 if (!CE) {
3420 Error(E, "shift amount must be an immediate");
3421 return MatchOperand_ParseFail;
3422 }
3423
3424 int64_t Val = CE->getValue();
3425 if (isASR) {
3426 // Shift amount must be in [1,32]
3427 if (Val < 1 || Val > 32) {
3428 Error(E, "'asr' shift amount must be in range [1,32]");
3429 return MatchOperand_ParseFail;
3430 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003431 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3432 if (isThumb() && Val == 32) {
3433 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3434 return MatchOperand_ParseFail;
3435 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003436 if (Val == 32) Val = 0;
3437 } else {
3438 // Shift amount must be in [1,32]
3439 if (Val < 0 || Val > 31) {
3440 Error(E, "'lsr' shift amount must be in range [0,31]");
3441 return MatchOperand_ParseFail;
3442 }
3443 }
3444
3445 E = Parser.getTok().getLoc();
3446 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3447
3448 return MatchOperand_Success;
3449}
3450
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003451/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3452/// of instructions. Legal values are:
3453/// ror #n 'n' in {0, 8, 16, 24}
3454ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3455parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3456 const AsmToken &Tok = Parser.getTok();
3457 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003458 if (Tok.isNot(AsmToken::Identifier))
3459 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003460 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003461 if (ShiftName != "ror" && ShiftName != "ROR")
3462 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003463 Parser.Lex(); // Eat the operator.
3464
3465 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003466 if (Parser.getTok().isNot(AsmToken::Hash) &&
3467 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003468 Error(Parser.getTok().getLoc(), "'#' expected");
3469 return MatchOperand_ParseFail;
3470 }
3471 Parser.Lex(); // Eat hash token.
3472
3473 const MCExpr *ShiftAmount;
3474 SMLoc E = Parser.getTok().getLoc();
3475 if (getParser().ParseExpression(ShiftAmount)) {
3476 Error(E, "malformed rotate expression");
3477 return MatchOperand_ParseFail;
3478 }
3479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3480 if (!CE) {
3481 Error(E, "rotate amount must be an immediate");
3482 return MatchOperand_ParseFail;
3483 }
3484
3485 int64_t Val = CE->getValue();
3486 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3487 // normally, zero is represented in asm by omitting the rotate operand
3488 // entirely.
3489 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3490 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3491 return MatchOperand_ParseFail;
3492 }
3493
3494 E = Parser.getTok().getLoc();
3495 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3496
3497 return MatchOperand_Success;
3498}
3499
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003500ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3501parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3502 SMLoc S = Parser.getTok().getLoc();
3503 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003504 if (Parser.getTok().isNot(AsmToken::Hash) &&
3505 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003506 Error(Parser.getTok().getLoc(), "'#' expected");
3507 return MatchOperand_ParseFail;
3508 }
3509 Parser.Lex(); // Eat hash token.
3510
3511 const MCExpr *LSBExpr;
3512 SMLoc E = Parser.getTok().getLoc();
3513 if (getParser().ParseExpression(LSBExpr)) {
3514 Error(E, "malformed immediate expression");
3515 return MatchOperand_ParseFail;
3516 }
3517 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3518 if (!CE) {
3519 Error(E, "'lsb' operand must be an immediate");
3520 return MatchOperand_ParseFail;
3521 }
3522
3523 int64_t LSB = CE->getValue();
3524 // The LSB must be in the range [0,31]
3525 if (LSB < 0 || LSB > 31) {
3526 Error(E, "'lsb' operand must be in the range [0,31]");
3527 return MatchOperand_ParseFail;
3528 }
3529 E = Parser.getTok().getLoc();
3530
3531 // Expect another immediate operand.
3532 if (Parser.getTok().isNot(AsmToken::Comma)) {
3533 Error(Parser.getTok().getLoc(), "too few operands");
3534 return MatchOperand_ParseFail;
3535 }
3536 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003537 if (Parser.getTok().isNot(AsmToken::Hash) &&
3538 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003539 Error(Parser.getTok().getLoc(), "'#' expected");
3540 return MatchOperand_ParseFail;
3541 }
3542 Parser.Lex(); // Eat hash token.
3543
3544 const MCExpr *WidthExpr;
3545 if (getParser().ParseExpression(WidthExpr)) {
3546 Error(E, "malformed immediate expression");
3547 return MatchOperand_ParseFail;
3548 }
3549 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3550 if (!CE) {
3551 Error(E, "'width' operand must be an immediate");
3552 return MatchOperand_ParseFail;
3553 }
3554
3555 int64_t Width = CE->getValue();
3556 // The LSB must be in the range [1,32-lsb]
3557 if (Width < 1 || Width > 32 - LSB) {
3558 Error(E, "'width' operand must be in the range [1,32-lsb]");
3559 return MatchOperand_ParseFail;
3560 }
3561 E = Parser.getTok().getLoc();
3562
3563 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3564
3565 return MatchOperand_Success;
3566}
3567
Jim Grosbach7ce05792011-08-03 23:50:40 +00003568ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3569parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3570 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003571 // postidx_reg := '+' register {, shift}
3572 // | '-' register {, shift}
3573 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003574
3575 // This method must return MatchOperand_NoMatch without consuming any tokens
3576 // in the case where there is no match, as other alternatives take other
3577 // parse methods.
3578 AsmToken Tok = Parser.getTok();
3579 SMLoc S = Tok.getLoc();
3580 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003581 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003582 int Reg = -1;
3583 if (Tok.is(AsmToken::Plus)) {
3584 Parser.Lex(); // Eat the '+' token.
3585 haveEaten = true;
3586 } else if (Tok.is(AsmToken::Minus)) {
3587 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003588 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003589 haveEaten = true;
3590 }
3591 if (Parser.getTok().is(AsmToken::Identifier))
3592 Reg = tryParseRegister();
3593 if (Reg == -1) {
3594 if (!haveEaten)
3595 return MatchOperand_NoMatch;
3596 Error(Parser.getTok().getLoc(), "register expected");
3597 return MatchOperand_ParseFail;
3598 }
3599 SMLoc E = Parser.getTok().getLoc();
3600
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003601 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3602 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003603 if (Parser.getTok().is(AsmToken::Comma)) {
3604 Parser.Lex(); // Eat the ','.
3605 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3606 return MatchOperand_ParseFail;
3607 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003608
3609 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3610 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003611
3612 return MatchOperand_Success;
3613}
3614
Jim Grosbach251bf252011-08-10 21:56:18 +00003615ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3616parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3617 // Check for a post-index addressing register operand. Specifically:
3618 // am3offset := '+' register
3619 // | '-' register
3620 // | register
3621 // | # imm
3622 // | # + imm
3623 // | # - imm
3624
3625 // This method must return MatchOperand_NoMatch without consuming any tokens
3626 // in the case where there is no match, as other alternatives take other
3627 // parse methods.
3628 AsmToken Tok = Parser.getTok();
3629 SMLoc S = Tok.getLoc();
3630
3631 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003632 if (Parser.getTok().is(AsmToken::Hash) ||
3633 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003634 Parser.Lex(); // Eat the '#'.
3635 // Explicitly look for a '-', as we need to encode negative zero
3636 // differently.
3637 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3638 const MCExpr *Offset;
3639 if (getParser().ParseExpression(Offset))
3640 return MatchOperand_ParseFail;
3641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3642 if (!CE) {
3643 Error(S, "constant expression expected");
3644 return MatchOperand_ParseFail;
3645 }
3646 SMLoc E = Tok.getLoc();
3647 // Negative zero is encoded as the flag value INT32_MIN.
3648 int32_t Val = CE->getValue();
3649 if (isNegative && Val == 0)
3650 Val = INT32_MIN;
3651
3652 Operands.push_back(
3653 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3654
3655 return MatchOperand_Success;
3656 }
3657
3658
3659 bool haveEaten = false;
3660 bool isAdd = true;
3661 int Reg = -1;
3662 if (Tok.is(AsmToken::Plus)) {
3663 Parser.Lex(); // Eat the '+' token.
3664 haveEaten = true;
3665 } else if (Tok.is(AsmToken::Minus)) {
3666 Parser.Lex(); // Eat the '-' token.
3667 isAdd = false;
3668 haveEaten = true;
3669 }
3670 if (Parser.getTok().is(AsmToken::Identifier))
3671 Reg = tryParseRegister();
3672 if (Reg == -1) {
3673 if (!haveEaten)
3674 return MatchOperand_NoMatch;
3675 Error(Parser.getTok().getLoc(), "register expected");
3676 return MatchOperand_ParseFail;
3677 }
3678 SMLoc E = Parser.getTok().getLoc();
3679
3680 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3681 0, S, E));
3682
3683 return MatchOperand_Success;
3684}
3685
Jim Grosbacha77295d2011-09-08 22:07:06 +00003686/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3687/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3688/// when they refer multiple MIOperands inside a single one.
3689bool ARMAsmParser::
3690cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3691 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3692 // Rt, Rt2
3693 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3694 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3695 // Create a writeback register dummy placeholder.
3696 Inst.addOperand(MCOperand::CreateReg(0));
3697 // addr
3698 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3699 // pred
3700 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3701 return true;
3702}
3703
3704/// cvtT2StrdPre - Convert parsed operands to MCInst.
3705/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3706/// when they refer multiple MIOperands inside a single one.
3707bool ARMAsmParser::
3708cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3709 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3710 // Create a writeback register dummy placeholder.
3711 Inst.addOperand(MCOperand::CreateReg(0));
3712 // Rt, Rt2
3713 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3714 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3715 // addr
3716 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3717 // pred
3718 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3719 return true;
3720}
3721
Jim Grosbacheeec0252011-09-08 00:39:19 +00003722/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3723/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3724/// when they refer multiple MIOperands inside a single one.
3725bool ARMAsmParser::
3726cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3727 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3728 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3729
3730 // Create a writeback register dummy placeholder.
3731 Inst.addOperand(MCOperand::CreateImm(0));
3732
3733 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3734 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3735 return true;
3736}
3737
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003738/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3739/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3740/// when they refer multiple MIOperands inside a single one.
3741bool ARMAsmParser::
3742cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3743 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3744 // Create a writeback register dummy placeholder.
3745 Inst.addOperand(MCOperand::CreateImm(0));
3746 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3747 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3748 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3749 return true;
3750}
3751
Jim Grosbach1355cf12011-07-26 17:10:22 +00003752/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003753/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3754/// when they refer multiple MIOperands inside a single one.
3755bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003756cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003757 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3758 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3759
3760 // Create a writeback register dummy placeholder.
3761 Inst.addOperand(MCOperand::CreateImm(0));
3762
Jim Grosbach7ce05792011-08-03 23:50:40 +00003763 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003764 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3765 return true;
3766}
3767
Owen Anderson9ab0f252011-08-26 20:43:14 +00003768/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3769/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3770/// when they refer multiple MIOperands inside a single one.
3771bool ARMAsmParser::
3772cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3773 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3774 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3775
3776 // Create a writeback register dummy placeholder.
3777 Inst.addOperand(MCOperand::CreateImm(0));
3778
3779 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3780 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3781 return true;
3782}
3783
3784
Jim Grosbach548340c2011-08-11 19:22:40 +00003785/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3786/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3787/// when they refer multiple MIOperands inside a single one.
3788bool ARMAsmParser::
3789cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3790 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3791 // Create a writeback register dummy placeholder.
3792 Inst.addOperand(MCOperand::CreateImm(0));
3793 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3794 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3795 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3796 return true;
3797}
3798
Jim Grosbach1355cf12011-07-26 17:10:22 +00003799/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003800/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3801/// when they refer multiple MIOperands inside a single one.
3802bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003803cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003804 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3805 // Create a writeback register dummy placeholder.
3806 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003807 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3808 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3809 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003810 return true;
3811}
3812
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003813/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3814/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3815/// when they refer multiple MIOperands inside a single one.
3816bool ARMAsmParser::
3817cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3818 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3819 // Create a writeback register dummy placeholder.
3820 Inst.addOperand(MCOperand::CreateImm(0));
3821 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3822 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3823 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3824 return true;
3825}
3826
Jim Grosbach7ce05792011-08-03 23:50:40 +00003827/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3828/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3829/// when they refer multiple MIOperands inside a single one.
3830bool ARMAsmParser::
3831cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3832 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3833 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003834 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003835 // Create a writeback register dummy placeholder.
3836 Inst.addOperand(MCOperand::CreateImm(0));
3837 // addr
3838 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3839 // offset
3840 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3841 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003842 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3843 return true;
3844}
3845
Jim Grosbach7ce05792011-08-03 23:50:40 +00003846/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003847/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3848/// when they refer multiple MIOperands inside a single one.
3849bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003850cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3851 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3852 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003853 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003854 // Create a writeback register dummy placeholder.
3855 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003856 // addr
3857 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3858 // offset
3859 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3860 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003861 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3862 return true;
3863}
3864
Jim Grosbach7ce05792011-08-03 23:50:40 +00003865/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003866/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3867/// when they refer multiple MIOperands inside a single one.
3868bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003869cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3870 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003871 // Create a writeback register dummy placeholder.
3872 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003873 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003874 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003875 // addr
3876 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3877 // offset
3878 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3879 // pred
3880 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3881 return true;
3882}
3883
3884/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3885/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3886/// when they refer multiple MIOperands inside a single one.
3887bool ARMAsmParser::
3888cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3889 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3890 // Create a writeback register dummy placeholder.
3891 Inst.addOperand(MCOperand::CreateImm(0));
3892 // Rt
3893 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3894 // addr
3895 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3896 // offset
3897 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3898 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003899 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3900 return true;
3901}
3902
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003903/// cvtLdrdPre - Convert parsed operands to MCInst.
3904/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3905/// when they refer multiple MIOperands inside a single one.
3906bool ARMAsmParser::
3907cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3908 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3909 // Rt, Rt2
3910 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3911 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3912 // Create a writeback register dummy placeholder.
3913 Inst.addOperand(MCOperand::CreateImm(0));
3914 // addr
3915 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3916 // pred
3917 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3918 return true;
3919}
3920
Jim Grosbach14605d12011-08-11 20:28:23 +00003921/// cvtStrdPre - Convert parsed operands to MCInst.
3922/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3923/// when they refer multiple MIOperands inside a single one.
3924bool ARMAsmParser::
3925cvtStrdPre(MCInst &Inst, unsigned Opcode,
3926 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3927 // Create a writeback register dummy placeholder.
3928 Inst.addOperand(MCOperand::CreateImm(0));
3929 // Rt, Rt2
3930 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3931 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3932 // addr
3933 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3934 // pred
3935 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3936 return true;
3937}
3938
Jim Grosbach623a4542011-08-10 22:42:16 +00003939/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3940/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3941/// when they refer multiple MIOperands inside a single one.
3942bool ARMAsmParser::
3943cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3944 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3945 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3946 // Create a writeback register dummy placeholder.
3947 Inst.addOperand(MCOperand::CreateImm(0));
3948 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3949 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3950 return true;
3951}
3952
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003953/// cvtThumbMultiple- Convert parsed operands to MCInst.
3954/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3955/// when they refer multiple MIOperands inside a single one.
3956bool ARMAsmParser::
3957cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3958 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3959 // The second source operand must be the same register as the destination
3960 // operand.
3961 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003962 (((ARMOperand*)Operands[3])->getReg() !=
3963 ((ARMOperand*)Operands[5])->getReg()) &&
3964 (((ARMOperand*)Operands[3])->getReg() !=
3965 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003966 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003967 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003968 return false;
3969 }
3970 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3971 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003972 // If we have a three-operand form, make sure to set Rn to be the operand
3973 // that isn't the same as Rd.
3974 unsigned RegOp = 4;
3975 if (Operands.size() == 6 &&
3976 ((ARMOperand*)Operands[4])->getReg() ==
3977 ((ARMOperand*)Operands[3])->getReg())
3978 RegOp = 5;
3979 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3980 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003981 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3982
3983 return true;
3984}
Jim Grosbach623a4542011-08-10 22:42:16 +00003985
Jim Grosbach12431322011-10-24 22:16:58 +00003986bool ARMAsmParser::
3987cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3988 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3989 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003990 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003991 // Create a writeback register dummy placeholder.
3992 Inst.addOperand(MCOperand::CreateImm(0));
3993 // Vn
3994 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3995 // pred
3996 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3997 return true;
3998}
3999
4000bool ARMAsmParser::
4001cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4002 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4003 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004004 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004005 // Create a writeback register dummy placeholder.
4006 Inst.addOperand(MCOperand::CreateImm(0));
4007 // Vn
4008 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4009 // Vm
4010 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4011 // pred
4012 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4013 return true;
4014}
4015
Jim Grosbach4334e032011-10-31 21:50:31 +00004016bool ARMAsmParser::
4017cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4018 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4019 // Create a writeback register dummy placeholder.
4020 Inst.addOperand(MCOperand::CreateImm(0));
4021 // Vn
4022 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4023 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004024 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004025 // pred
4026 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4027 return true;
4028}
4029
4030bool ARMAsmParser::
4031cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4032 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4033 // Create a writeback register dummy placeholder.
4034 Inst.addOperand(MCOperand::CreateImm(0));
4035 // Vn
4036 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4037 // Vm
4038 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4039 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004040 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004041 // pred
4042 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4043 return true;
4044}
4045
Bill Wendlinge7176102010-11-06 22:36:58 +00004046/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004047/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004048bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004049parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004050 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004051 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004052 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004053 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004054 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004055
Sean Callanan18b83232010-01-19 21:44:56 +00004056 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004057 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004058 if (BaseRegNum == -1)
4059 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004060
Daniel Dunbar05710932011-01-18 05:34:17 +00004061 // The next token must either be a comma or a closing bracket.
4062 const AsmToken &Tok = Parser.getTok();
4063 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004064 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004065
Jim Grosbach7ce05792011-08-03 23:50:40 +00004066 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004067 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004068 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004069
Jim Grosbach7ce05792011-08-03 23:50:40 +00004070 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004071 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004072
Jim Grosbachfb12f352011-09-19 18:42:21 +00004073 // If there's a pre-indexing writeback marker, '!', just add it as a token
4074 // operand. It's rather odd, but syntactically valid.
4075 if (Parser.getTok().is(AsmToken::Exclaim)) {
4076 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4077 Parser.Lex(); // Eat the '!'.
4078 }
4079
Jim Grosbach7ce05792011-08-03 23:50:40 +00004080 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004081 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004082
Jim Grosbach7ce05792011-08-03 23:50:40 +00004083 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4084 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004085
Jim Grosbach57dcb852011-10-11 17:29:55 +00004086 // If we have a ':', it's an alignment specifier.
4087 if (Parser.getTok().is(AsmToken::Colon)) {
4088 Parser.Lex(); // Eat the ':'.
4089 E = Parser.getTok().getLoc();
4090
4091 const MCExpr *Expr;
4092 if (getParser().ParseExpression(Expr))
4093 return true;
4094
4095 // The expression has to be a constant. Memory references with relocations
4096 // don't come through here, as they use the <label> forms of the relevant
4097 // instructions.
4098 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4099 if (!CE)
4100 return Error (E, "constant expression expected");
4101
4102 unsigned Align = 0;
4103 switch (CE->getValue()) {
4104 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004105 return Error(E,
4106 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4107 case 16: Align = 2; break;
4108 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004109 case 64: Align = 8; break;
4110 case 128: Align = 16; break;
4111 case 256: Align = 32; break;
4112 }
4113
4114 // Now we should have the closing ']'
4115 E = Parser.getTok().getLoc();
4116 if (Parser.getTok().isNot(AsmToken::RBrac))
4117 return Error(E, "']' expected");
4118 Parser.Lex(); // Eat right bracket token.
4119
4120 // Don't worry about range checking the value here. That's handled by
4121 // the is*() predicates.
4122 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4123 ARM_AM::no_shift, 0, Align,
4124 false, S, E));
4125
4126 // If there's a pre-indexing writeback marker, '!', just add it as a token
4127 // operand.
4128 if (Parser.getTok().is(AsmToken::Exclaim)) {
4129 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4130 Parser.Lex(); // Eat the '!'.
4131 }
4132
4133 return false;
4134 }
4135
4136 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004137 // offset. Be friendly and also accept a plain integer (without a leading
4138 // hash) for gas compatibility.
4139 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004140 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004141 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004142 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004143 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004144 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004145
Owen Anderson0da10cf2011-08-29 19:36:44 +00004146 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004147 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004148 if (getParser().ParseExpression(Offset))
4149 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004150
4151 // The expression has to be a constant. Memory references with relocations
4152 // don't come through here, as they use the <label> forms of the relevant
4153 // instructions.
4154 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4155 if (!CE)
4156 return Error (E, "constant expression expected");
4157
Owen Anderson0da10cf2011-08-29 19:36:44 +00004158 // If the constant was #-0, represent it as INT32_MIN.
4159 int32_t Val = CE->getValue();
4160 if (isNegative && Val == 0)
4161 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4162
Jim Grosbach7ce05792011-08-03 23:50:40 +00004163 // Now we should have the closing ']'
4164 E = Parser.getTok().getLoc();
4165 if (Parser.getTok().isNot(AsmToken::RBrac))
4166 return Error(E, "']' expected");
4167 Parser.Lex(); // Eat right bracket token.
4168
4169 // Don't worry about range checking the value here. That's handled by
4170 // the is*() predicates.
4171 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004172 ARM_AM::no_shift, 0, 0,
4173 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004174
4175 // If there's a pre-indexing writeback marker, '!', just add it as a token
4176 // operand.
4177 if (Parser.getTok().is(AsmToken::Exclaim)) {
4178 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4179 Parser.Lex(); // Eat the '!'.
4180 }
4181
4182 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004183 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004184
4185 // The register offset is optionally preceded by a '+' or '-'
4186 bool isNegative = false;
4187 if (Parser.getTok().is(AsmToken::Minus)) {
4188 isNegative = true;
4189 Parser.Lex(); // Eat the '-'.
4190 } else if (Parser.getTok().is(AsmToken::Plus)) {
4191 // Nothing to do.
4192 Parser.Lex(); // Eat the '+'.
4193 }
4194
4195 E = Parser.getTok().getLoc();
4196 int OffsetRegNum = tryParseRegister();
4197 if (OffsetRegNum == -1)
4198 return Error(E, "register expected");
4199
4200 // If there's a shift operator, handle it.
4201 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004202 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004203 if (Parser.getTok().is(AsmToken::Comma)) {
4204 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004205 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004206 return true;
4207 }
4208
4209 // Now we should have the closing ']'
4210 E = Parser.getTok().getLoc();
4211 if (Parser.getTok().isNot(AsmToken::RBrac))
4212 return Error(E, "']' expected");
4213 Parser.Lex(); // Eat right bracket token.
4214
4215 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004216 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004217 S, E));
4218
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004219 // If there's a pre-indexing writeback marker, '!', just add it as a token
4220 // operand.
4221 if (Parser.getTok().is(AsmToken::Exclaim)) {
4222 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4223 Parser.Lex(); // Eat the '!'.
4224 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004225
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004226 return false;
4227}
4228
Jim Grosbach7ce05792011-08-03 23:50:40 +00004229/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004230/// ( lsl | lsr | asr | ror ) , # shift_amount
4231/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004232/// return true if it parses a shift otherwise it returns false.
4233bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4234 unsigned &Amount) {
4235 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004236 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004237 if (Tok.isNot(AsmToken::Identifier))
4238 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004239 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004240 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4241 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004242 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004243 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004244 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004245 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004246 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004247 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004248 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004249 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004250 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004251 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004252 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004253 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004254
Jim Grosbach7ce05792011-08-03 23:50:40 +00004255 // rrx stands alone.
4256 Amount = 0;
4257 if (St != ARM_AM::rrx) {
4258 Loc = Parser.getTok().getLoc();
4259 // A '#' and a shift amount.
4260 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004261 if (HashTok.isNot(AsmToken::Hash) &&
4262 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004263 return Error(HashTok.getLoc(), "'#' expected");
4264 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004265
Jim Grosbach7ce05792011-08-03 23:50:40 +00004266 const MCExpr *Expr;
4267 if (getParser().ParseExpression(Expr))
4268 return true;
4269 // Range check the immediate.
4270 // lsl, ror: 0 <= imm <= 31
4271 // lsr, asr: 0 <= imm <= 32
4272 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4273 if (!CE)
4274 return Error(Loc, "shift amount must be an immediate");
4275 int64_t Imm = CE->getValue();
4276 if (Imm < 0 ||
4277 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4278 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4279 return Error(Loc, "immediate shift value out of range");
4280 Amount = Imm;
4281 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004282
4283 return false;
4284}
4285
Jim Grosbach9d390362011-10-03 23:38:36 +00004286/// parseFPImm - A floating point immediate expression operand.
4287ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4288parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004289 // Anything that can accept a floating point constant as an operand
4290 // needs to go through here, as the regular ParseExpression is
4291 // integer only.
4292 //
4293 // This routine still creates a generic Immediate operand, containing
4294 // a bitcast of the 64-bit floating point value. The various operands
4295 // that accept floats can check whether the value is valid for them
4296 // via the standard is*() predicates.
4297
Jim Grosbach9d390362011-10-03 23:38:36 +00004298 SMLoc S = Parser.getTok().getLoc();
4299
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004300 if (Parser.getTok().isNot(AsmToken::Hash) &&
4301 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004302 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004303
4304 // Disambiguate the VMOV forms that can accept an FP immediate.
4305 // vmov.f32 <sreg>, #imm
4306 // vmov.f64 <dreg>, #imm
4307 // vmov.f32 <dreg>, #imm @ vector f32x2
4308 // vmov.f32 <qreg>, #imm @ vector f32x4
4309 //
4310 // There are also the NEON VMOV instructions which expect an
4311 // integer constant. Make sure we don't try to parse an FPImm
4312 // for these:
4313 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4314 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4315 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4316 TyOp->getToken() != ".f64"))
4317 return MatchOperand_NoMatch;
4318
Jim Grosbach9d390362011-10-03 23:38:36 +00004319 Parser.Lex(); // Eat the '#'.
4320
4321 // Handle negation, as that still comes through as a separate token.
4322 bool isNegative = false;
4323 if (Parser.getTok().is(AsmToken::Minus)) {
4324 isNegative = true;
4325 Parser.Lex();
4326 }
4327 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004328 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004329 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004330 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004331 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4332 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004333 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004334 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004335 Operands.push_back(ARMOperand::CreateImm(
4336 MCConstantExpr::Create(IntVal, getContext()),
4337 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004338 return MatchOperand_Success;
4339 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004340 // Also handle plain integers. Instructions which allow floating point
4341 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004342 if (Tok.is(AsmToken::Integer)) {
4343 int64_t Val = Tok.getIntVal();
4344 Parser.Lex(); // Eat the token.
4345 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004346 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004347 return MatchOperand_ParseFail;
4348 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004349 double RealVal = ARM_AM::getFPImmFloat(Val);
4350 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4351 Operands.push_back(ARMOperand::CreateImm(
4352 MCConstantExpr::Create(Val, getContext()), S,
4353 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004354 return MatchOperand_Success;
4355 }
4356
Jim Grosbachae69f702012-01-19 02:47:30 +00004357 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004358 return MatchOperand_ParseFail;
4359}
Jim Grosbach51222d12012-01-20 18:09:51 +00004360
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004361/// Parse a arm instruction operand. For now this parses the operand regardless
4362/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004363bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004364 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004365 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004366
4367 // Check if the current operand has a custom associated parser, if so, try to
4368 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004369 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4370 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004371 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004372 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4373 // there was a match, but an error occurred, in which case, just return that
4374 // the operand parsing failed.
4375 if (ResTy == MatchOperand_ParseFail)
4376 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004377
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004378 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004379 default:
4380 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004381 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004382 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004383 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004384 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004385 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004386 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004387 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004388 else if (Res == -1) // irrecoverable error
4389 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004390 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004391 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4392 S = Parser.getTok().getLoc();
4393 Parser.Lex();
4394 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4395 return false;
4396 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004397
4398 // Fall though for the Identifier case that is not a register or a
4399 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004400 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004401 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004402 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004403 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004404 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004405 // This was not a register so parse other operands that start with an
4406 // identifier (like labels) as expressions and create them as immediates.
4407 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004408 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004409 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004410 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004411 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004412 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4413 return false;
4414 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004415 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004416 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004417 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004418 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004419 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004420 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004421 // #42 -> immediate.
4422 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004423 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004424 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004425 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004426 const MCExpr *ImmVal;
4427 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004428 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004429 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004430 if (CE) {
4431 int32_t Val = CE->getValue();
4432 if (isNegative && Val == 0)
4433 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004434 }
Sean Callanan76264762010-04-02 22:27:05 +00004435 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004436 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4437 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004438 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004439 case AsmToken::Colon: {
4440 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004441 // FIXME: Check it's an expression prefix,
4442 // e.g. (FOO - :lower16:BAR) isn't legal.
4443 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004444 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004445 return true;
4446
Evan Cheng75972122011-01-13 07:58:56 +00004447 const MCExpr *SubExprVal;
4448 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004449 return true;
4450
Evan Cheng75972122011-01-13 07:58:56 +00004451 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4452 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004453 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004454 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004455 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004456 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004457 }
4458}
4459
Jim Grosbach1355cf12011-07-26 17:10:22 +00004460// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004461// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004462bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004463 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004464
4465 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004466 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004467 Parser.Lex(); // Eat ':'
4468
4469 if (getLexer().isNot(AsmToken::Identifier)) {
4470 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4471 return true;
4472 }
4473
4474 StringRef IDVal = Parser.getTok().getIdentifier();
4475 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004476 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004477 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004478 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004479 } else {
4480 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4481 return true;
4482 }
4483 Parser.Lex();
4484
4485 if (getLexer().isNot(AsmToken::Colon)) {
4486 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4487 return true;
4488 }
4489 Parser.Lex(); // Eat the last ':'
4490 return false;
4491}
4492
Daniel Dunbar352e1482011-01-11 15:59:50 +00004493/// \brief Given a mnemonic, split out possible predication code and carry
4494/// setting letters to form a canonical mnemonic and flags.
4495//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004496// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004497// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004498StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004499 unsigned &PredicationCode,
4500 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004501 unsigned &ProcessorIMod,
4502 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004503 PredicationCode = ARMCC::AL;
4504 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004505 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004506
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004507 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004508 //
4509 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004510 if ((Mnemonic == "movs" && isThumb()) ||
4511 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4512 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4513 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4514 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4515 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4516 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004517 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4518 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004519 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004520
Jim Grosbach3f00e312011-07-11 17:09:57 +00004521 // First, split out any predication code. Ignore mnemonics we know aren't
4522 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004523 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004524 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004525 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004526 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004527 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4528 .Case("eq", ARMCC::EQ)
4529 .Case("ne", ARMCC::NE)
4530 .Case("hs", ARMCC::HS)
4531 .Case("cs", ARMCC::HS)
4532 .Case("lo", ARMCC::LO)
4533 .Case("cc", ARMCC::LO)
4534 .Case("mi", ARMCC::MI)
4535 .Case("pl", ARMCC::PL)
4536 .Case("vs", ARMCC::VS)
4537 .Case("vc", ARMCC::VC)
4538 .Case("hi", ARMCC::HI)
4539 .Case("ls", ARMCC::LS)
4540 .Case("ge", ARMCC::GE)
4541 .Case("lt", ARMCC::LT)
4542 .Case("gt", ARMCC::GT)
4543 .Case("le", ARMCC::LE)
4544 .Case("al", ARMCC::AL)
4545 .Default(~0U);
4546 if (CC != ~0U) {
4547 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4548 PredicationCode = CC;
4549 }
Bill Wendling52925b62010-10-29 23:50:21 +00004550 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004551
Daniel Dunbar352e1482011-01-11 15:59:50 +00004552 // Next, determine if we have a carry setting bit. We explicitly ignore all
4553 // the instructions we know end in 's'.
4554 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004555 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004556 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4557 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4558 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004559 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004560 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004561 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004562 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004563 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004564 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4565 CarrySetting = true;
4566 }
4567
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004568 // The "cps" instruction can have a interrupt mode operand which is glued into
4569 // the mnemonic. Check if this is the case, split it and parse the imod op
4570 if (Mnemonic.startswith("cps")) {
4571 // Split out any imod code.
4572 unsigned IMod =
4573 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4574 .Case("ie", ARM_PROC::IE)
4575 .Case("id", ARM_PROC::ID)
4576 .Default(~0U);
4577 if (IMod != ~0U) {
4578 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4579 ProcessorIMod = IMod;
4580 }
4581 }
4582
Jim Grosbach89df9962011-08-26 21:43:41 +00004583 // The "it" instruction has the condition mask on the end of the mnemonic.
4584 if (Mnemonic.startswith("it")) {
4585 ITMask = Mnemonic.slice(2, Mnemonic.size());
4586 Mnemonic = Mnemonic.slice(0, 2);
4587 }
4588
Daniel Dunbar352e1482011-01-11 15:59:50 +00004589 return Mnemonic;
4590}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004591
4592/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4593/// inclusion of carry set or predication code operands.
4594//
4595// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004596void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004597getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004598 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004599 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4600 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004601 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004602 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004603 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004604 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004605 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004606 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004607 Mnemonic == "mla" || Mnemonic == "smlal" ||
4608 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004609 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004610 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004611 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004612
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004613 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4614 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4615 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4616 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004617 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4618 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004619 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004620 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4621 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4622 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004623 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4624 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004625 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004626 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004627 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004628 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004629
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004630 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004631 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004632 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004633 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004634 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004635}
4636
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004637bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4638 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004639 // FIXME: This is all horribly hacky. We really need a better way to deal
4640 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004641
4642 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4643 // another does not. Specifically, the MOVW instruction does not. So we
4644 // special case it here and remove the defaulted (non-setting) cc_out
4645 // operand if that's the instruction we're trying to match.
4646 //
4647 // We do this as post-processing of the explicit operands rather than just
4648 // conditionally adding the cc_out in the first place because we need
4649 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004650 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004651 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4652 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4653 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4654 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004655
4656 // Register-register 'add' for thumb does not have a cc_out operand
4657 // when there are only two register operands.
4658 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4659 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4660 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4661 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4662 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004663 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004664 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4665 // have to check the immediate range here since Thumb2 has a variant
4666 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004667 if (((isThumb() && Mnemonic == "add") ||
4668 (isThumbTwo() && Mnemonic == "sub")) &&
4669 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004670 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4671 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4672 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004673 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4674 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4675 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004676 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004677 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4678 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004679 // selecting via the generic "add" mnemonic, so to know that we
4680 // should remove the cc_out operand, we have to explicitly check that
4681 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004682 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4683 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004684 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4685 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4686 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4687 // Nest conditions rather than one big 'if' statement for readability.
4688 //
4689 // If either register is a high reg, it's either one of the SP
4690 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004691 // check against T3. If the second register is the PC, this is an
4692 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004693 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4694 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004695 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004696 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4697 return false;
4698 // If both registers are low, we're in an IT block, and the immediate is
4699 // in range, we should use encoding T1 instead, which has a cc_out.
4700 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004701 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004702 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4703 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4704 return false;
4705
4706 // Otherwise, we use encoding T4, which does not have a cc_out
4707 // operand.
4708 return true;
4709 }
4710
Jim Grosbach64944f42011-09-14 21:00:40 +00004711 // The thumb2 multiply instruction doesn't have a CCOut register, so
4712 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4713 // use the 16-bit encoding or not.
4714 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4715 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4716 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4717 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4718 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4719 // If the registers aren't low regs, the destination reg isn't the
4720 // same as one of the source regs, or the cc_out operand is zero
4721 // outside of an IT block, we have to use the 32-bit encoding, so
4722 // remove the cc_out operand.
4723 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4724 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004725 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004726 !inITBlock() ||
4727 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4728 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4729 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4730 static_cast<ARMOperand*>(Operands[4])->getReg())))
4731 return true;
4732
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004733 // Also check the 'mul' syntax variant that doesn't specify an explicit
4734 // destination register.
4735 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4736 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4737 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4738 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4739 // If the registers aren't low regs or the cc_out operand is zero
4740 // outside of an IT block, we have to use the 32-bit encoding, so
4741 // remove the cc_out operand.
4742 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4743 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4744 !inITBlock()))
4745 return true;
4746
Jim Grosbach64944f42011-09-14 21:00:40 +00004747
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004748
Jim Grosbachf69c8042011-08-24 21:42:27 +00004749 // Register-register 'add/sub' for thumb does not have a cc_out operand
4750 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4751 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4752 // right, this will result in better diagnostics (which operand is off)
4753 // anyway.
4754 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4755 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004756 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4757 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4758 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4759 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004760
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004761 return false;
4762}
4763
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004764static bool isDataTypeToken(StringRef Tok) {
4765 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4766 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4767 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4768 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4769 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4770 Tok == ".f" || Tok == ".d";
4771}
4772
4773// FIXME: This bit should probably be handled via an explicit match class
4774// in the .td files that matches the suffix instead of having it be
4775// a literal string token the way it is now.
4776static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4777 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4778}
4779
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004780static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004781/// Parse an arm instruction mnemonic followed by its operands.
4782bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4783 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004784 // Apply mnemonic aliases before doing anything else, as the destination
4785 // mnemnonic may include suffices and we want to handle them normally.
4786 // The generic tblgen'erated code does this later, at the start of
4787 // MatchInstructionImpl(), but that's too late for aliases that include
4788 // any sort of suffix.
4789 unsigned AvailableFeatures = getAvailableFeatures();
4790 applyMnemonicAliases(Name, AvailableFeatures);
4791
Jim Grosbacha39cda72011-12-14 02:16:11 +00004792 // First check for the ARM-specific .req directive.
4793 if (Parser.getTok().is(AsmToken::Identifier) &&
4794 Parser.getTok().getIdentifier() == ".req") {
4795 parseDirectiveReq(Name, NameLoc);
4796 // We always return 'error' for this, as we're done with this
4797 // statement and don't need to match the 'instruction."
4798 return true;
4799 }
4800
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004801 // Create the leading tokens for the mnemonic, split by '.' characters.
4802 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004803 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004804
Daniel Dunbar352e1482011-01-11 15:59:50 +00004805 // Split out the predication code and carry setting flag from the mnemonic.
4806 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004807 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004808 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004809 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004810 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004811 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004812
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004813 // In Thumb1, only the branch (B) instruction can be predicated.
4814 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4815 Parser.EatToEndOfStatement();
4816 return Error(NameLoc, "conditional execution not supported in Thumb1");
4817 }
4818
Jim Grosbachffa32252011-07-19 19:13:28 +00004819 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4820
Jim Grosbach89df9962011-08-26 21:43:41 +00004821 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4822 // is the mask as it will be for the IT encoding if the conditional
4823 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4824 // where the conditional bit0 is zero, the instruction post-processing
4825 // will adjust the mask accordingly.
4826 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004827 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4828 if (ITMask.size() > 3) {
4829 Parser.EatToEndOfStatement();
4830 return Error(Loc, "too many conditions on IT instruction");
4831 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004832 unsigned Mask = 8;
4833 for (unsigned i = ITMask.size(); i != 0; --i) {
4834 char pos = ITMask[i - 1];
4835 if (pos != 't' && pos != 'e') {
4836 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004837 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004838 }
4839 Mask >>= 1;
4840 if (ITMask[i - 1] == 't')
4841 Mask |= 8;
4842 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004843 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004844 }
4845
Jim Grosbachffa32252011-07-19 19:13:28 +00004846 // FIXME: This is all a pretty gross hack. We should automatically handle
4847 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004848
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004849 // Next, add the CCOut and ConditionCode operands, if needed.
4850 //
4851 // For mnemonics which can ever incorporate a carry setting bit or predication
4852 // code, our matching model involves us always generating CCOut and
4853 // ConditionCode operands to match the mnemonic "as written" and then we let
4854 // the matcher deal with finding the right instruction or generating an
4855 // appropriate error.
4856 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004857 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004858
Jim Grosbach33c16a22011-07-14 22:04:21 +00004859 // If we had a carry-set on an instruction that can't do that, issue an
4860 // error.
4861 if (!CanAcceptCarrySet && CarrySetting) {
4862 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004863 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004864 "' can not set flags, but 's' suffix specified");
4865 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004866 // If we had a predication code on an instruction that can't do that, issue an
4867 // error.
4868 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4869 Parser.EatToEndOfStatement();
4870 return Error(NameLoc, "instruction '" + Mnemonic +
4871 "' is not predicable, but condition code specified");
4872 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004873
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004874 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004875 if (CanAcceptCarrySet) {
4876 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004877 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004878 Loc));
4879 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004880
4881 // Add the predication code operand, if necessary.
4882 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004883 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4884 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004885 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004886 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004887 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004888
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004889 // Add the processor imod operand, if necessary.
4890 if (ProcessorIMod) {
4891 Operands.push_back(ARMOperand::CreateImm(
4892 MCConstantExpr::Create(ProcessorIMod, getContext()),
4893 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004894 }
4895
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004896 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004897 while (Next != StringRef::npos) {
4898 Start = Next;
4899 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004900 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004901
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004902 // Some NEON instructions have an optional datatype suffix that is
4903 // completely ignored. Check for that.
4904 if (isDataTypeToken(ExtraToken) &&
4905 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4906 continue;
4907
Jim Grosbach81d2e392011-09-07 16:06:04 +00004908 if (ExtraToken != ".n") {
4909 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4910 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4911 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004912 }
4913
4914 // Read the remaining operands.
4915 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004916 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004917 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004918 Parser.EatToEndOfStatement();
4919 return true;
4920 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004921
4922 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004923 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004924
4925 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004926 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004927 Parser.EatToEndOfStatement();
4928 return true;
4929 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004930 }
4931 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004932
Chris Lattnercbf8a982010-09-11 16:18:25 +00004933 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004934 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004935 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004936 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004937 }
Bill Wendling146018f2010-11-06 21:42:12 +00004938
Chris Lattner34e53142010-09-08 05:10:46 +00004939 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004940
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004941 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4942 // do and don't have a cc_out optional-def operand. With some spot-checks
4943 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004944 // parse and adjust accordingly before actually matching. We shouldn't ever
4945 // try to remove a cc_out operand that was explicitly set on the the
4946 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4947 // table driven matcher doesn't fit well with the ARM instruction set.
4948 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004949 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4950 Operands.erase(Operands.begin() + 1);
4951 delete Op;
4952 }
4953
Jim Grosbachcf121c32011-07-28 21:57:55 +00004954 // ARM mode 'blx' need special handling, as the register operand version
4955 // is predicable, but the label operand version is not. So, we can't rely
4956 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004957 // a k_CondCode operand in the list. If we're trying to match the label
4958 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004959 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4960 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4961 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4962 Operands.erase(Operands.begin() + 1);
4963 delete Op;
4964 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004965
4966 // The vector-compare-to-zero instructions have a literal token "#0" at
4967 // the end that comes to here as an immediate operand. Convert it to a
4968 // token to play nicely with the matcher.
4969 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4970 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4971 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4972 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4973 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4974 if (CE && CE->getValue() == 0) {
4975 Operands.erase(Operands.begin() + 5);
4976 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4977 delete Op;
4978 }
4979 }
Jim Grosbach68259142011-10-03 22:30:24 +00004980 // VCMP{E} does the same thing, but with a different operand count.
4981 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4982 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4983 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4984 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4985 if (CE && CE->getValue() == 0) {
4986 Operands.erase(Operands.begin() + 4);
4987 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4988 delete Op;
4989 }
4990 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004991 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004992 // end. Convert it to a token here. Take care not to convert those
4993 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004994 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004995 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4996 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004997 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4998 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4999 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005000 if (CE && CE->getValue() == 0 &&
5001 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005002 // The cc_out operand matches the IT block.
5003 ((inITBlock() != CarrySetting) &&
5004 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005005 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005006 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005007 Operands.erase(Operands.begin() + 5);
5008 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5009 delete Op;
5010 }
5011 }
5012
Chris Lattner98986712010-01-14 22:21:20 +00005013 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005014}
5015
Jim Grosbach189610f2011-07-26 18:25:39 +00005016// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005017
5018// return 'true' if register list contains non-low GPR registers,
5019// 'false' otherwise. If Reg is in the register list or is HiReg, set
5020// 'containsReg' to true.
5021static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5022 unsigned HiReg, bool &containsReg) {
5023 containsReg = false;
5024 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5025 unsigned OpReg = Inst.getOperand(i).getReg();
5026 if (OpReg == Reg)
5027 containsReg = true;
5028 // Anything other than a low register isn't legal here.
5029 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5030 return true;
5031 }
5032 return false;
5033}
5034
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005035// Check if the specified regisgter is in the register list of the inst,
5036// starting at the indicated operand number.
5037static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5038 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5039 unsigned OpReg = Inst.getOperand(i).getReg();
5040 if (OpReg == Reg)
5041 return true;
5042 }
5043 return false;
5044}
5045
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005046// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5047// the ARMInsts array) instead. Getting that here requires awkward
5048// API changes, though. Better way?
5049namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005050extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005051}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005052static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005053 return ARMInsts[Opcode];
5054}
5055
Jim Grosbach189610f2011-07-26 18:25:39 +00005056// FIXME: We would really like to be able to tablegen'erate this.
5057bool ARMAsmParser::
5058validateInstruction(MCInst &Inst,
5059 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005060 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005061 SMLoc Loc = Operands[0]->getStartLoc();
5062 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00005063 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
5064 // being allowed in IT blocks, but not being predicable. It just always
5065 // executes.
5066 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005067 unsigned bit = 1;
5068 if (ITState.FirstCond)
5069 ITState.FirstCond = false;
5070 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005071 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005072 // The instruction must be predicable.
5073 if (!MCID.isPredicable())
5074 return Error(Loc, "instructions in IT block must be predicable");
5075 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5076 unsigned ITCond = bit ? ITState.Cond :
5077 ARMCC::getOppositeCondition(ITState.Cond);
5078 if (Cond != ITCond) {
5079 // Find the condition code Operand to get its SMLoc information.
5080 SMLoc CondLoc;
5081 for (unsigned i = 1; i < Operands.size(); ++i)
5082 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5083 CondLoc = Operands[i]->getStartLoc();
5084 return Error(CondLoc, "incorrect condition in IT block; got '" +
5085 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5086 "', but expected '" +
5087 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5088 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005089 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005090 } else if (isThumbTwo() && MCID.isPredicable() &&
5091 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005092 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5093 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005094 return Error(Loc, "predicated instructions must be in IT block");
5095
Jim Grosbach189610f2011-07-26 18:25:39 +00005096 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005097 case ARM::LDRD:
5098 case ARM::LDRD_PRE:
5099 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005100 case ARM::LDREXD: {
5101 // Rt2 must be Rt + 1.
5102 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5103 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5104 if (Rt2 != Rt + 1)
5105 return Error(Operands[3]->getStartLoc(),
5106 "destination operands must be sequential");
5107 return false;
5108 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005109 case ARM::STRD: {
5110 // Rt2 must be Rt + 1.
5111 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5112 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5113 if (Rt2 != Rt + 1)
5114 return Error(Operands[3]->getStartLoc(),
5115 "source operands must be sequential");
5116 return false;
5117 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005118 case ARM::STRD_PRE:
5119 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005120 case ARM::STREXD: {
5121 // Rt2 must be Rt + 1.
5122 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5123 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5124 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005125 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005126 "source operands must be sequential");
5127 return false;
5128 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005129 case ARM::SBFX:
5130 case ARM::UBFX: {
5131 // width must be in range [1, 32-lsb]
5132 unsigned lsb = Inst.getOperand(2).getImm();
5133 unsigned widthm1 = Inst.getOperand(3).getImm();
5134 if (widthm1 >= 32 - lsb)
5135 return Error(Operands[5]->getStartLoc(),
5136 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005137 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005138 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005139 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005140 // If we're parsing Thumb2, the .w variant is available and handles
5141 // most cases that are normally illegal for a Thumb1 LDM
5142 // instruction. We'll make the transformation in processInstruction()
5143 // if necessary.
5144 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005145 // Thumb LDM instructions are writeback iff the base register is not
5146 // in the register list.
5147 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005148 bool hasWritebackToken =
5149 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5150 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005151 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005152 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005153 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5154 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005155 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005156 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005157 return Error(Operands[2]->getStartLoc(),
5158 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005159 // If we should not have writeback, there must not be a '!'. This is
5160 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005161 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005162 return Error(Operands[3]->getStartLoc(),
5163 "writeback operator '!' not allowed when base register "
5164 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005165
5166 break;
5167 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005168 case ARM::t2LDMIA_UPD: {
5169 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5170 return Error(Operands[4]->getStartLoc(),
5171 "writeback operator '!' not allowed when base register "
5172 "in register list");
5173 break;
5174 }
Jim Grosbach54026372011-11-10 23:17:11 +00005175 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5176 // so only issue a diagnostic for thumb1. The instructions will be
5177 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005178 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005179 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005180 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5181 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005182 return Error(Operands[2]->getStartLoc(),
5183 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005184 break;
5185 }
5186 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005187 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005188 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5189 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005190 return Error(Operands[2]->getStartLoc(),
5191 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005192 break;
5193 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005194 case ARM::tSTMIA_UPD: {
5195 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005196 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005197 return Error(Operands[4]->getStartLoc(),
5198 "registers must be in range r0-r7");
5199 break;
5200 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005201 }
5202
5203 return false;
5204}
5205
Jim Grosbachd7433e22012-01-23 23:45:44 +00005206static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005207 switch(Opc) {
5208 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005209 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005210 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5211 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5212 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5213 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5214 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5215 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5216 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5217 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5218 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005219
5220 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005221 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5222 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5223 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5224 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5225 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005226
Jim Grosbach7945ead2012-01-24 00:43:12 +00005227 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5228 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5229 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5230 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5231 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005232
Jim Grosbach7945ead2012-01-24 00:43:12 +00005233 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5234 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5235 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5236 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5237 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005238
Jim Grosbach4adb1822012-01-24 00:07:41 +00005239 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005240 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5241 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5242 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5243 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5244 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5245 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5246 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5247 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5248 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5249 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5250 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5251 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5252 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5253 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5254 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005255
Jim Grosbachd7433e22012-01-23 23:45:44 +00005256 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005257 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5258 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5259 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5260 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5261 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5262 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5263 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5264 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5265 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5266 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5267 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5268 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5269 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5270 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5271 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5272 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5273 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5274 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005275
5276 // VST4
5277 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5278 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5279 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5280 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5281 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5282 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5283 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5284 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5285 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5286 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5287 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5288 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5289 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5290 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5291 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5292 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5293 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5294 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005295 }
5296}
5297
Jim Grosbachd7433e22012-01-23 23:45:44 +00005298static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005299 switch(Opc) {
5300 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005301 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005302 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5303 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5304 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5305 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5306 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5307 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5308 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5309 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5310 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005311
5312 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005313 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5314 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5315 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5316 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5317 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5318 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5319 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5320 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5321 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5322 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5323 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5324 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5325 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5326 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5327 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005328
5329 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005330 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5331 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5332 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5333 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5334 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5335 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5336 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5337 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5338 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5339 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5340 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5341 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5342 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5343 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5344 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005345
5346 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005347 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5348 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5349 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5350 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5351 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5352 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5353 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5354 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5355 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5356 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5357 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5358 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5359 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5360 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5361 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5362 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5363 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5364 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005365
Jim Grosbache983a132012-01-24 18:37:25 +00005366 // VLD4LN
5367 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5368 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5369 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5370 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5371 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5372 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5373 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5374 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5375 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5376 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5377 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5378 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5379 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5380 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5381 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5382
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005383 // VLD4
5384 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5385 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5386 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5387 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5388 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5389 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5390 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5391 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5392 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5393 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5394 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5395 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5396 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5397 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5398 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5399 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5400 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5401 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005402 }
5403}
5404
Jim Grosbach83ec8772011-11-10 23:42:14 +00005405bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005406processInstruction(MCInst &Inst,
5407 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5408 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005409 // Aliases for alternate PC+imm syntax of LDR instructions.
5410 case ARM::t2LDRpcrel:
5411 Inst.setOpcode(ARM::t2LDRpci);
5412 return true;
5413 case ARM::t2LDRBpcrel:
5414 Inst.setOpcode(ARM::t2LDRBpci);
5415 return true;
5416 case ARM::t2LDRHpcrel:
5417 Inst.setOpcode(ARM::t2LDRHpci);
5418 return true;
5419 case ARM::t2LDRSBpcrel:
5420 Inst.setOpcode(ARM::t2LDRSBpci);
5421 return true;
5422 case ARM::t2LDRSHpcrel:
5423 Inst.setOpcode(ARM::t2LDRSHpci);
5424 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005425 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005426 case ARM::VST1LNdWB_register_Asm_8:
5427 case ARM::VST1LNdWB_register_Asm_16:
5428 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005429 MCInst TmpInst;
5430 // Shuffle the operands around so the lane index operand is in the
5431 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005432 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005433 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005434 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5435 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5436 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5437 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5438 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5439 TmpInst.addOperand(Inst.getOperand(1)); // lane
5440 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5441 TmpInst.addOperand(Inst.getOperand(6));
5442 Inst = TmpInst;
5443 return true;
5444 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005445
Jim Grosbach8b31f952012-01-23 19:39:08 +00005446 case ARM::VST2LNdWB_register_Asm_8:
5447 case ARM::VST2LNdWB_register_Asm_16:
5448 case ARM::VST2LNdWB_register_Asm_32:
5449 case ARM::VST2LNqWB_register_Asm_16:
5450 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005451 MCInst TmpInst;
5452 // Shuffle the operands around so the lane index operand is in the
5453 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005454 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005455 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005456 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5457 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5458 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5459 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5460 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005461 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5462 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005463 TmpInst.addOperand(Inst.getOperand(1)); // lane
5464 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5465 TmpInst.addOperand(Inst.getOperand(6));
5466 Inst = TmpInst;
5467 return true;
5468 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005469
5470 case ARM::VST3LNdWB_register_Asm_8:
5471 case ARM::VST3LNdWB_register_Asm_16:
5472 case ARM::VST3LNdWB_register_Asm_32:
5473 case ARM::VST3LNqWB_register_Asm_16:
5474 case ARM::VST3LNqWB_register_Asm_32: {
5475 MCInst TmpInst;
5476 // Shuffle the operands around so the lane index operand is in the
5477 // right place.
5478 unsigned Spacing;
5479 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5480 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5481 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5482 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5483 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5484 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5485 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5486 Spacing));
5487 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5488 Spacing * 2));
5489 TmpInst.addOperand(Inst.getOperand(1)); // lane
5490 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5491 TmpInst.addOperand(Inst.getOperand(6));
5492 Inst = TmpInst;
5493 return true;
5494 }
5495
Jim Grosbach8b31f952012-01-23 19:39:08 +00005496 case ARM::VST1LNdWB_fixed_Asm_8:
5497 case ARM::VST1LNdWB_fixed_Asm_16:
5498 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005499 MCInst TmpInst;
5500 // Shuffle the operands around so the lane index operand is in the
5501 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005502 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005503 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005504 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5505 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5506 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5507 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5508 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5509 TmpInst.addOperand(Inst.getOperand(1)); // lane
5510 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5511 TmpInst.addOperand(Inst.getOperand(5));
5512 Inst = TmpInst;
5513 return true;
5514 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005515
Jim Grosbach8b31f952012-01-23 19:39:08 +00005516 case ARM::VST2LNdWB_fixed_Asm_8:
5517 case ARM::VST2LNdWB_fixed_Asm_16:
5518 case ARM::VST2LNdWB_fixed_Asm_32:
5519 case ARM::VST2LNqWB_fixed_Asm_16:
5520 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005521 MCInst TmpInst;
5522 // Shuffle the operands around so the lane index operand is in the
5523 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005524 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005525 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005526 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5527 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5528 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5529 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5530 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005531 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5532 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005533 TmpInst.addOperand(Inst.getOperand(1)); // lane
5534 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5535 TmpInst.addOperand(Inst.getOperand(5));
5536 Inst = TmpInst;
5537 return true;
5538 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005539
5540 case ARM::VST3LNdWB_fixed_Asm_8:
5541 case ARM::VST3LNdWB_fixed_Asm_16:
5542 case ARM::VST3LNdWB_fixed_Asm_32:
5543 case ARM::VST3LNqWB_fixed_Asm_16:
5544 case ARM::VST3LNqWB_fixed_Asm_32: {
5545 MCInst TmpInst;
5546 // Shuffle the operands around so the lane index operand is in the
5547 // right place.
5548 unsigned Spacing;
5549 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5550 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5551 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5552 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5553 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5554 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5555 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5556 Spacing));
5557 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5558 Spacing * 2));
5559 TmpInst.addOperand(Inst.getOperand(1)); // lane
5560 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5561 TmpInst.addOperand(Inst.getOperand(5));
5562 Inst = TmpInst;
5563 return true;
5564 }
5565
Jim Grosbach8b31f952012-01-23 19:39:08 +00005566 case ARM::VST1LNdAsm_8:
5567 case ARM::VST1LNdAsm_16:
5568 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005569 MCInst TmpInst;
5570 // Shuffle the operands around so the lane index operand is in the
5571 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005572 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005573 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005574 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5575 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5576 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5577 TmpInst.addOperand(Inst.getOperand(1)); // lane
5578 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5579 TmpInst.addOperand(Inst.getOperand(5));
5580 Inst = TmpInst;
5581 return true;
5582 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005583
Jim Grosbach8b31f952012-01-23 19:39:08 +00005584 case ARM::VST2LNdAsm_8:
5585 case ARM::VST2LNdAsm_16:
5586 case ARM::VST2LNdAsm_32:
5587 case ARM::VST2LNqAsm_16:
5588 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005589 MCInst TmpInst;
5590 // Shuffle the operands around so the lane index operand is in the
5591 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005592 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005593 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005594 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5595 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5596 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5598 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005599 TmpInst.addOperand(Inst.getOperand(1)); // lane
5600 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5601 TmpInst.addOperand(Inst.getOperand(5));
5602 Inst = TmpInst;
5603 return true;
5604 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005605
5606 case ARM::VST3LNdAsm_8:
5607 case ARM::VST3LNdAsm_16:
5608 case ARM::VST3LNdAsm_32:
5609 case ARM::VST3LNqAsm_16:
5610 case ARM::VST3LNqAsm_32: {
5611 MCInst TmpInst;
5612 // Shuffle the operands around so the lane index operand is in the
5613 // right place.
5614 unsigned Spacing;
5615 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5616 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5617 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5618 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5619 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5620 Spacing));
5621 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5622 Spacing * 2));
5623 TmpInst.addOperand(Inst.getOperand(1)); // lane
5624 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5625 TmpInst.addOperand(Inst.getOperand(5));
5626 Inst = TmpInst;
5627 return true;
5628 }
5629
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005630 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005631 case ARM::VLD1LNdWB_register_Asm_8:
5632 case ARM::VLD1LNdWB_register_Asm_16:
5633 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005634 MCInst TmpInst;
5635 // Shuffle the operands around so the lane index operand is in the
5636 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005637 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005638 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005639 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5640 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5641 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5642 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5643 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5644 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5645 TmpInst.addOperand(Inst.getOperand(1)); // lane
5646 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5647 TmpInst.addOperand(Inst.getOperand(6));
5648 Inst = TmpInst;
5649 return true;
5650 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005651
Jim Grosbach8b31f952012-01-23 19:39:08 +00005652 case ARM::VLD2LNdWB_register_Asm_8:
5653 case ARM::VLD2LNdWB_register_Asm_16:
5654 case ARM::VLD2LNdWB_register_Asm_32:
5655 case ARM::VLD2LNqWB_register_Asm_16:
5656 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005657 MCInst TmpInst;
5658 // Shuffle the operands around so the lane index operand is in the
5659 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005660 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005661 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005662 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005663 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5664 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005665 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5666 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5667 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5668 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5669 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005670 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5671 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005672 TmpInst.addOperand(Inst.getOperand(1)); // lane
5673 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5674 TmpInst.addOperand(Inst.getOperand(6));
5675 Inst = TmpInst;
5676 return true;
5677 }
5678
Jim Grosbach3a678af2012-01-23 21:53:26 +00005679 case ARM::VLD3LNdWB_register_Asm_8:
5680 case ARM::VLD3LNdWB_register_Asm_16:
5681 case ARM::VLD3LNdWB_register_Asm_32:
5682 case ARM::VLD3LNqWB_register_Asm_16:
5683 case ARM::VLD3LNqWB_register_Asm_32: {
5684 MCInst TmpInst;
5685 // Shuffle the operands around so the lane index operand is in the
5686 // right place.
5687 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005688 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005689 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5690 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5691 Spacing));
5692 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005693 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005694 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5695 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5696 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5697 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5698 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5699 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5700 Spacing));
5701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005702 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005703 TmpInst.addOperand(Inst.getOperand(1)); // lane
5704 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5705 TmpInst.addOperand(Inst.getOperand(6));
5706 Inst = TmpInst;
5707 return true;
5708 }
5709
Jim Grosbache983a132012-01-24 18:37:25 +00005710 case ARM::VLD4LNdWB_register_Asm_8:
5711 case ARM::VLD4LNdWB_register_Asm_16:
5712 case ARM::VLD4LNdWB_register_Asm_32:
5713 case ARM::VLD4LNqWB_register_Asm_16:
5714 case ARM::VLD4LNqWB_register_Asm_32: {
5715 MCInst TmpInst;
5716 // Shuffle the operands around so the lane index operand is in the
5717 // right place.
5718 unsigned Spacing;
5719 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5720 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5721 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5722 Spacing));
5723 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5724 Spacing * 2));
5725 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5726 Spacing * 3));
5727 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5728 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5729 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5730 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5731 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5732 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5733 Spacing));
5734 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5735 Spacing * 2));
5736 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5737 Spacing * 3));
5738 TmpInst.addOperand(Inst.getOperand(1)); // lane
5739 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5740 TmpInst.addOperand(Inst.getOperand(6));
5741 Inst = TmpInst;
5742 return true;
5743 }
5744
Jim Grosbach8b31f952012-01-23 19:39:08 +00005745 case ARM::VLD1LNdWB_fixed_Asm_8:
5746 case ARM::VLD1LNdWB_fixed_Asm_16:
5747 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005748 MCInst TmpInst;
5749 // Shuffle the operands around so the lane index operand is in the
5750 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005751 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005752 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005753 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5754 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5755 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5756 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5757 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5758 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5759 TmpInst.addOperand(Inst.getOperand(1)); // lane
5760 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5761 TmpInst.addOperand(Inst.getOperand(5));
5762 Inst = TmpInst;
5763 return true;
5764 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005765
Jim Grosbach8b31f952012-01-23 19:39:08 +00005766 case ARM::VLD2LNdWB_fixed_Asm_8:
5767 case ARM::VLD2LNdWB_fixed_Asm_16:
5768 case ARM::VLD2LNdWB_fixed_Asm_32:
5769 case ARM::VLD2LNqWB_fixed_Asm_16:
5770 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005771 MCInst TmpInst;
5772 // Shuffle the operands around so the lane index operand is in the
5773 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005774 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005775 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005776 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005777 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5778 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005779 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5780 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5781 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5782 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5783 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005784 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5785 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005786 TmpInst.addOperand(Inst.getOperand(1)); // lane
5787 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5788 TmpInst.addOperand(Inst.getOperand(5));
5789 Inst = TmpInst;
5790 return true;
5791 }
5792
Jim Grosbach3a678af2012-01-23 21:53:26 +00005793 case ARM::VLD3LNdWB_fixed_Asm_8:
5794 case ARM::VLD3LNdWB_fixed_Asm_16:
5795 case ARM::VLD3LNdWB_fixed_Asm_32:
5796 case ARM::VLD3LNqWB_fixed_Asm_16:
5797 case ARM::VLD3LNqWB_fixed_Asm_32: {
5798 MCInst TmpInst;
5799 // Shuffle the operands around so the lane index operand is in the
5800 // right place.
5801 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005802 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005803 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5804 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5805 Spacing));
5806 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005807 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005808 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5809 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5810 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5811 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5812 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5813 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5814 Spacing));
5815 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005816 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005817 TmpInst.addOperand(Inst.getOperand(1)); // lane
5818 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5819 TmpInst.addOperand(Inst.getOperand(5));
5820 Inst = TmpInst;
5821 return true;
5822 }
5823
Jim Grosbache983a132012-01-24 18:37:25 +00005824 case ARM::VLD4LNdWB_fixed_Asm_8:
5825 case ARM::VLD4LNdWB_fixed_Asm_16:
5826 case ARM::VLD4LNdWB_fixed_Asm_32:
5827 case ARM::VLD4LNqWB_fixed_Asm_16:
5828 case ARM::VLD4LNqWB_fixed_Asm_32: {
5829 MCInst TmpInst;
5830 // Shuffle the operands around so the lane index operand is in the
5831 // right place.
5832 unsigned Spacing;
5833 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5834 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5835 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5836 Spacing));
5837 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5838 Spacing * 2));
5839 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5840 Spacing * 3));
5841 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5842 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5843 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5844 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5845 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5846 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5847 Spacing));
5848 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5849 Spacing * 2));
5850 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5851 Spacing * 3));
5852 TmpInst.addOperand(Inst.getOperand(1)); // lane
5853 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5854 TmpInst.addOperand(Inst.getOperand(5));
5855 Inst = TmpInst;
5856 return true;
5857 }
5858
Jim Grosbach8b31f952012-01-23 19:39:08 +00005859 case ARM::VLD1LNdAsm_8:
5860 case ARM::VLD1LNdAsm_16:
5861 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005862 MCInst TmpInst;
5863 // Shuffle the operands around so the lane index operand is in the
5864 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005865 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005866 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005867 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5868 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5869 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5870 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5871 TmpInst.addOperand(Inst.getOperand(1)); // lane
5872 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5873 TmpInst.addOperand(Inst.getOperand(5));
5874 Inst = TmpInst;
5875 return true;
5876 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005877
Jim Grosbach8b31f952012-01-23 19:39:08 +00005878 case ARM::VLD2LNdAsm_8:
5879 case ARM::VLD2LNdAsm_16:
5880 case ARM::VLD2LNdAsm_32:
5881 case ARM::VLD2LNqAsm_16:
5882 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005883 MCInst TmpInst;
5884 // Shuffle the operands around so the lane index operand is in the
5885 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005886 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005887 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005888 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005889 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5890 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005891 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5892 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5893 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005894 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5895 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005896 TmpInst.addOperand(Inst.getOperand(1)); // lane
5897 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5898 TmpInst.addOperand(Inst.getOperand(5));
5899 Inst = TmpInst;
5900 return true;
5901 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00005902
5903 case ARM::VLD3LNdAsm_8:
5904 case ARM::VLD3LNdAsm_16:
5905 case ARM::VLD3LNdAsm_32:
5906 case ARM::VLD3LNqAsm_16:
5907 case ARM::VLD3LNqAsm_32: {
5908 MCInst TmpInst;
5909 // Shuffle the operands around so the lane index operand is in the
5910 // right place.
5911 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005912 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005913 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5914 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5915 Spacing));
5916 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005917 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005918 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5919 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5920 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5921 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5922 Spacing));
5923 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005924 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005925 TmpInst.addOperand(Inst.getOperand(1)); // lane
5926 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5927 TmpInst.addOperand(Inst.getOperand(5));
5928 Inst = TmpInst;
5929 return true;
5930 }
5931
Jim Grosbache983a132012-01-24 18:37:25 +00005932 case ARM::VLD4LNdAsm_8:
5933 case ARM::VLD4LNdAsm_16:
5934 case ARM::VLD4LNdAsm_32:
5935 case ARM::VLD4LNqAsm_16:
5936 case ARM::VLD4LNqAsm_32: {
5937 MCInst TmpInst;
5938 // Shuffle the operands around so the lane index operand is in the
5939 // right place.
5940 unsigned Spacing;
5941 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5942 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5943 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5944 Spacing));
5945 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5946 Spacing * 2));
5947 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5948 Spacing * 3));
5949 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5950 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5951 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5952 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5953 Spacing));
5954 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5955 Spacing * 2));
5956 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5957 Spacing * 3));
5958 TmpInst.addOperand(Inst.getOperand(1)); // lane
5959 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5960 TmpInst.addOperand(Inst.getOperand(5));
5961 Inst = TmpInst;
5962 return true;
5963 }
5964
Jim Grosbachc387fc62012-01-23 23:20:46 +00005965 // VLD3 multiple 3-element structure instructions.
5966 case ARM::VLD3dAsm_8:
5967 case ARM::VLD3dAsm_16:
5968 case ARM::VLD3dAsm_32:
5969 case ARM::VLD3qAsm_8:
5970 case ARM::VLD3qAsm_16:
5971 case ARM::VLD3qAsm_32: {
5972 MCInst TmpInst;
5973 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005974 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005975 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5976 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5977 Spacing));
5978 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5979 Spacing * 2));
5980 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5981 TmpInst.addOperand(Inst.getOperand(2)); // alignment
5982 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5983 TmpInst.addOperand(Inst.getOperand(4));
5984 Inst = TmpInst;
5985 return true;
5986 }
5987
5988 case ARM::VLD3dWB_fixed_Asm_8:
5989 case ARM::VLD3dWB_fixed_Asm_16:
5990 case ARM::VLD3dWB_fixed_Asm_32:
5991 case ARM::VLD3qWB_fixed_Asm_8:
5992 case ARM::VLD3qWB_fixed_Asm_16:
5993 case ARM::VLD3qWB_fixed_Asm_32: {
5994 MCInst TmpInst;
5995 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005996 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00005997 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5998 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5999 Spacing));
6000 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6001 Spacing * 2));
6002 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6003 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6004 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6005 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6006 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6007 TmpInst.addOperand(Inst.getOperand(4));
6008 Inst = TmpInst;
6009 return true;
6010 }
6011
6012 case ARM::VLD3dWB_register_Asm_8:
6013 case ARM::VLD3dWB_register_Asm_16:
6014 case ARM::VLD3dWB_register_Asm_32:
6015 case ARM::VLD3qWB_register_Asm_8:
6016 case ARM::VLD3qWB_register_Asm_16:
6017 case ARM::VLD3qWB_register_Asm_32: {
6018 MCInst TmpInst;
6019 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006020 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006021 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6022 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6023 Spacing));
6024 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6025 Spacing * 2));
6026 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6027 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6028 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6029 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6030 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6031 TmpInst.addOperand(Inst.getOperand(5));
6032 Inst = TmpInst;
6033 return true;
6034 }
6035
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006036 // VLD4 multiple 3-element structure instructions.
6037 case ARM::VLD4dAsm_8:
6038 case ARM::VLD4dAsm_16:
6039 case ARM::VLD4dAsm_32:
6040 case ARM::VLD4qAsm_8:
6041 case ARM::VLD4qAsm_16:
6042 case ARM::VLD4qAsm_32: {
6043 MCInst TmpInst;
6044 unsigned Spacing;
6045 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6046 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6047 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6048 Spacing));
6049 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6050 Spacing * 2));
6051 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6052 Spacing * 3));
6053 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6054 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6055 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6056 TmpInst.addOperand(Inst.getOperand(4));
6057 Inst = TmpInst;
6058 return true;
6059 }
6060
6061 case ARM::VLD4dWB_fixed_Asm_8:
6062 case ARM::VLD4dWB_fixed_Asm_16:
6063 case ARM::VLD4dWB_fixed_Asm_32:
6064 case ARM::VLD4qWB_fixed_Asm_8:
6065 case ARM::VLD4qWB_fixed_Asm_16:
6066 case ARM::VLD4qWB_fixed_Asm_32: {
6067 MCInst TmpInst;
6068 unsigned Spacing;
6069 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6070 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6071 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6072 Spacing));
6073 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6074 Spacing * 2));
6075 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6076 Spacing * 3));
6077 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6078 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6079 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6080 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6081 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6082 TmpInst.addOperand(Inst.getOperand(4));
6083 Inst = TmpInst;
6084 return true;
6085 }
6086
6087 case ARM::VLD4dWB_register_Asm_8:
6088 case ARM::VLD4dWB_register_Asm_16:
6089 case ARM::VLD4dWB_register_Asm_32:
6090 case ARM::VLD4qWB_register_Asm_8:
6091 case ARM::VLD4qWB_register_Asm_16:
6092 case ARM::VLD4qWB_register_Asm_32: {
6093 MCInst TmpInst;
6094 unsigned Spacing;
6095 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6096 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6097 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6098 Spacing));
6099 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6100 Spacing * 2));
6101 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6102 Spacing * 3));
6103 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6104 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6105 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6106 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6107 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6108 TmpInst.addOperand(Inst.getOperand(5));
6109 Inst = TmpInst;
6110 return true;
6111 }
6112
Jim Grosbachd7433e22012-01-23 23:45:44 +00006113 // VST3 multiple 3-element structure instructions.
6114 case ARM::VST3dAsm_8:
6115 case ARM::VST3dAsm_16:
6116 case ARM::VST3dAsm_32:
6117 case ARM::VST3qAsm_8:
6118 case ARM::VST3qAsm_16:
6119 case ARM::VST3qAsm_32: {
6120 MCInst TmpInst;
6121 unsigned Spacing;
6122 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6123 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6124 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6125 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6126 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6127 Spacing));
6128 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6129 Spacing * 2));
6130 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6131 TmpInst.addOperand(Inst.getOperand(4));
6132 Inst = TmpInst;
6133 return true;
6134 }
6135
6136 case ARM::VST3dWB_fixed_Asm_8:
6137 case ARM::VST3dWB_fixed_Asm_16:
6138 case ARM::VST3dWB_fixed_Asm_32:
6139 case ARM::VST3qWB_fixed_Asm_8:
6140 case ARM::VST3qWB_fixed_Asm_16:
6141 case ARM::VST3qWB_fixed_Asm_32: {
6142 MCInst TmpInst;
6143 unsigned Spacing;
6144 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6145 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6146 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6147 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6148 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6149 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6150 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6151 Spacing));
6152 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6153 Spacing * 2));
6154 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6155 TmpInst.addOperand(Inst.getOperand(4));
6156 Inst = TmpInst;
6157 return true;
6158 }
6159
6160 case ARM::VST3dWB_register_Asm_8:
6161 case ARM::VST3dWB_register_Asm_16:
6162 case ARM::VST3dWB_register_Asm_32:
6163 case ARM::VST3qWB_register_Asm_8:
6164 case ARM::VST3qWB_register_Asm_16:
6165 case ARM::VST3qWB_register_Asm_32: {
6166 MCInst TmpInst;
6167 unsigned Spacing;
6168 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6169 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6170 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6171 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6172 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6173 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6174 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6175 Spacing));
6176 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6177 Spacing * 2));
6178 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6179 TmpInst.addOperand(Inst.getOperand(5));
6180 Inst = TmpInst;
6181 return true;
6182 }
6183
Jim Grosbach539aab72012-01-24 00:58:13 +00006184 // VST4 multiple 3-element structure instructions.
6185 case ARM::VST4dAsm_8:
6186 case ARM::VST4dAsm_16:
6187 case ARM::VST4dAsm_32:
6188 case ARM::VST4qAsm_8:
6189 case ARM::VST4qAsm_16:
6190 case ARM::VST4qAsm_32: {
6191 MCInst TmpInst;
6192 unsigned Spacing;
6193 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6194 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6195 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6196 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6197 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6198 Spacing));
6199 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6200 Spacing * 2));
6201 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6202 Spacing * 3));
6203 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6204 TmpInst.addOperand(Inst.getOperand(4));
6205 Inst = TmpInst;
6206 return true;
6207 }
6208
6209 case ARM::VST4dWB_fixed_Asm_8:
6210 case ARM::VST4dWB_fixed_Asm_16:
6211 case ARM::VST4dWB_fixed_Asm_32:
6212 case ARM::VST4qWB_fixed_Asm_8:
6213 case ARM::VST4qWB_fixed_Asm_16:
6214 case ARM::VST4qWB_fixed_Asm_32: {
6215 MCInst TmpInst;
6216 unsigned Spacing;
6217 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6218 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6219 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6220 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6221 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6222 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6223 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6224 Spacing));
6225 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6226 Spacing * 2));
6227 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6228 Spacing * 3));
6229 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6230 TmpInst.addOperand(Inst.getOperand(4));
6231 Inst = TmpInst;
6232 return true;
6233 }
6234
6235 case ARM::VST4dWB_register_Asm_8:
6236 case ARM::VST4dWB_register_Asm_16:
6237 case ARM::VST4dWB_register_Asm_32:
6238 case ARM::VST4qWB_register_Asm_8:
6239 case ARM::VST4qWB_register_Asm_16:
6240 case ARM::VST4qWB_register_Asm_32: {
6241 MCInst TmpInst;
6242 unsigned Spacing;
6243 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6244 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6245 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6246 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6247 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6248 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6249 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6250 Spacing));
6251 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6252 Spacing * 2));
6253 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6254 Spacing * 3));
6255 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6256 TmpInst.addOperand(Inst.getOperand(5));
6257 Inst = TmpInst;
6258 return true;
6259 }
6260
Jim Grosbach863d2af2011-12-13 22:45:11 +00006261 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006262 case ARM::t2MOVsr:
6263 case ARM::t2MOVSsr: {
6264 // Which instruction to expand to depends on the CCOut operand and
6265 // whether we're in an IT block if the register operands are low
6266 // registers.
6267 bool isNarrow = false;
6268 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6269 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6270 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6271 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6272 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6273 isNarrow = true;
6274 MCInst TmpInst;
6275 unsigned newOpc;
6276 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6277 default: llvm_unreachable("unexpected opcode!");
6278 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6279 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6280 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6281 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6282 }
6283 TmpInst.setOpcode(newOpc);
6284 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6285 if (isNarrow)
6286 TmpInst.addOperand(MCOperand::CreateReg(
6287 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6288 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6289 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6290 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6291 TmpInst.addOperand(Inst.getOperand(5));
6292 if (!isNarrow)
6293 TmpInst.addOperand(MCOperand::CreateReg(
6294 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6295 Inst = TmpInst;
6296 return true;
6297 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006298 case ARM::t2MOVsi:
6299 case ARM::t2MOVSsi: {
6300 // Which instruction to expand to depends on the CCOut operand and
6301 // whether we're in an IT block if the register operands are low
6302 // registers.
6303 bool isNarrow = false;
6304 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6305 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6306 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6307 isNarrow = true;
6308 MCInst TmpInst;
6309 unsigned newOpc;
6310 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6311 default: llvm_unreachable("unexpected opcode!");
6312 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6313 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6314 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6315 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006316 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006317 }
6318 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6319 if (Ammount == 32) Ammount = 0;
6320 TmpInst.setOpcode(newOpc);
6321 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6322 if (isNarrow)
6323 TmpInst.addOperand(MCOperand::CreateReg(
6324 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6325 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006326 if (newOpc != ARM::t2RRX)
6327 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006328 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6329 TmpInst.addOperand(Inst.getOperand(4));
6330 if (!isNarrow)
6331 TmpInst.addOperand(MCOperand::CreateReg(
6332 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6333 Inst = TmpInst;
6334 return true;
6335 }
6336 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006337 case ARM::ASRr:
6338 case ARM::LSRr:
6339 case ARM::LSLr:
6340 case ARM::RORr: {
6341 ARM_AM::ShiftOpc ShiftTy;
6342 switch(Inst.getOpcode()) {
6343 default: llvm_unreachable("unexpected opcode!");
6344 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6345 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6346 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6347 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6348 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006349 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6350 MCInst TmpInst;
6351 TmpInst.setOpcode(ARM::MOVsr);
6352 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6353 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6354 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6355 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6356 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6357 TmpInst.addOperand(Inst.getOperand(4));
6358 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6359 Inst = TmpInst;
6360 return true;
6361 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006362 case ARM::ASRi:
6363 case ARM::LSRi:
6364 case ARM::LSLi:
6365 case ARM::RORi: {
6366 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006367 switch(Inst.getOpcode()) {
6368 default: llvm_unreachable("unexpected opcode!");
6369 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6370 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6371 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6372 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6373 }
6374 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006375 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006376 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6377 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006378 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006379 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006380 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6381 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006382 if (Opc == ARM::MOVsi)
6383 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006384 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6385 TmpInst.addOperand(Inst.getOperand(4));
6386 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6387 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006388 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006389 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006390 case ARM::RRXi: {
6391 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6392 MCInst TmpInst;
6393 TmpInst.setOpcode(ARM::MOVsi);
6394 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6395 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6396 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6397 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6398 TmpInst.addOperand(Inst.getOperand(3));
6399 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6400 Inst = TmpInst;
6401 return true;
6402 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006403 case ARM::t2LDMIA_UPD: {
6404 // If this is a load of a single register, then we should use
6405 // a post-indexed LDR instruction instead, per the ARM ARM.
6406 if (Inst.getNumOperands() != 5)
6407 return false;
6408 MCInst TmpInst;
6409 TmpInst.setOpcode(ARM::t2LDR_POST);
6410 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6411 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6412 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6413 TmpInst.addOperand(MCOperand::CreateImm(4));
6414 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6415 TmpInst.addOperand(Inst.getOperand(3));
6416 Inst = TmpInst;
6417 return true;
6418 }
6419 case ARM::t2STMDB_UPD: {
6420 // If this is a store of a single register, then we should use
6421 // a pre-indexed STR instruction instead, per the ARM ARM.
6422 if (Inst.getNumOperands() != 5)
6423 return false;
6424 MCInst TmpInst;
6425 TmpInst.setOpcode(ARM::t2STR_PRE);
6426 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6427 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6428 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6429 TmpInst.addOperand(MCOperand::CreateImm(-4));
6430 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6431 TmpInst.addOperand(Inst.getOperand(3));
6432 Inst = TmpInst;
6433 return true;
6434 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006435 case ARM::LDMIA_UPD:
6436 // If this is a load of a single register via a 'pop', then we should use
6437 // a post-indexed LDR instruction instead, per the ARM ARM.
6438 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6439 Inst.getNumOperands() == 5) {
6440 MCInst TmpInst;
6441 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6442 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6443 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6444 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6445 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6446 TmpInst.addOperand(MCOperand::CreateImm(4));
6447 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6448 TmpInst.addOperand(Inst.getOperand(3));
6449 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006450 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006451 }
6452 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006453 case ARM::STMDB_UPD:
6454 // If this is a store of a single register via a 'push', then we should use
6455 // a pre-indexed STR instruction instead, per the ARM ARM.
6456 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6457 Inst.getNumOperands() == 5) {
6458 MCInst TmpInst;
6459 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6460 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6461 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6462 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6463 TmpInst.addOperand(MCOperand::CreateImm(-4));
6464 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6465 TmpInst.addOperand(Inst.getOperand(3));
6466 Inst = TmpInst;
6467 }
6468 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006469 case ARM::t2ADDri12:
6470 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6471 // mnemonic was used (not "addw"), encoding T3 is preferred.
6472 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6473 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6474 break;
6475 Inst.setOpcode(ARM::t2ADDri);
6476 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6477 break;
6478 case ARM::t2SUBri12:
6479 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6480 // mnemonic was used (not "subw"), encoding T3 is preferred.
6481 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6482 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6483 break;
6484 Inst.setOpcode(ARM::t2SUBri);
6485 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6486 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006487 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006488 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6489 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6490 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6491 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006492 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006493 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006494 return true;
6495 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006496 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006497 case ARM::tSUBi8:
6498 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6499 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6500 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6501 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00006502 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006503 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006504 return true;
6505 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006506 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00006507 case ARM::t2ADDrr: {
6508 // If the destination and first source operand are the same, and
6509 // there's no setting of the flags, use encoding T2 instead of T3.
6510 // Note that this is only for ADD, not SUB. This mirrors the system
6511 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
6512 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
6513 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00006514 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6515 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00006516 break;
6517 MCInst TmpInst;
6518 TmpInst.setOpcode(ARM::tADDhirr);
6519 TmpInst.addOperand(Inst.getOperand(0));
6520 TmpInst.addOperand(Inst.getOperand(0));
6521 TmpInst.addOperand(Inst.getOperand(2));
6522 TmpInst.addOperand(Inst.getOperand(3));
6523 TmpInst.addOperand(Inst.getOperand(4));
6524 Inst = TmpInst;
6525 return true;
6526 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006527 case ARM::tB:
6528 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006529 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006530 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006531 return true;
6532 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006533 break;
6534 case ARM::t2B:
6535 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006536 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006537 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006538 return true;
6539 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006540 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006541 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006542 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006543 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006544 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006545 return true;
6546 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006547 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006548 case ARM::tBcc:
6549 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006550 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006551 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006552 return true;
6553 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006554 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006555 case ARM::tLDMIA: {
6556 // If the register list contains any high registers, or if the writeback
6557 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6558 // instead if we're in Thumb2. Otherwise, this should have generated
6559 // an error in validateInstruction().
6560 unsigned Rn = Inst.getOperand(0).getReg();
6561 bool hasWritebackToken =
6562 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6563 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6564 bool listContainsBase;
6565 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6566 (!listContainsBase && !hasWritebackToken) ||
6567 (listContainsBase && hasWritebackToken)) {
6568 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6569 assert (isThumbTwo());
6570 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6571 // If we're switching to the updating version, we need to insert
6572 // the writeback tied operand.
6573 if (hasWritebackToken)
6574 Inst.insert(Inst.begin(),
6575 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006576 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006577 }
6578 break;
6579 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006580 case ARM::tSTMIA_UPD: {
6581 // If the register list contains any high registers, we need to use
6582 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6583 // should have generated an error in validateInstruction().
6584 unsigned Rn = Inst.getOperand(0).getReg();
6585 bool listContainsBase;
6586 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6587 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6588 assert (isThumbTwo());
6589 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006590 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006591 }
6592 break;
6593 }
Jim Grosbach54026372011-11-10 23:17:11 +00006594 case ARM::tPOP: {
6595 bool listContainsBase;
6596 // If the register list contains any high registers, we need to use
6597 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6598 // should have generated an error in validateInstruction().
6599 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006600 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006601 assert (isThumbTwo());
6602 Inst.setOpcode(ARM::t2LDMIA_UPD);
6603 // Add the base register and writeback operands.
6604 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6605 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006606 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006607 }
6608 case ARM::tPUSH: {
6609 bool listContainsBase;
6610 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006611 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006612 assert (isThumbTwo());
6613 Inst.setOpcode(ARM::t2STMDB_UPD);
6614 // Add the base register and writeback operands.
6615 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6616 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006617 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006618 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006619 case ARM::t2MOVi: {
6620 // If we can use the 16-bit encoding and the user didn't explicitly
6621 // request the 32-bit variant, transform it here.
6622 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6623 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006624 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6625 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6626 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006627 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6628 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6629 // The operands aren't in the same order for tMOVi8...
6630 MCInst TmpInst;
6631 TmpInst.setOpcode(ARM::tMOVi8);
6632 TmpInst.addOperand(Inst.getOperand(0));
6633 TmpInst.addOperand(Inst.getOperand(4));
6634 TmpInst.addOperand(Inst.getOperand(1));
6635 TmpInst.addOperand(Inst.getOperand(2));
6636 TmpInst.addOperand(Inst.getOperand(3));
6637 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006638 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006639 }
6640 break;
6641 }
6642 case ARM::t2MOVr: {
6643 // If we can use the 16-bit encoding and the user didn't explicitly
6644 // request the 32-bit variant, transform it here.
6645 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6646 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6647 Inst.getOperand(2).getImm() == ARMCC::AL &&
6648 Inst.getOperand(4).getReg() == ARM::CPSR &&
6649 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6650 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6651 // The operands aren't the same for tMOV[S]r... (no cc_out)
6652 MCInst TmpInst;
6653 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6654 TmpInst.addOperand(Inst.getOperand(0));
6655 TmpInst.addOperand(Inst.getOperand(1));
6656 TmpInst.addOperand(Inst.getOperand(2));
6657 TmpInst.addOperand(Inst.getOperand(3));
6658 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006659 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006660 }
6661 break;
6662 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006663 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006664 case ARM::t2SXTB:
6665 case ARM::t2UXTH:
6666 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006667 // If we can use the 16-bit encoding and the user didn't explicitly
6668 // request the 32-bit variant, transform it here.
6669 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6670 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6671 Inst.getOperand(2).getImm() == 0 &&
6672 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6673 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006674 unsigned NewOpc;
6675 switch (Inst.getOpcode()) {
6676 default: llvm_unreachable("Illegal opcode!");
6677 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6678 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6679 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6680 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6681 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006682 // The operands aren't the same for thumb1 (no rotate operand).
6683 MCInst TmpInst;
6684 TmpInst.setOpcode(NewOpc);
6685 TmpInst.addOperand(Inst.getOperand(0));
6686 TmpInst.addOperand(Inst.getOperand(1));
6687 TmpInst.addOperand(Inst.getOperand(3));
6688 TmpInst.addOperand(Inst.getOperand(4));
6689 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006690 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006691 }
6692 break;
6693 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006694 case ARM::MOVsi: {
6695 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6696 if (SOpc == ARM_AM::rrx) return false;
6697 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6698 // Shifting by zero is accepted as a vanilla 'MOVr'
6699 MCInst TmpInst;
6700 TmpInst.setOpcode(ARM::MOVr);
6701 TmpInst.addOperand(Inst.getOperand(0));
6702 TmpInst.addOperand(Inst.getOperand(1));
6703 TmpInst.addOperand(Inst.getOperand(3));
6704 TmpInst.addOperand(Inst.getOperand(4));
6705 TmpInst.addOperand(Inst.getOperand(5));
6706 Inst = TmpInst;
6707 return true;
6708 }
6709 return false;
6710 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006711 case ARM::ANDrsi:
6712 case ARM::ORRrsi:
6713 case ARM::EORrsi:
6714 case ARM::BICrsi:
6715 case ARM::SUBrsi:
6716 case ARM::ADDrsi: {
6717 unsigned newOpc;
6718 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6719 if (SOpc == ARM_AM::rrx) return false;
6720 switch (Inst.getOpcode()) {
Matt Beaumont-Gay19055cc2012-01-03 19:03:59 +00006721 default: assert(0 && "unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006722 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6723 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6724 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6725 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6726 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6727 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6728 }
6729 // If the shift is by zero, use the non-shifted instruction definition.
6730 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6731 MCInst TmpInst;
6732 TmpInst.setOpcode(newOpc);
6733 TmpInst.addOperand(Inst.getOperand(0));
6734 TmpInst.addOperand(Inst.getOperand(1));
6735 TmpInst.addOperand(Inst.getOperand(2));
6736 TmpInst.addOperand(Inst.getOperand(4));
6737 TmpInst.addOperand(Inst.getOperand(5));
6738 TmpInst.addOperand(Inst.getOperand(6));
6739 Inst = TmpInst;
6740 return true;
6741 }
6742 return false;
6743 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006744 case ARM::t2IT: {
6745 // The mask bits for all but the first condition are represented as
6746 // the low bit of the condition code value implies 't'. We currently
6747 // always have 1 implies 't', so XOR toggle the bits if the low bit
6748 // of the condition code is zero. The encoding also expects the low
6749 // bit of the condition to be encoded as bit 4 of the mask operand,
6750 // so mask that in if needed
6751 MCOperand &MO = Inst.getOperand(1);
6752 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006753 unsigned OrigMask = Mask;
6754 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006755 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006756 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6757 for (unsigned i = 3; i != TZ; --i)
6758 Mask ^= 1 << i;
6759 } else
6760 Mask |= 0x10;
6761 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006762
6763 // Set up the IT block state according to the IT instruction we just
6764 // matched.
6765 assert(!inITBlock() && "nested IT blocks?!");
6766 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6767 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6768 ITState.CurPosition = 0;
6769 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006770 break;
6771 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006772 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006773 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006774}
6775
Jim Grosbach47a0d522011-08-16 20:45:50 +00006776unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6777 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6778 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006779 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006780 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006781 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6782 assert(MCID.hasOptionalDef() &&
6783 "optionally flag setting instruction missing optional def operand");
6784 assert(MCID.NumOperands == Inst.getNumOperands() &&
6785 "operand count mismatch!");
6786 // Find the optional-def operand (cc_out).
6787 unsigned OpNo;
6788 for (OpNo = 0;
6789 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6790 ++OpNo)
6791 ;
6792 // If we're parsing Thumb1, reject it completely.
6793 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6794 return Match_MnemonicFail;
6795 // If we're parsing Thumb2, which form is legal depends on whether we're
6796 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006797 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6798 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006799 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006800 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6801 inITBlock())
6802 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006803 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006804 // Some high-register supporting Thumb1 encodings only allow both registers
6805 // to be from r0-r7 when in Thumb2.
6806 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6807 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6808 isARMLowRegister(Inst.getOperand(2).getReg()))
6809 return Match_RequiresThumb2;
6810 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006811 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006812 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6813 isARMLowRegister(Inst.getOperand(1).getReg()))
6814 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006815 return Match_Success;
6816}
6817
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006818bool ARMAsmParser::
6819MatchAndEmitInstruction(SMLoc IDLoc,
6820 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6821 MCStreamer &Out) {
6822 MCInst Inst;
6823 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006824 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006825 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006826 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006827 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006828 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006829 // Context sensitive operand constraints aren't handled by the matcher,
6830 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006831 if (validateInstruction(Inst, Operands)) {
6832 // Still progress the IT block, otherwise one wrong condition causes
6833 // nasty cascading errors.
6834 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006835 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006836 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006837
Jim Grosbachf8fce712011-08-11 17:35:48 +00006838 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006839 // encoding is selected. Loop on it while changes happen so the
6840 // individual transformations can chain off each other. E.g.,
6841 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6842 while (processInstruction(Inst, Operands))
6843 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006844
Jim Grosbacha1109882011-09-02 23:22:08 +00006845 // Only move forward at the very end so that everything in validate
6846 // and process gets a consistent answer about whether we're in an IT
6847 // block.
6848 forwardITPosition();
6849
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006850 Out.EmitInstruction(Inst);
6851 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006852 case Match_MissingFeature:
6853 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6854 return true;
6855 case Match_InvalidOperand: {
6856 SMLoc ErrorLoc = IDLoc;
6857 if (ErrorInfo != ~0U) {
6858 if (ErrorInfo >= Operands.size())
6859 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006860
Chris Lattnere73d4f82010-10-28 21:41:58 +00006861 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6862 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6863 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006864
Chris Lattnere73d4f82010-10-28 21:41:58 +00006865 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006866 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006867 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006868 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006869 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006870 // The converter function will have already emited a diagnostic.
6871 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006872 case Match_RequiresNotITBlock:
6873 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006874 case Match_RequiresITBlock:
6875 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006876 case Match_RequiresV6:
6877 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6878 case Match_RequiresThumb2:
6879 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006880 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006881
Eric Christopherc223e2b2010-10-29 09:26:59 +00006882 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006883}
6884
Jim Grosbach1355cf12011-07-26 17:10:22 +00006885/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006886bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6887 StringRef IDVal = DirectiveID.getIdentifier();
6888 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006889 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006890 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006891 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006892 else if (IDVal == ".arm")
6893 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006894 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006895 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006896 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006897 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006898 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006899 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006900 else if (IDVal == ".unreq")
6901 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006902 else if (IDVal == ".arch")
6903 return parseDirectiveArch(DirectiveID.getLoc());
6904 else if (IDVal == ".eabi_attribute")
6905 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006906 return true;
6907}
6908
Jim Grosbach1355cf12011-07-26 17:10:22 +00006909/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006910/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006911bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006912 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6913 for (;;) {
6914 const MCExpr *Value;
6915 if (getParser().ParseExpression(Value))
6916 return true;
6917
Chris Lattneraaec2052010-01-19 19:46:13 +00006918 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006919
6920 if (getLexer().is(AsmToken::EndOfStatement))
6921 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006922
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006923 // FIXME: Improve diagnostic.
6924 if (getLexer().isNot(AsmToken::Comma))
6925 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006926 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006927 }
6928 }
6929
Sean Callananb9a25b72010-01-19 20:27:46 +00006930 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006931 return false;
6932}
6933
Jim Grosbach1355cf12011-07-26 17:10:22 +00006934/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006935/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006936bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006937 if (getLexer().isNot(AsmToken::EndOfStatement))
6938 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006939 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006940
Jim Grosbach9a70df92011-12-07 18:04:19 +00006941 if (!isThumb())
6942 SwitchMode();
6943 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6944 return false;
6945}
6946
6947/// parseDirectiveARM
6948/// ::= .arm
6949bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6950 if (getLexer().isNot(AsmToken::EndOfStatement))
6951 return Error(L, "unexpected token in directive");
6952 Parser.Lex();
6953
6954 if (isThumb())
6955 SwitchMode();
6956 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006957 return false;
6958}
6959
Jim Grosbach1355cf12011-07-26 17:10:22 +00006960/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006961/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006962bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006963 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6964 bool isMachO = MAI.hasSubsectionsViaSymbols();
6965 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006966 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006967
Jim Grosbachde4d8392011-12-21 22:30:16 +00006968 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006969 // ELF doesn't
6970 if (isMachO) {
6971 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006972 if (Tok.isNot(AsmToken::EndOfStatement)) {
6973 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6974 return Error(L, "unexpected token in .thumb_func directive");
6975 Name = Tok.getIdentifier();
6976 Parser.Lex(); // Consume the identifier token.
6977 needFuncName = false;
6978 }
Rafael Espindola64695402011-05-16 16:17:21 +00006979 }
6980
Jim Grosbachde4d8392011-12-21 22:30:16 +00006981 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006982 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006983
6984 // Eat the end of statement and any blank lines that follow.
6985 while (getLexer().is(AsmToken::EndOfStatement))
6986 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006987
Rafael Espindola64695402011-05-16 16:17:21 +00006988 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006989 // We really should be checking the next symbol definition even if there's
6990 // stuff in between.
6991 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006992 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006993 }
6994
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006995 // Mark symbol as a thumb symbol.
6996 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6997 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006998 return false;
6999}
7000
Jim Grosbach1355cf12011-07-26 17:10:22 +00007001/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007002/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007003bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007004 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007005 if (Tok.isNot(AsmToken::Identifier))
7006 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007007 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007008 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007009 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007010 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007011 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007012 else
7013 return Error(L, "unrecognized syntax mode in .syntax directive");
7014
7015 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007016 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007017 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007018
7019 // TODO tell the MC streamer the mode
7020 // getParser().getStreamer().Emit???();
7021 return false;
7022}
7023
Jim Grosbach1355cf12011-07-26 17:10:22 +00007024/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007025/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007026bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007027 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007028 if (Tok.isNot(AsmToken::Integer))
7029 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007030 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007031 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007032 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007033 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007034 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007035 else
7036 return Error(L, "invalid operand to .code directive");
7037
7038 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007039 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007040 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007041
Evan Cheng32869202011-07-08 22:36:29 +00007042 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007043 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007044 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007045 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007046 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007047 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007048 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007049 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007050 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007051
Kevin Enderby515d5092009-10-15 20:48:48 +00007052 return false;
7053}
7054
Jim Grosbacha39cda72011-12-14 02:16:11 +00007055/// parseDirectiveReq
7056/// ::= name .req registername
7057bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7058 Parser.Lex(); // Eat the '.req' token.
7059 unsigned Reg;
7060 SMLoc SRegLoc, ERegLoc;
7061 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7062 Parser.EatToEndOfStatement();
7063 return Error(SRegLoc, "register name expected");
7064 }
7065
7066 // Shouldn't be anything else.
7067 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7068 Parser.EatToEndOfStatement();
7069 return Error(Parser.getTok().getLoc(),
7070 "unexpected input in .req directive.");
7071 }
7072
7073 Parser.Lex(); // Consume the EndOfStatement
7074
7075 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7076 return Error(SRegLoc, "redefinition of '" + Name +
7077 "' does not match original.");
7078
7079 return false;
7080}
7081
7082/// parseDirectiveUneq
7083/// ::= .unreq registername
7084bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7085 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7086 Parser.EatToEndOfStatement();
7087 return Error(L, "unexpected input in .unreq directive.");
7088 }
7089 RegisterReqs.erase(Parser.getTok().getIdentifier());
7090 Parser.Lex(); // Eat the identifier.
7091 return false;
7092}
7093
Jason W Kimd7c9e082011-12-20 17:38:12 +00007094/// parseDirectiveArch
7095/// ::= .arch token
7096bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7097 return true;
7098}
7099
7100/// parseDirectiveEabiAttr
7101/// ::= .eabi_attribute int, int
7102bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7103 return true;
7104}
7105
Sean Callanan90b70972010-04-07 20:29:34 +00007106extern "C" void LLVMInitializeARMAsmLexer();
7107
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007108/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007109extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007110 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7111 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007112 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007113}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007114
Chris Lattner0692ee62010-09-06 19:11:01 +00007115#define GET_REGISTER_MATCHER
7116#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007117#include "ARMGenAsmMatcher.inc"