blob: 705825478daea58651b1238180d1d90a6f48476c [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan76264762010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbach862019c2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendling8155e5b2010-11-06 22:19:43 +0000344 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000351
Jim Grosbach9d390362011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000400
Bill Wendling146018f2010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan76264762010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000425 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan76264762010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000479
Sean Callanan76264762010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Daniel Dunbar8462b302010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503 }
504
Bill Wendling5fa22a12010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000509 }
510
Kevin Enderbycfe07242009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000512 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbach9d390362011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbach460a9052011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000550 bool isFBits16() 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 >= 0 && Value <= 16;
556 }
557 bool isFBits32() const {
558 if (!isImm()) return false;
559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return Value >= 1 && Value <= 32;
563 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000564 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +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 >= -1020 && Value <= 1020;
570 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000571 bool isImm0_1020s4() 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 <= 1020;
577 }
578 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
584 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000585 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 256;
591 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000592 bool isImm0_1() 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 < 2;
598 }
599 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 4;
605 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000606 bool isImm0_7() 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 < 8;
612 }
613 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 16;
619 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000620 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 32;
626 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000627 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value >= 0 && Value < 64;
633 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000634 bool isImm8() 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 == 8;
640 }
641 bool isImm16() 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 == 16;
647 }
648 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value == 32;
654 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000655 bool isShrImm8() 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 <= 8;
661 }
662 bool isShrImm16() 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 <= 16;
668 }
669 bool isShrImm32() 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 <= 32;
675 }
676 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value <= 64;
682 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000683 bool isImm1_7() 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 < 8;
689 }
690 bool isImm1_15() 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 < 16;
696 }
697 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 32;
703 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000704 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value > 0 && Value < 17;
710 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000711 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +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 Grosbachee10ff82011-11-10 19:18:01 +0000718 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 if (!CE) return false;
722 int64_t Value = CE->getValue();
723 return Value >= 0 && Value < 33;
724 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000725 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000726 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 if (!CE) return false;
729 int64_t Value = CE->getValue();
730 return Value >= 0 && Value < 65536;
731 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000732 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000733 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000734 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
735 // If it's not a constant expression, it'll generate a fixup and be
736 // handled later.
737 if (!CE) return true;
738 int64_t Value = CE->getValue();
739 return Value >= 0 && Value < 65536;
740 }
Jim Grosbached838482011-07-26 16:24:27 +0000741 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24: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 <= 0xffffff;
747 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000748 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value > 0 && Value < 33;
754 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000755 bool isPKHLSLImm() 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 }
762 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return Value > 0 && Value <= 32;
768 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000769 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +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 Grosbache70ec842011-10-28 22:50:54 +0000776 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +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 Grosbach3bc8a3d2011-12-08 00:31:07 +0000783 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getSOImmVal(-Value) != -1;
789 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000790 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +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 Grosbach89a63372011-10-28 22:36:30 +0000797 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +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 Grosbach3bc8a3d2011-12-08 00:31:07 +0000804 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000805 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807 if (!CE) return false;
808 int64_t Value = CE->getValue();
809 return ARM_AM::getT2SOImmVal(-Value) != -1;
810 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000811 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000812 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000813 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
814 if (!CE) return false;
815 int64_t Value = CE->getValue();
816 return Value == 1 || Value == 0;
817 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000818 bool isReg() const { return Kind == k_Register; }
819 bool isRegList() const { return Kind == k_RegisterList; }
820 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
821 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
822 bool isToken() const { return Kind == k_Token; }
823 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
824 bool isMemory() const { return Kind == k_Memory; }
825 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
826 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
827 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
828 bool isRotImm() const { return Kind == k_RotateImmediate; }
829 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
830 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000831 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000832 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000833 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000835 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000836 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000837 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000838 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
839 (alignOK || Memory.Alignment == 0);
840 }
841 bool isAlignedMemory() const {
842 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000843 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000844 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000846 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000848 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000849 if (!Memory.OffsetImm) return true;
850 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000851 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000852 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000853 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000854 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000855 // Immediate offset in range [-4095, 4095].
856 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
857 if (!CE) return false;
858 int64_t Val = CE->getValue();
859 return Val > -4096 && Val < 4096;
860 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000861 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000862 // If we have an immediate that's not a constant, treat it as a label
863 // reference needing a fixup. If it is a constant, it's something else
864 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000865 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000866 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000867 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000868 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000869 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000870 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000872 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000873 if (!Memory.OffsetImm) return true;
874 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000875 return Val > -256 && Val < 256;
876 }
877 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000878 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000879 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000880 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000881 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
882 // Immediate offset in range [-255, 255].
883 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
884 if (!CE) return false;
885 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000886 // Special case, #-0 is INT32_MIN.
887 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000888 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000889 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000890 // If we have an immediate that's not a constant, treat it as a label
891 // reference needing a fixup. If it is a constant, it's something else
892 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000893 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000894 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000895 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000896 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000897 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000898 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000899 if (!Memory.OffsetImm) return true;
900 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000901 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000902 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000903 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000904 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000905 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000906 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000907 return false;
908 return true;
909 }
910 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000911 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000912 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
913 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000914 return false;
915 return true;
916 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000917 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000918 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000919 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000920 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000921 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000922 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000923 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
924 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000925 return false;
926 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000927 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000928 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000929 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000930 return false;
931 return true;
932 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000933 bool isMemThumbRR() const {
934 // Thumb reg+reg addressing is simple. Just two registers, a base and
935 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000936 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000937 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000938 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 return isARMLowRegister(Memory.BaseRegNum) &&
940 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000941 }
942 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000944 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000945 return false;
946 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!Memory.OffsetImm) return true;
948 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000949 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
950 }
Jim Grosbach38466302011-08-19 18:55:51 +0000951 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000953 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000954 return false;
955 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000956 if (!Memory.OffsetImm) return true;
957 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000958 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
959 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000960 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000961 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000962 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000963 return false;
964 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000965 if (!Memory.OffsetImm) return true;
966 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000967 return Val >= 0 && Val <= 31;
968 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000969 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000970 if (!isMemory() || Memory.OffsetRegNum != 0 ||
971 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000972 return false;
973 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000974 if (!Memory.OffsetImm) return true;
975 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000976 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000977 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000978 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000979 // If we have an immediate that's not a constant, treat it as a label
980 // reference needing a fixup. If it is a constant, it's something else
981 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000982 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000983 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000984 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000985 return false;
986 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000987 if (!Memory.OffsetImm) return true;
988 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000989 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
990 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000991 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000992 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000993 return false;
994 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000995 if (!Memory.OffsetImm) return true;
996 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000997 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
998 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000999 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001000 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001001 return false;
1002 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!Memory.OffsetImm) return true;
1004 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001005 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001006 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001007 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001008 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001009 return false;
1010 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001011 if (!Memory.OffsetImm) return true;
1012 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001013 return Val >= 0 && Val < 256;
1014 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001015 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001016 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001017 return false;
1018 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001019 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001020 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001021 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001022 }
1023 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001024 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001025 return false;
1026 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001027 if (!Memory.OffsetImm) return true;
1028 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001029 return (Val >= 0 && Val < 4096);
1030 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001031 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001032 // If we have an immediate that's not a constant, treat it as a label
1033 // reference needing a fixup. If it is a constant, it's something else
1034 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001035 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001036 return true;
1037
Jim Grosbach57dcb852011-10-11 17:29:55 +00001038 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001039 return false;
1040 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001041 if (!Memory.OffsetImm) return true;
1042 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001043 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001044 }
1045 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001046 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001047 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1048 if (!CE) return false;
1049 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001050 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001051 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001052 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001053 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001054 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1055 if (!CE) return false;
1056 int64_t Val = CE->getValue();
1057 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1058 (Val == INT32_MIN);
1059 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001060
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001061 bool isMSRMask() const { return Kind == k_MSRMask; }
1062 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001063
Jim Grosbach0e387b22011-10-17 22:26:03 +00001064 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001065 bool isSingleSpacedVectorList() const {
1066 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1067 }
1068 bool isDoubleSpacedVectorList() const {
1069 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1070 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001071 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001072 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001073 return VectorList.Count == 1;
1074 }
1075
Jim Grosbach280dfad2011-10-21 18:54:25 +00001076 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001077 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001078 return VectorList.Count == 2;
1079 }
1080
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001081 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001082 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001083 return VectorList.Count == 3;
1084 }
1085
Jim Grosbachb6310312011-10-21 20:35:01 +00001086 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001087 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001088 return VectorList.Count == 4;
1089 }
1090
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001091 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001092 if (!isDoubleSpacedVectorList()) return false;
1093 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001094 }
1095
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001096 bool isSingleSpacedVectorAllLanes() const {
1097 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1098 }
1099 bool isDoubleSpacedVectorAllLanes() const {
1100 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1101 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001102 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001103 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001104 return VectorList.Count == 1;
1105 }
1106
Jim Grosbach13af2222011-11-30 18:21:25 +00001107 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001108 if (!isSingleSpacedVectorAllLanes()) return false;
1109 return VectorList.Count == 2;
1110 }
1111
1112 bool isVecListTwoQAllLanes() const {
1113 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001114 return VectorList.Count == 2;
1115 }
1116
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001117 bool isSingleSpacedVectorIndexed() const {
1118 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1119 }
1120 bool isDoubleSpacedVectorIndexed() const {
1121 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1122 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001123 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001124 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001125 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1126 }
1127
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001128 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001129 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001130 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1131 }
1132
1133 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001134 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001135 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1136 }
1137
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001138 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001139 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001140 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1141 }
1142
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001143 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001144 if (!isSingleSpacedVectorIndexed()) return false;
1145 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1146 }
1147
1148 bool isVecListTwoQWordIndexed() const {
1149 if (!isDoubleSpacedVectorIndexed()) return false;
1150 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1151 }
1152
1153 bool isVecListTwoQHWordIndexed() const {
1154 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001155 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1156 }
1157
1158 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001159 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001160 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1161 }
1162
Jim Grosbach460a9052011-10-07 23:56:00 +00001163 bool isVectorIndex8() const {
1164 if (Kind != k_VectorIndex) return false;
1165 return VectorIndex.Val < 8;
1166 }
1167 bool isVectorIndex16() const {
1168 if (Kind != k_VectorIndex) return false;
1169 return VectorIndex.Val < 4;
1170 }
1171 bool isVectorIndex32() const {
1172 if (Kind != k_VectorIndex) return false;
1173 return VectorIndex.Val < 2;
1174 }
1175
Jim Grosbach0e387b22011-10-17 22:26:03 +00001176 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001177 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001178 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1179 // Must be a constant.
1180 if (!CE) return false;
1181 int64_t Value = CE->getValue();
1182 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1183 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001184 return Value >= 0 && Value < 256;
1185 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001186
Jim Grosbachea461102011-10-17 23:09:09 +00001187 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001188 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1190 // Must be a constant.
1191 if (!CE) return false;
1192 int64_t Value = CE->getValue();
1193 // i16 value in the range [0,255] or [0x0100, 0xff00]
1194 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1195 }
1196
Jim Grosbach6248a542011-10-18 00:22:00 +00001197 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001198 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001199 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1200 // Must be a constant.
1201 if (!CE) return false;
1202 int64_t Value = CE->getValue();
1203 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1204 return (Value >= 0 && Value < 256) ||
1205 (Value >= 0x0100 && Value <= 0xff00) ||
1206 (Value >= 0x010000 && Value <= 0xff0000) ||
1207 (Value >= 0x01000000 && Value <= 0xff000000);
1208 }
1209
1210 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001211 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1213 // Must be a constant.
1214 if (!CE) return false;
1215 int64_t Value = CE->getValue();
1216 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1217 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1218 return (Value >= 0 && Value < 256) ||
1219 (Value >= 0x0100 && Value <= 0xff00) ||
1220 (Value >= 0x010000 && Value <= 0xff0000) ||
1221 (Value >= 0x01000000 && Value <= 0xff000000) ||
1222 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1223 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1224 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001225 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001226 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001227 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1228 // Must be a constant.
1229 if (!CE) return false;
1230 int64_t Value = ~CE->getValue();
1231 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1232 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1233 return (Value >= 0 && Value < 256) ||
1234 (Value >= 0x0100 && Value <= 0xff00) ||
1235 (Value >= 0x010000 && Value <= 0xff0000) ||
1236 (Value >= 0x01000000 && Value <= 0xff000000) ||
1237 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1238 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1239 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001240
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001241 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001242 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001243 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1244 // Must be a constant.
1245 if (!CE) return false;
1246 uint64_t Value = CE->getValue();
1247 // i64 value with each byte being either 0 or 0xff.
1248 for (unsigned i = 0; i < 8; ++i)
1249 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1250 return true;
1251 }
1252
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001253 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001254 // Add as immediates when possible. Null MCExpr = 0.
1255 if (Expr == 0)
1256 Inst.addOperand(MCOperand::CreateImm(0));
1257 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001258 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1259 else
1260 Inst.addOperand(MCOperand::CreateExpr(Expr));
1261 }
1262
Daniel Dunbar8462b302010-08-11 06:36:53 +00001263 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001264 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001265 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001266 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1267 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001268 }
1269
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001270 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1271 assert(N == 1 && "Invalid number of operands!");
1272 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1273 }
1274
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001275 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1276 assert(N == 1 && "Invalid number of operands!");
1277 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1278 }
1279
1280 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 1 && "Invalid number of operands!");
1282 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1283 }
1284
Jim Grosbach89df9962011-08-26 21:43:41 +00001285 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
1287 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1288 }
1289
1290 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1293 }
1294
Jim Grosbachd67641b2010-12-06 18:21:12 +00001295 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
1297 Inst.addOperand(MCOperand::CreateReg(getReg()));
1298 }
1299
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001300 void addRegOperands(MCInst &Inst, unsigned N) const {
1301 assert(N == 1 && "Invalid number of operands!");
1302 Inst.addOperand(MCOperand::CreateReg(getReg()));
1303 }
1304
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001305 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001306 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001307 assert(isRegShiftedReg() &&
1308 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001309 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1310 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001311 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001312 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001313 }
1314
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001315 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001316 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001317 assert(isRegShiftedImm() &&
1318 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001319 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001320 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001321 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001322 }
1323
Jim Grosbach580f4a92011-07-25 22:20:28 +00001324 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001325 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001326 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1327 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001328 }
1329
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001330 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001331 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001332 const SmallVectorImpl<unsigned> &RegList = getRegList();
1333 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001334 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1335 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001336 }
1337
Bill Wendling0f630752010-11-17 04:32:08 +00001338 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1339 addRegListOperands(Inst, N);
1340 }
1341
1342 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1343 addRegListOperands(Inst, N);
1344 }
1345
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001346 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
1348 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1349 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1350 }
1351
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001352 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
1354 // Munge the lsb/width into a bitfield mask.
1355 unsigned lsb = Bitfield.LSB;
1356 unsigned width = Bitfield.Width;
1357 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1358 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1359 (32 - (lsb + width)));
1360 Inst.addOperand(MCOperand::CreateImm(Mask));
1361 }
1362
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001363 void addImmOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 addExpr(Inst, getImm());
1366 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001367
Jim Grosbach4050bc42011-12-22 22:19:05 +00001368 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1371 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1372 }
1373
1374 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1375 assert(N == 1 && "Invalid number of operands!");
1376 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1377 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1378 }
1379
Jim Grosbach9d390362011-10-03 23:38:36 +00001380 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
1382 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1383 }
1384
Jim Grosbacha77295d2011-09-08 22:07:06 +00001385 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 // FIXME: We really want to scale the value here, but the LDRD/STRD
1388 // instruction don't encode operands that way yet.
1389 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1390 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1391 }
1392
Jim Grosbach72f39f82011-08-24 21:22:15 +00001393 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 // The immediate is scaled by four in the encoding and is stored
1396 // in the MCInst as such. Lop off the low two bits here.
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1399 }
1400
1401 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 // The immediate is scaled by four in the encoding and is stored
1404 // in the MCInst as such. Lop off the low two bits here.
1405 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1406 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1407 }
1408
Jim Grosbachf4943352011-07-25 23:09:14 +00001409 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 // The constant encodes as the immediate-1, and we store in the instruction
1412 // the bits as encoded, so subtract off one here.
1413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1414 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1415 }
1416
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001417 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 // The constant encodes as the immediate-1, and we store in the instruction
1420 // the bits as encoded, so subtract off one here.
1421 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1422 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1423 }
1424
Jim Grosbach70939ee2011-08-17 21:51:27 +00001425 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 // The constant encodes as the immediate, except for 32, which encodes as
1428 // zero.
1429 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1430 unsigned Imm = CE->getValue();
1431 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1432 }
1433
Jim Grosbachf6c05252011-07-21 17:23:04 +00001434 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1437 // the instruction as well.
1438 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1439 int Val = CE->getValue();
1440 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1441 }
1442
Jim Grosbach89a63372011-10-28 22:36:30 +00001443 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
1445 // The operand is actually a t2_so_imm, but we have its bitwise
1446 // negation in the assembly source, so twiddle it here.
1447 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1448 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1449 }
1450
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001451 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 // The operand is actually a t2_so_imm, but we have its
1454 // negation in the assembly source, so twiddle it here.
1455 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1456 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1457 }
1458
Jim Grosbache70ec842011-10-28 22:50:54 +00001459 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
1461 // The operand is actually a so_imm, but we have its bitwise
1462 // negation in the assembly source, so twiddle it here.
1463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1464 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1465 }
1466
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001467 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 // The operand is actually a so_imm, but we have its
1470 // negation in the assembly source, so twiddle it here.
1471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1472 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1473 }
1474
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001475 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1478 }
1479
Jim Grosbach7ce05792011-08-03 23:50:40 +00001480 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001482 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001483 }
1484
Jim Grosbach57dcb852011-10-11 17:29:55 +00001485 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 2 && "Invalid number of operands!");
1487 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1488 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1489 }
1490
Jim Grosbach7ce05792011-08-03 23:50:40 +00001491 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1492 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001493 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1494 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001495 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1496 // Special case for #-0
1497 if (Val == INT32_MIN) Val = 0;
1498 if (Val < 0) Val = -Val;
1499 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1500 } else {
1501 // For register offset, we encode the shift type and negation flag
1502 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001503 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1504 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001505 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001506 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1507 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001508 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001509 }
1510
Jim Grosbach039c2e12011-08-04 23:01:30 +00001511 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 2 && "Invalid number of operands!");
1513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1514 assert(CE && "non-constant AM2OffsetImm operand!");
1515 int32_t Val = CE->getValue();
1516 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1517 // Special case for #-0
1518 if (Val == INT32_MIN) Val = 0;
1519 if (Val < 0) Val = -Val;
1520 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1521 Inst.addOperand(MCOperand::CreateReg(0));
1522 Inst.addOperand(MCOperand::CreateImm(Val));
1523 }
1524
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001525 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001527 // If we have an immediate that's not a constant, treat it as a label
1528 // reference needing a fixup. If it is a constant, it's something else
1529 // and we reject it.
1530 if (isImm()) {
1531 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1532 Inst.addOperand(MCOperand::CreateReg(0));
1533 Inst.addOperand(MCOperand::CreateImm(0));
1534 return;
1535 }
1536
Jim Grosbache53c87b2011-10-11 15:59:20 +00001537 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1538 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001539 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1540 // Special case for #-0
1541 if (Val == INT32_MIN) Val = 0;
1542 if (Val < 0) Val = -Val;
1543 Val = ARM_AM::getAM3Opc(AddSub, Val);
1544 } else {
1545 // For register offset, we encode the shift type and negation flag
1546 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001547 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001548 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001549 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1550 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001551 Inst.addOperand(MCOperand::CreateImm(Val));
1552 }
1553
1554 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001556 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001557 int32_t Val =
1558 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1559 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1560 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001561 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001562 }
1563
1564 // Constant offset.
1565 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1566 int32_t Val = CE->getValue();
1567 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1568 // Special case for #-0
1569 if (Val == INT32_MIN) Val = 0;
1570 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001571 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001572 Inst.addOperand(MCOperand::CreateReg(0));
1573 Inst.addOperand(MCOperand::CreateImm(Val));
1574 }
1575
Jim Grosbach7ce05792011-08-03 23:50:40 +00001576 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1577 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001578 // If we have an immediate that's not a constant, treat it as a label
1579 // reference needing a fixup. If it is a constant, it's something else
1580 // and we reject it.
1581 if (isImm()) {
1582 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1583 Inst.addOperand(MCOperand::CreateImm(0));
1584 return;
1585 }
1586
Jim Grosbach7ce05792011-08-03 23:50:40 +00001587 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001588 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001589 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1590 // Special case for #-0
1591 if (Val == INT32_MIN) Val = 0;
1592 if (Val < 0) Val = -Val;
1593 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001594 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001595 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001596 }
1597
Jim Grosbacha77295d2011-09-08 22:07:06 +00001598 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001600 // If we have an immediate that's not a constant, treat it as a label
1601 // reference needing a fixup. If it is a constant, it's something else
1602 // and we reject it.
1603 if (isImm()) {
1604 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1605 Inst.addOperand(MCOperand::CreateImm(0));
1606 return;
1607 }
1608
Jim Grosbache53c87b2011-10-11 15:59:20 +00001609 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1610 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001611 Inst.addOperand(MCOperand::CreateImm(Val));
1612 }
1613
Jim Grosbachb6aed502011-09-09 18:37:27 +00001614 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 2 && "Invalid number of operands!");
1616 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001617 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1618 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001619 Inst.addOperand(MCOperand::CreateImm(Val));
1620 }
1621
Jim Grosbach7ce05792011-08-03 23:50:40 +00001622 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001624 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1625 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001626 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001627 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001628
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001629 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1630 addMemImm8OffsetOperands(Inst, N);
1631 }
1632
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001633 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001634 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001635 }
1636
1637 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1638 assert(N == 2 && "Invalid number of operands!");
1639 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001640 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001641 addExpr(Inst, getImm());
1642 Inst.addOperand(MCOperand::CreateImm(0));
1643 return;
1644 }
1645
1646 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001647 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1648 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001649 Inst.addOperand(MCOperand::CreateImm(Val));
1650 }
1651
Jim Grosbach7ce05792011-08-03 23:50:40 +00001652 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1653 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001654 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001655 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001656 addExpr(Inst, getImm());
1657 Inst.addOperand(MCOperand::CreateImm(0));
1658 return;
1659 }
1660
1661 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001662 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1663 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001664 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001665 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001666
Jim Grosbach7f739be2011-09-19 22:21:13 +00001667 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1668 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001669 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1670 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001671 }
1672
1673 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1674 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001675 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1676 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001677 }
1678
Jim Grosbach7ce05792011-08-03 23:50:40 +00001679 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1680 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001681 unsigned Val =
1682 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1683 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001684 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1685 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001686 Inst.addOperand(MCOperand::CreateImm(Val));
1687 }
1688
Jim Grosbachab899c12011-09-07 23:10:15 +00001689 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1690 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001691 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1692 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1693 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001694 }
1695
Jim Grosbach7ce05792011-08-03 23:50:40 +00001696 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1697 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001698 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1699 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001700 }
1701
Jim Grosbach60f91a32011-08-19 17:55:24 +00001702 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1703 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001704 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1705 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001706 Inst.addOperand(MCOperand::CreateImm(Val));
1707 }
1708
Jim Grosbach38466302011-08-19 18:55:51 +00001709 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1710 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001711 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1712 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001713 Inst.addOperand(MCOperand::CreateImm(Val));
1714 }
1715
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001716 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1717 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001718 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1719 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001720 Inst.addOperand(MCOperand::CreateImm(Val));
1721 }
1722
Jim Grosbachecd85892011-08-19 18:13:48 +00001723 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1724 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001725 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1726 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001727 Inst.addOperand(MCOperand::CreateImm(Val));
1728 }
1729
Jim Grosbach7ce05792011-08-03 23:50:40 +00001730 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1731 assert(N == 1 && "Invalid number of operands!");
1732 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1733 assert(CE && "non-constant post-idx-imm8 operand!");
1734 int Imm = CE->getValue();
1735 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001736 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001737 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1738 Inst.addOperand(MCOperand::CreateImm(Imm));
1739 }
1740
Jim Grosbach2bd01182011-10-11 21:55:36 +00001741 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1742 assert(N == 1 && "Invalid number of operands!");
1743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1744 assert(CE && "non-constant post-idx-imm8s4 operand!");
1745 int Imm = CE->getValue();
1746 bool isAdd = Imm >= 0;
1747 if (Imm == INT32_MIN) Imm = 0;
1748 // Immediate is scaled by 4.
1749 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1750 Inst.addOperand(MCOperand::CreateImm(Imm));
1751 }
1752
Jim Grosbach7ce05792011-08-03 23:50:40 +00001753 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1754 assert(N == 2 && "Invalid number of operands!");
1755 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001756 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1757 }
1758
1759 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 2 && "Invalid number of operands!");
1761 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1762 // The sign, shift type, and shift amount are encoded in a single operand
1763 // using the AM2 encoding helpers.
1764 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1765 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1766 PostIdxReg.ShiftTy);
1767 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001768 }
1769
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001770 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1771 assert(N == 1 && "Invalid number of operands!");
1772 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1773 }
1774
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001775 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1776 assert(N == 1 && "Invalid number of operands!");
1777 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1778 }
1779
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001780 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001781 assert(N == 1 && "Invalid number of operands!");
1782 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1783 }
1784
Jim Grosbach7636bf62011-12-02 00:35:16 +00001785 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1786 assert(N == 2 && "Invalid number of operands!");
1787 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1788 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1789 }
1790
Jim Grosbach460a9052011-10-07 23:56:00 +00001791 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1792 assert(N == 1 && "Invalid number of operands!");
1793 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1794 }
1795
1796 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1797 assert(N == 1 && "Invalid number of operands!");
1798 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1799 }
1800
1801 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1802 assert(N == 1 && "Invalid number of operands!");
1803 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1804 }
1805
Jim Grosbach0e387b22011-10-17 22:26:03 +00001806 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1807 assert(N == 1 && "Invalid number of operands!");
1808 // The immediate encodes the type of constant as well as the value.
1809 // Mask in that this is an i8 splat.
1810 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1811 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1812 }
1813
Jim Grosbachea461102011-10-17 23:09:09 +00001814 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1815 assert(N == 1 && "Invalid number of operands!");
1816 // The immediate encodes the type of constant as well as the value.
1817 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1818 unsigned Value = CE->getValue();
1819 if (Value >= 256)
1820 Value = (Value >> 8) | 0xa00;
1821 else
1822 Value |= 0x800;
1823 Inst.addOperand(MCOperand::CreateImm(Value));
1824 }
1825
Jim Grosbach6248a542011-10-18 00:22:00 +00001826 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1827 assert(N == 1 && "Invalid number of operands!");
1828 // The immediate encodes the type of constant as well as the value.
1829 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1830 unsigned Value = CE->getValue();
1831 if (Value >= 256 && Value <= 0xff00)
1832 Value = (Value >> 8) | 0x200;
1833 else if (Value > 0xffff && Value <= 0xff0000)
1834 Value = (Value >> 16) | 0x400;
1835 else if (Value > 0xffffff)
1836 Value = (Value >> 24) | 0x600;
1837 Inst.addOperand(MCOperand::CreateImm(Value));
1838 }
1839
1840 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1841 assert(N == 1 && "Invalid number of operands!");
1842 // The immediate encodes the type of constant as well as the value.
1843 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1844 unsigned Value = CE->getValue();
1845 if (Value >= 256 && Value <= 0xffff)
1846 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1847 else if (Value > 0xffff && Value <= 0xffffff)
1848 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1849 else if (Value > 0xffffff)
1850 Value = (Value >> 24) | 0x600;
1851 Inst.addOperand(MCOperand::CreateImm(Value));
1852 }
1853
Jim Grosbach9b087852011-12-19 23:51:07 +00001854 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1855 assert(N == 1 && "Invalid number of operands!");
1856 // The immediate encodes the type of constant as well as the value.
1857 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1858 unsigned Value = ~CE->getValue();
1859 if (Value >= 256 && Value <= 0xffff)
1860 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1861 else if (Value > 0xffff && Value <= 0xffffff)
1862 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1863 else if (Value > 0xffffff)
1864 Value = (Value >> 24) | 0x600;
1865 Inst.addOperand(MCOperand::CreateImm(Value));
1866 }
1867
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001868 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1869 assert(N == 1 && "Invalid number of operands!");
1870 // The immediate encodes the type of constant as well as the value.
1871 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1872 uint64_t Value = CE->getValue();
1873 unsigned Imm = 0;
1874 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1875 Imm |= (Value & 1) << i;
1876 }
1877 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1878 }
1879
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001880 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001881
Jim Grosbach89df9962011-08-26 21:43:41 +00001882 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001883 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001884 Op->ITMask.Mask = Mask;
1885 Op->StartLoc = S;
1886 Op->EndLoc = S;
1887 return Op;
1888 }
1889
Chris Lattner3a697562010-10-28 17:20:03 +00001890 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001892 Op->CC.Val = CC;
1893 Op->StartLoc = S;
1894 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001895 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001896 }
1897
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001898 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001899 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001900 Op->Cop.Val = CopVal;
1901 Op->StartLoc = S;
1902 Op->EndLoc = S;
1903 return Op;
1904 }
1905
1906 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001907 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001908 Op->Cop.Val = CopVal;
1909 Op->StartLoc = S;
1910 Op->EndLoc = S;
1911 return Op;
1912 }
1913
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001914 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1915 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1916 Op->Cop.Val = Val;
1917 Op->StartLoc = S;
1918 Op->EndLoc = E;
1919 return Op;
1920 }
1921
Jim Grosbachd67641b2010-12-06 18:21:12 +00001922 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001924 Op->Reg.RegNum = RegNum;
1925 Op->StartLoc = S;
1926 Op->EndLoc = S;
1927 return Op;
1928 }
1929
Chris Lattner3a697562010-10-28 17:20:03 +00001930 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001932 Op->Tok.Data = Str.data();
1933 Op->Tok.Length = Str.size();
1934 Op->StartLoc = S;
1935 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001936 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001937 }
1938
Bill Wendling50d0f582010-11-18 23:43:05 +00001939 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001941 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001942 Op->StartLoc = S;
1943 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001944 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001945 }
1946
Jim Grosbache8606dc2011-07-13 17:50:29 +00001947 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1948 unsigned SrcReg,
1949 unsigned ShiftReg,
1950 unsigned ShiftImm,
1951 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001952 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001953 Op->RegShiftedReg.ShiftTy = ShTy;
1954 Op->RegShiftedReg.SrcReg = SrcReg;
1955 Op->RegShiftedReg.ShiftReg = ShiftReg;
1956 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001957 Op->StartLoc = S;
1958 Op->EndLoc = E;
1959 return Op;
1960 }
1961
Owen Anderson92a20222011-07-21 18:54:16 +00001962 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1963 unsigned SrcReg,
1964 unsigned ShiftImm,
1965 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001967 Op->RegShiftedImm.ShiftTy = ShTy;
1968 Op->RegShiftedImm.SrcReg = SrcReg;
1969 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001970 Op->StartLoc = S;
1971 Op->EndLoc = E;
1972 return Op;
1973 }
1974
Jim Grosbach580f4a92011-07-25 22:20:28 +00001975 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001976 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001977 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001978 Op->ShifterImm.isASR = isASR;
1979 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001980 Op->StartLoc = S;
1981 Op->EndLoc = E;
1982 return Op;
1983 }
1984
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001985 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001986 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001987 Op->RotImm.Imm = Imm;
1988 Op->StartLoc = S;
1989 Op->EndLoc = E;
1990 return Op;
1991 }
1992
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001993 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1994 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001995 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001996 Op->Bitfield.LSB = LSB;
1997 Op->Bitfield.Width = Width;
1998 Op->StartLoc = S;
1999 Op->EndLoc = E;
2000 return Op;
2001 }
2002
Bill Wendling7729e062010-11-09 22:44:22 +00002003 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002004 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002005 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002006 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002007
Jim Grosbachd300b942011-09-13 22:56:44 +00002008 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002009 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002010 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002011 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002012 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002013
2014 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002015 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002016 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002017 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002018 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002019 Op->StartLoc = StartLoc;
2020 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002021 return Op;
2022 }
2023
Jim Grosbach862019c2011-10-18 23:02:30 +00002024 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002025 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002026 ARMOperand *Op = new ARMOperand(k_VectorList);
2027 Op->VectorList.RegNum = RegNum;
2028 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002029 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002030 Op->StartLoc = S;
2031 Op->EndLoc = E;
2032 return Op;
2033 }
2034
Jim Grosbach98b05a52011-11-30 01:09:44 +00002035 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002036 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002037 SMLoc S, SMLoc E) {
2038 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2039 Op->VectorList.RegNum = RegNum;
2040 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002041 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002042 Op->StartLoc = S;
2043 Op->EndLoc = E;
2044 return Op;
2045 }
2046
Jim Grosbach7636bf62011-12-02 00:35:16 +00002047 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002048 unsigned Index,
2049 bool isDoubleSpaced,
2050 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002051 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2052 Op->VectorList.RegNum = RegNum;
2053 Op->VectorList.Count = Count;
2054 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002055 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002056 Op->StartLoc = S;
2057 Op->EndLoc = E;
2058 return Op;
2059 }
2060
Jim Grosbach460a9052011-10-07 23:56:00 +00002061 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2062 MCContext &Ctx) {
2063 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2064 Op->VectorIndex.Val = Idx;
2065 Op->StartLoc = S;
2066 Op->EndLoc = E;
2067 return Op;
2068 }
2069
Chris Lattner3a697562010-10-28 17:20:03 +00002070 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002071 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002072 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002073 Op->StartLoc = S;
2074 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002075 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002076 }
2077
Jim Grosbach9d390362011-10-03 23:38:36 +00002078 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002079 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002080 Op->FPImm.Val = Val;
2081 Op->StartLoc = S;
2082 Op->EndLoc = S;
2083 return Op;
2084 }
2085
Jim Grosbach7ce05792011-08-03 23:50:40 +00002086 static ARMOperand *CreateMem(unsigned BaseRegNum,
2087 const MCConstantExpr *OffsetImm,
2088 unsigned OffsetRegNum,
2089 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002090 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002091 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002092 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002093 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002094 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002095 Op->Memory.BaseRegNum = BaseRegNum;
2096 Op->Memory.OffsetImm = OffsetImm;
2097 Op->Memory.OffsetRegNum = OffsetRegNum;
2098 Op->Memory.ShiftType = ShiftType;
2099 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002100 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002101 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002102 Op->StartLoc = S;
2103 Op->EndLoc = E;
2104 return Op;
2105 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002106
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002107 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2108 ARM_AM::ShiftOpc ShiftTy,
2109 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002110 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002111 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002112 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002113 Op->PostIdxReg.isAdd = isAdd;
2114 Op->PostIdxReg.ShiftTy = ShiftTy;
2115 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002116 Op->StartLoc = S;
2117 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002118 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002119 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002120
2121 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002122 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002123 Op->MBOpt.Val = Opt;
2124 Op->StartLoc = S;
2125 Op->EndLoc = S;
2126 return Op;
2127 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002128
2129 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002130 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002131 Op->IFlags.Val = IFlags;
2132 Op->StartLoc = S;
2133 Op->EndLoc = S;
2134 return Op;
2135 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002136
2137 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002138 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002139 Op->MMask.Val = MMask;
2140 Op->StartLoc = S;
2141 Op->EndLoc = S;
2142 return Op;
2143 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002144};
2145
2146} // end anonymous namespace.
2147
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002148void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002149 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002150 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002151 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2152 << ") >";
2153 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002154 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002155 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002156 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002157 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002158 OS << "<ccout " << getReg() << ">";
2159 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002160 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002161 static const char *MaskStr[] = {
2162 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2163 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2164 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002165 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2166 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2167 break;
2168 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002169 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002170 OS << "<coprocessor number: " << getCoproc() << ">";
2171 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002172 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002173 OS << "<coprocessor register: " << getCoproc() << ">";
2174 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002175 case k_CoprocOption:
2176 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2177 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002178 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002179 OS << "<mask: " << getMSRMask() << ">";
2180 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002181 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002182 getImm()->print(OS);
2183 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002184 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002185 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2186 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002187 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002188 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002189 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002190 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002191 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002192 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002193 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2194 << PostIdxReg.RegNum;
2195 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2196 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2197 << PostIdxReg.ShiftImm;
2198 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002199 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002200 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002201 OS << "<ARM_PROC::";
2202 unsigned IFlags = getProcIFlags();
2203 for (int i=2; i >= 0; --i)
2204 if (IFlags & (1 << i))
2205 OS << ARM_PROC::IFlagsToString(1 << i);
2206 OS << ">";
2207 break;
2208 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002209 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002210 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002211 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002212 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002213 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2214 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002215 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002216 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002217 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002218 << RegShiftedReg.SrcReg << " "
2219 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2220 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002221 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002222 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002223 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002224 << RegShiftedImm.SrcReg << " "
2225 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2226 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002227 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002229 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2230 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002231 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002232 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2233 << ", width: " << Bitfield.Width << ">";
2234 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002235 case k_RegisterList:
2236 case k_DPRRegisterList:
2237 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002238 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002239
Bill Wendling5fa22a12010-11-09 23:28:44 +00002240 const SmallVectorImpl<unsigned> &RegList = getRegList();
2241 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002242 I = RegList.begin(), E = RegList.end(); I != E; ) {
2243 OS << *I;
2244 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002245 }
2246
2247 OS << ">";
2248 break;
2249 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002250 case k_VectorList:
2251 OS << "<vector_list " << VectorList.Count << " * "
2252 << VectorList.RegNum << ">";
2253 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002254 case k_VectorListAllLanes:
2255 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2256 << VectorList.RegNum << ">";
2257 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002258 case k_VectorListIndexed:
2259 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2260 << VectorList.Count << " * " << VectorList.RegNum << ">";
2261 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002262 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002263 OS << "'" << getToken() << "'";
2264 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002265 case k_VectorIndex:
2266 OS << "<vectorindex " << getVectorIndex() << ">";
2267 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002268 }
2269}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002270
2271/// @name Auto-generated Match Functions
2272/// {
2273
2274static unsigned MatchRegisterName(StringRef Name);
2275
2276/// }
2277
Bob Wilson69df7232011-02-03 21:46:10 +00002278bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2279 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002280 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002281 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002282 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002283
2284 return (RegNo == (unsigned)-1);
2285}
2286
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002287/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002288/// and if it is a register name the token is eaten and the register number is
2289/// returned. Otherwise return -1.
2290///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002291int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002292 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002293 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002294
Benjamin Kramer59085362011-11-06 20:37:06 +00002295 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002296 unsigned RegNum = MatchRegisterName(lowerCase);
2297 if (!RegNum) {
2298 RegNum = StringSwitch<unsigned>(lowerCase)
2299 .Case("r13", ARM::SP)
2300 .Case("r14", ARM::LR)
2301 .Case("r15", ARM::PC)
2302 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002303 // Additional register name aliases for 'gas' compatibility.
2304 .Case("a1", ARM::R0)
2305 .Case("a2", ARM::R1)
2306 .Case("a3", ARM::R2)
2307 .Case("a4", ARM::R3)
2308 .Case("v1", ARM::R4)
2309 .Case("v2", ARM::R5)
2310 .Case("v3", ARM::R6)
2311 .Case("v4", ARM::R7)
2312 .Case("v5", ARM::R8)
2313 .Case("v6", ARM::R9)
2314 .Case("v7", ARM::R10)
2315 .Case("v8", ARM::R11)
2316 .Case("sb", ARM::R9)
2317 .Case("sl", ARM::R10)
2318 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002319 .Default(0);
2320 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002321 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002322 // Check for aliases registered via .req. Canonicalize to lower case.
2323 // That's more consistent since register names are case insensitive, and
2324 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2325 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002326 // If no match, return failure.
2327 if (Entry == RegisterReqs.end())
2328 return -1;
2329 Parser.Lex(); // Eat identifier token.
2330 return Entry->getValue();
2331 }
Bob Wilson69df7232011-02-03 21:46:10 +00002332
Chris Lattnere5658fa2010-10-30 04:09:10 +00002333 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002334
Chris Lattnere5658fa2010-10-30 04:09:10 +00002335 return RegNum;
2336}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002337
Jim Grosbach19906722011-07-13 18:49:30 +00002338// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2339// If a recoverable error occurs, return 1. If an irrecoverable error
2340// occurs, return -1. An irrecoverable error is one where tokens have been
2341// consumed in the process of trying to parse the shifter (i.e., when it is
2342// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002343int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002344 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2345 SMLoc S = Parser.getTok().getLoc();
2346 const AsmToken &Tok = Parser.getTok();
2347 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2348
Benjamin Kramer59085362011-11-06 20:37:06 +00002349 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002350 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002351 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002352 .Case("lsl", ARM_AM::lsl)
2353 .Case("lsr", ARM_AM::lsr)
2354 .Case("asr", ARM_AM::asr)
2355 .Case("ror", ARM_AM::ror)
2356 .Case("rrx", ARM_AM::rrx)
2357 .Default(ARM_AM::no_shift);
2358
2359 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002360 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002361
Jim Grosbache8606dc2011-07-13 17:50:29 +00002362 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002363
Jim Grosbache8606dc2011-07-13 17:50:29 +00002364 // The source register for the shift has already been added to the
2365 // operand list, so we need to pop it off and combine it into the shifted
2366 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002367 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002368 if (!PrevOp->isReg())
2369 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2370 int SrcReg = PrevOp->getReg();
2371 int64_t Imm = 0;
2372 int ShiftReg = 0;
2373 if (ShiftTy == ARM_AM::rrx) {
2374 // RRX Doesn't have an explicit shift amount. The encoder expects
2375 // the shift register to be the same as the source register. Seems odd,
2376 // but OK.
2377 ShiftReg = SrcReg;
2378 } else {
2379 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002380 if (Parser.getTok().is(AsmToken::Hash) ||
2381 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002382 Parser.Lex(); // Eat hash.
2383 SMLoc ImmLoc = Parser.getTok().getLoc();
2384 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002385 if (getParser().ParseExpression(ShiftExpr)) {
2386 Error(ImmLoc, "invalid immediate shift value");
2387 return -1;
2388 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002389 // The expression must be evaluatable as an immediate.
2390 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002391 if (!CE) {
2392 Error(ImmLoc, "invalid immediate shift value");
2393 return -1;
2394 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002395 // Range check the immediate.
2396 // lsl, ror: 0 <= imm <= 31
2397 // lsr, asr: 0 <= imm <= 32
2398 Imm = CE->getValue();
2399 if (Imm < 0 ||
2400 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2401 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002402 Error(ImmLoc, "immediate shift value out of range");
2403 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002404 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002405 // shift by zero is a nop. Always send it through as lsl.
2406 // ('as' compatibility)
2407 if (Imm == 0)
2408 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002409 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002410 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002411 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002412 if (ShiftReg == -1) {
2413 Error (L, "expected immediate or register in shift operand");
2414 return -1;
2415 }
2416 } else {
2417 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002418 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002419 return -1;
2420 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002421 }
2422
Owen Anderson92a20222011-07-21 18:54:16 +00002423 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2424 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002425 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002426 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002427 else
2428 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2429 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002430
Jim Grosbach19906722011-07-13 18:49:30 +00002431 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002432}
2433
2434
Bill Wendling50d0f582010-11-18 23:43:05 +00002435/// Try to parse a register name. The token must be an Identifier when called.
2436/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2437/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002438///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002439/// TODO this is likely to change to allow different register types and or to
2440/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002441bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002442tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002443 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002444 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002445 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002446 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002447
Bill Wendling50d0f582010-11-18 23:43:05 +00002448 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002449
Chris Lattnere5658fa2010-10-30 04:09:10 +00002450 const AsmToken &ExclaimTok = Parser.getTok();
2451 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002452 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2453 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002454 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002455 return false;
2456 }
2457
2458 // Also check for an index operand. This is only legal for vector registers,
2459 // but that'll get caught OK in operand matching, so we don't need to
2460 // explicitly filter everything else out here.
2461 if (Parser.getTok().is(AsmToken::LBrac)) {
2462 SMLoc SIdx = Parser.getTok().getLoc();
2463 Parser.Lex(); // Eat left bracket token.
2464
2465 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002466 if (getParser().ParseExpression(ImmVal))
2467 return MatchOperand_ParseFail;
2468 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2469 if (!MCE) {
2470 TokError("immediate value expected for vector index");
2471 return MatchOperand_ParseFail;
2472 }
2473
2474 SMLoc E = Parser.getTok().getLoc();
2475 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2476 Error(E, "']' expected");
2477 return MatchOperand_ParseFail;
2478 }
2479
2480 Parser.Lex(); // Eat right bracket token.
2481
2482 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2483 SIdx, E,
2484 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002485 }
2486
Bill Wendling50d0f582010-11-18 23:43:05 +00002487 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002488}
2489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002490/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2491/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2492/// "c5", ...
2493static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002494 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2495 // but efficient.
2496 switch (Name.size()) {
2497 default: break;
2498 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002499 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002500 return -1;
2501 switch (Name[1]) {
2502 default: return -1;
2503 case '0': return 0;
2504 case '1': return 1;
2505 case '2': return 2;
2506 case '3': return 3;
2507 case '4': return 4;
2508 case '5': return 5;
2509 case '6': return 6;
2510 case '7': return 7;
2511 case '8': return 8;
2512 case '9': return 9;
2513 }
2514 break;
2515 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002516 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002517 return -1;
2518 switch (Name[2]) {
2519 default: return -1;
2520 case '0': return 10;
2521 case '1': return 11;
2522 case '2': return 12;
2523 case '3': return 13;
2524 case '4': return 14;
2525 case '5': return 15;
2526 }
2527 break;
2528 }
2529
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002530 return -1;
2531}
2532
Jim Grosbach89df9962011-08-26 21:43:41 +00002533/// parseITCondCode - Try to parse a condition code for an IT instruction.
2534ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2535parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2536 SMLoc S = Parser.getTok().getLoc();
2537 const AsmToken &Tok = Parser.getTok();
2538 if (!Tok.is(AsmToken::Identifier))
2539 return MatchOperand_NoMatch;
2540 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2541 .Case("eq", ARMCC::EQ)
2542 .Case("ne", ARMCC::NE)
2543 .Case("hs", ARMCC::HS)
2544 .Case("cs", ARMCC::HS)
2545 .Case("lo", ARMCC::LO)
2546 .Case("cc", ARMCC::LO)
2547 .Case("mi", ARMCC::MI)
2548 .Case("pl", ARMCC::PL)
2549 .Case("vs", ARMCC::VS)
2550 .Case("vc", ARMCC::VC)
2551 .Case("hi", ARMCC::HI)
2552 .Case("ls", ARMCC::LS)
2553 .Case("ge", ARMCC::GE)
2554 .Case("lt", ARMCC::LT)
2555 .Case("gt", ARMCC::GT)
2556 .Case("le", ARMCC::LE)
2557 .Case("al", ARMCC::AL)
2558 .Default(~0U);
2559 if (CC == ~0U)
2560 return MatchOperand_NoMatch;
2561 Parser.Lex(); // Eat the token.
2562
2563 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2564
2565 return MatchOperand_Success;
2566}
2567
Jim Grosbach43904292011-07-25 20:14:50 +00002568/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002569/// token must be an Identifier when called, and if it is a coprocessor
2570/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002571ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002572parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002573 SMLoc S = Parser.getTok().getLoc();
2574 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002575 if (Tok.isNot(AsmToken::Identifier))
2576 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002577
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002578 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002579 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002580 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002581
2582 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002583 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002584 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002585}
2586
Jim Grosbach43904292011-07-25 20:14:50 +00002587/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002588/// token must be an Identifier when called, and if it is a coprocessor
2589/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002590ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002591parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002592 SMLoc S = Parser.getTok().getLoc();
2593 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002594 if (Tok.isNot(AsmToken::Identifier))
2595 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002596
2597 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2598 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002599 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002600
2601 Parser.Lex(); // Eat identifier token.
2602 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002603 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002604}
2605
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002606/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2607/// coproc_option : '{' imm0_255 '}'
2608ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2609parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2610 SMLoc S = Parser.getTok().getLoc();
2611
2612 // If this isn't a '{', this isn't a coprocessor immediate operand.
2613 if (Parser.getTok().isNot(AsmToken::LCurly))
2614 return MatchOperand_NoMatch;
2615 Parser.Lex(); // Eat the '{'
2616
2617 const MCExpr *Expr;
2618 SMLoc Loc = Parser.getTok().getLoc();
2619 if (getParser().ParseExpression(Expr)) {
2620 Error(Loc, "illegal expression");
2621 return MatchOperand_ParseFail;
2622 }
2623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2624 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2625 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2626 return MatchOperand_ParseFail;
2627 }
2628 int Val = CE->getValue();
2629
2630 // Check for and consume the closing '}'
2631 if (Parser.getTok().isNot(AsmToken::RCurly))
2632 return MatchOperand_ParseFail;
2633 SMLoc E = Parser.getTok().getLoc();
2634 Parser.Lex(); // Eat the '}'
2635
2636 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2637 return MatchOperand_Success;
2638}
2639
Jim Grosbachd0588e22011-09-14 18:08:35 +00002640// For register list parsing, we need to map from raw GPR register numbering
2641// to the enumeration values. The enumeration values aren't sorted by
2642// register number due to our using "sp", "lr" and "pc" as canonical names.
2643static unsigned getNextRegister(unsigned Reg) {
2644 // If this is a GPR, we need to do it manually, otherwise we can rely
2645 // on the sort ordering of the enumeration since the other reg-classes
2646 // are sane.
2647 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2648 return Reg + 1;
2649 switch(Reg) {
2650 default: assert(0 && "Invalid GPR number!");
2651 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2652 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2653 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2654 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2655 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2656 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2657 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2658 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2659 }
2660}
2661
Jim Grosbachce485e72011-11-11 21:27:40 +00002662// Return the low-subreg of a given Q register.
2663static unsigned getDRegFromQReg(unsigned QReg) {
2664 switch (QReg) {
2665 default: llvm_unreachable("expected a Q register!");
2666 case ARM::Q0: return ARM::D0;
2667 case ARM::Q1: return ARM::D2;
2668 case ARM::Q2: return ARM::D4;
2669 case ARM::Q3: return ARM::D6;
2670 case ARM::Q4: return ARM::D8;
2671 case ARM::Q5: return ARM::D10;
2672 case ARM::Q6: return ARM::D12;
2673 case ARM::Q7: return ARM::D14;
2674 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002675 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002676 case ARM::Q10: return ARM::D20;
2677 case ARM::Q11: return ARM::D22;
2678 case ARM::Q12: return ARM::D24;
2679 case ARM::Q13: return ARM::D26;
2680 case ARM::Q14: return ARM::D28;
2681 case ARM::Q15: return ARM::D30;
2682 }
2683}
2684
Jim Grosbachd0588e22011-09-14 18:08:35 +00002685/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002686bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002687parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002688 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002689 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002690 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002691 Parser.Lex(); // Eat '{' token.
2692 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002693
Jim Grosbachd0588e22011-09-14 18:08:35 +00002694 // Check the first register in the list to see what register class
2695 // this is a list of.
2696 int Reg = tryParseRegister();
2697 if (Reg == -1)
2698 return Error(RegLoc, "register expected");
2699
Jim Grosbachce485e72011-11-11 21:27:40 +00002700 // The reglist instructions have at most 16 registers, so reserve
2701 // space for that many.
2702 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2703
2704 // Allow Q regs and just interpret them as the two D sub-registers.
2705 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2706 Reg = getDRegFromQReg(Reg);
2707 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2708 ++Reg;
2709 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002710 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002711 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2712 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2713 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2714 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2715 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2716 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2717 else
2718 return Error(RegLoc, "invalid register in register list");
2719
Jim Grosbachce485e72011-11-11 21:27:40 +00002720 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002721 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002722
Jim Grosbachd0588e22011-09-14 18:08:35 +00002723 // This starts immediately after the first register token in the list,
2724 // so we can see either a comma or a minus (range separator) as a legal
2725 // next token.
2726 while (Parser.getTok().is(AsmToken::Comma) ||
2727 Parser.getTok().is(AsmToken::Minus)) {
2728 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002729 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002730 SMLoc EndLoc = Parser.getTok().getLoc();
2731 int EndReg = tryParseRegister();
2732 if (EndReg == -1)
2733 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002734 // Allow Q regs and just interpret them as the two D sub-registers.
2735 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2736 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002737 // If the register is the same as the start reg, there's nothing
2738 // more to do.
2739 if (Reg == EndReg)
2740 continue;
2741 // The register must be in the same register class as the first.
2742 if (!RC->contains(EndReg))
2743 return Error(EndLoc, "invalid register in register list");
2744 // Ranges must go from low to high.
2745 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2746 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002747
Jim Grosbachd0588e22011-09-14 18:08:35 +00002748 // Add all the registers in the range to the register list.
2749 while (Reg != EndReg) {
2750 Reg = getNextRegister(Reg);
2751 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2752 }
2753 continue;
2754 }
2755 Parser.Lex(); // Eat the comma.
2756 RegLoc = Parser.getTok().getLoc();
2757 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002758 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002759 Reg = tryParseRegister();
2760 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002761 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002762 // Allow Q regs and just interpret them as the two D sub-registers.
2763 bool isQReg = false;
2764 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2765 Reg = getDRegFromQReg(Reg);
2766 isQReg = true;
2767 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002768 // The register must be in the same register class as the first.
2769 if (!RC->contains(Reg))
2770 return Error(RegLoc, "invalid register in register list");
2771 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002772 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002773 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002774 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2775 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2776 ") in register list");
2777 continue;
2778 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002779 // VFP register lists must also be contiguous.
2780 // It's OK to use the enumeration values directly here rather, as the
2781 // VFP register classes have the enum sorted properly.
2782 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2783 Reg != OldReg + 1)
2784 return Error(RegLoc, "non-contiguous register range");
2785 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002786 if (isQReg)
2787 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002788 }
2789
Jim Grosbachd0588e22011-09-14 18:08:35 +00002790 SMLoc E = Parser.getTok().getLoc();
2791 if (Parser.getTok().isNot(AsmToken::RCurly))
2792 return Error(E, "'}' expected");
2793 Parser.Lex(); // Eat '}' token.
2794
Jim Grosbach27debd62011-12-13 21:48:29 +00002795 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002796 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002797
2798 // The ARM system instruction variants for LDM/STM have a '^' token here.
2799 if (Parser.getTok().is(AsmToken::Caret)) {
2800 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2801 Parser.Lex(); // Eat '^' token.
2802 }
2803
Bill Wendling50d0f582010-11-18 23:43:05 +00002804 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002805}
2806
Jim Grosbach98b05a52011-11-30 01:09:44 +00002807// Helper function to parse the lane index for vector lists.
2808ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002809parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2810 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002811 if (Parser.getTok().is(AsmToken::LBrac)) {
2812 Parser.Lex(); // Eat the '['.
2813 if (Parser.getTok().is(AsmToken::RBrac)) {
2814 // "Dn[]" is the 'all lanes' syntax.
2815 LaneKind = AllLanes;
2816 Parser.Lex(); // Eat the ']'.
2817 return MatchOperand_Success;
2818 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002819 const MCExpr *LaneIndex;
2820 SMLoc Loc = Parser.getTok().getLoc();
2821 if (getParser().ParseExpression(LaneIndex)) {
2822 Error(Loc, "illegal expression");
2823 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002824 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002825 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2826 if (!CE) {
2827 Error(Loc, "lane index must be empty or an integer");
2828 return MatchOperand_ParseFail;
2829 }
2830 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2831 Error(Parser.getTok().getLoc(), "']' expected");
2832 return MatchOperand_ParseFail;
2833 }
2834 Parser.Lex(); // Eat the ']'.
2835 int64_t Val = CE->getValue();
2836
2837 // FIXME: Make this range check context sensitive for .8, .16, .32.
2838 if (Val < 0 || Val > 7) {
2839 Error(Parser.getTok().getLoc(), "lane index out of range");
2840 return MatchOperand_ParseFail;
2841 }
2842 Index = Val;
2843 LaneKind = IndexedLane;
2844 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002845 }
2846 LaneKind = NoLanes;
2847 return MatchOperand_Success;
2848}
2849
Jim Grosbach862019c2011-10-18 23:02:30 +00002850// parse a vector register list
2851ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2852parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002853 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002854 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002855 SMLoc S = Parser.getTok().getLoc();
2856 // As an extension (to match gas), support a plain D register or Q register
2857 // (without encosing curly braces) as a single or double entry list,
2858 // respectively.
2859 if (Parser.getTok().is(AsmToken::Identifier)) {
2860 int Reg = tryParseRegister();
2861 if (Reg == -1)
2862 return MatchOperand_NoMatch;
2863 SMLoc E = Parser.getTok().getLoc();
2864 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002865 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002866 if (Res != MatchOperand_Success)
2867 return Res;
2868 switch (LaneKind) {
2869 default:
2870 assert(0 && "unexpected lane kind!");
2871 case NoLanes:
2872 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002873 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002874 break;
2875 case AllLanes:
2876 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002877 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2878 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002879 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002880 case IndexedLane:
2881 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002882 LaneIndex,
2883 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002884 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002885 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002886 return MatchOperand_Success;
2887 }
2888 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2889 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002890 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002891 if (Res != MatchOperand_Success)
2892 return Res;
2893 switch (LaneKind) {
2894 default:
2895 assert(0 && "unexpected lane kind!");
2896 case NoLanes:
2897 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002898 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002899 break;
2900 case AllLanes:
2901 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002902 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2903 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002904 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002905 case IndexedLane:
2906 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002907 LaneIndex,
2908 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002909 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002910 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002911 return MatchOperand_Success;
2912 }
2913 Error(S, "vector register expected");
2914 return MatchOperand_ParseFail;
2915 }
2916
2917 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002918 return MatchOperand_NoMatch;
2919
Jim Grosbach862019c2011-10-18 23:02:30 +00002920 Parser.Lex(); // Eat '{' token.
2921 SMLoc RegLoc = Parser.getTok().getLoc();
2922
2923 int Reg = tryParseRegister();
2924 if (Reg == -1) {
2925 Error(RegLoc, "register expected");
2926 return MatchOperand_ParseFail;
2927 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002928 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002929 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002930 unsigned FirstReg = Reg;
2931 // The list is of D registers, but we also allow Q regs and just interpret
2932 // them as the two D sub-registers.
2933 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2934 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002935 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2936 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002937 ++Reg;
2938 ++Count;
2939 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002940 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002941 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002942
Jim Grosbache43862b2011-11-15 23:19:15 +00002943 while (Parser.getTok().is(AsmToken::Comma) ||
2944 Parser.getTok().is(AsmToken::Minus)) {
2945 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002946 if (!Spacing)
2947 Spacing = 1; // Register range implies a single spaced list.
2948 else if (Spacing == 2) {
2949 Error(Parser.getTok().getLoc(),
2950 "sequential registers in double spaced list");
2951 return MatchOperand_ParseFail;
2952 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002953 Parser.Lex(); // Eat the minus.
2954 SMLoc EndLoc = Parser.getTok().getLoc();
2955 int EndReg = tryParseRegister();
2956 if (EndReg == -1) {
2957 Error(EndLoc, "register expected");
2958 return MatchOperand_ParseFail;
2959 }
2960 // Allow Q regs and just interpret them as the two D sub-registers.
2961 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2962 EndReg = getDRegFromQReg(EndReg) + 1;
2963 // If the register is the same as the start reg, there's nothing
2964 // more to do.
2965 if (Reg == EndReg)
2966 continue;
2967 // The register must be in the same register class as the first.
2968 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2969 Error(EndLoc, "invalid register in register list");
2970 return MatchOperand_ParseFail;
2971 }
2972 // Ranges must go from low to high.
2973 if (Reg > EndReg) {
2974 Error(EndLoc, "bad range in register list");
2975 return MatchOperand_ParseFail;
2976 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002977 // Parse the lane specifier if present.
2978 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002979 unsigned NextLaneIndex;
2980 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002981 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002982 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002983 Error(EndLoc, "mismatched lane index in register list");
2984 return MatchOperand_ParseFail;
2985 }
2986 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002987
2988 // Add all the registers in the range to the register list.
2989 Count += EndReg - Reg;
2990 Reg = EndReg;
2991 continue;
2992 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002993 Parser.Lex(); // Eat the comma.
2994 RegLoc = Parser.getTok().getLoc();
2995 int OldReg = Reg;
2996 Reg = tryParseRegister();
2997 if (Reg == -1) {
2998 Error(RegLoc, "register expected");
2999 return MatchOperand_ParseFail;
3000 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003001 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003002 // It's OK to use the enumeration values directly here rather, as the
3003 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003004 //
3005 // The list is of D registers, but we also allow Q regs and just interpret
3006 // them as the two D sub-registers.
3007 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003008 if (!Spacing)
3009 Spacing = 1; // Register range implies a single spaced list.
3010 else if (Spacing == 2) {
3011 Error(RegLoc,
3012 "invalid register in double-spaced list (must be 'D' register')");
3013 return MatchOperand_ParseFail;
3014 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003015 Reg = getDRegFromQReg(Reg);
3016 if (Reg != OldReg + 1) {
3017 Error(RegLoc, "non-contiguous register range");
3018 return MatchOperand_ParseFail;
3019 }
3020 ++Reg;
3021 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003022 // Parse the lane specifier if present.
3023 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003024 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003025 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003026 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003027 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003028 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003029 Error(EndLoc, "mismatched lane index in register list");
3030 return MatchOperand_ParseFail;
3031 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003032 continue;
3033 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003034 // Normal D register.
3035 // Figure out the register spacing (single or double) of the list if
3036 // we don't know it already.
3037 if (!Spacing)
3038 Spacing = 1 + (Reg == OldReg + 2);
3039
3040 // Just check that it's contiguous and keep going.
3041 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003042 Error(RegLoc, "non-contiguous register range");
3043 return MatchOperand_ParseFail;
3044 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003045 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003046 // Parse the lane specifier if present.
3047 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003048 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003050 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003051 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003052 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003053 Error(EndLoc, "mismatched lane index in register list");
3054 return MatchOperand_ParseFail;
3055 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003056 }
3057
3058 SMLoc E = Parser.getTok().getLoc();
3059 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3060 Error(E, "'}' expected");
3061 return MatchOperand_ParseFail;
3062 }
3063 Parser.Lex(); // Eat '}' token.
3064
Jim Grosbach98b05a52011-11-30 01:09:44 +00003065 switch (LaneKind) {
3066 default:
3067 assert(0 && "unexpected lane kind in register list.");
3068 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003069 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3070 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003071 break;
3072 case AllLanes:
3073 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003074 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003075 S, E));
3076 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003077 case IndexedLane:
3078 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003079 LaneIndex,
3080 (Spacing == 2),
3081 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003082 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003083 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003084 return MatchOperand_Success;
3085}
3086
Jim Grosbach43904292011-07-25 20:14:50 +00003087/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003088ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003089parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003090 SMLoc S = Parser.getTok().getLoc();
3091 const AsmToken &Tok = Parser.getTok();
3092 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3093 StringRef OptStr = Tok.getString();
3094
3095 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3096 .Case("sy", ARM_MB::SY)
3097 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003098 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003099 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003100 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003101 .Case("ishst", ARM_MB::ISHST)
3102 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003103 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003104 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003105 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003106 .Case("osh", ARM_MB::OSH)
3107 .Case("oshst", ARM_MB::OSHST)
3108 .Default(~0U);
3109
3110 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003111 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003112
3113 Parser.Lex(); // Eat identifier token.
3114 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003115 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003116}
3117
Jim Grosbach43904292011-07-25 20:14:50 +00003118/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003119ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003120parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003121 SMLoc S = Parser.getTok().getLoc();
3122 const AsmToken &Tok = Parser.getTok();
3123 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3124 StringRef IFlagsStr = Tok.getString();
3125
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003126 // An iflags string of "none" is interpreted to mean that none of the AIF
3127 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003128 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003129 if (IFlagsStr != "none") {
3130 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3131 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3132 .Case("a", ARM_PROC::A)
3133 .Case("i", ARM_PROC::I)
3134 .Case("f", ARM_PROC::F)
3135 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003136
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003137 // If some specific iflag is already set, it means that some letter is
3138 // present more than once, this is not acceptable.
3139 if (Flag == ~0U || (IFlags & Flag))
3140 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003141
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003142 IFlags |= Flag;
3143 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003144 }
3145
3146 Parser.Lex(); // Eat identifier token.
3147 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3148 return MatchOperand_Success;
3149}
3150
Jim Grosbach43904292011-07-25 20:14:50 +00003151/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003152ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003153parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003154 SMLoc S = Parser.getTok().getLoc();
3155 const AsmToken &Tok = Parser.getTok();
3156 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3157 StringRef Mask = Tok.getString();
3158
James Molloyacad68d2011-09-28 14:21:38 +00003159 if (isMClass()) {
3160 // See ARMv6-M 10.1.1
3161 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3162 .Case("apsr", 0)
3163 .Case("iapsr", 1)
3164 .Case("eapsr", 2)
3165 .Case("xpsr", 3)
3166 .Case("ipsr", 5)
3167 .Case("epsr", 6)
3168 .Case("iepsr", 7)
3169 .Case("msp", 8)
3170 .Case("psp", 9)
3171 .Case("primask", 16)
3172 .Case("basepri", 17)
3173 .Case("basepri_max", 18)
3174 .Case("faultmask", 19)
3175 .Case("control", 20)
3176 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003177
James Molloyacad68d2011-09-28 14:21:38 +00003178 if (FlagsVal == ~0U)
3179 return MatchOperand_NoMatch;
3180
3181 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3182 // basepri, basepri_max and faultmask only valid for V7m.
3183 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003184
James Molloyacad68d2011-09-28 14:21:38 +00003185 Parser.Lex(); // Eat identifier token.
3186 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3187 return MatchOperand_Success;
3188 }
3189
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003190 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3191 size_t Start = 0, Next = Mask.find('_');
3192 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003193 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003194 if (Next != StringRef::npos)
3195 Flags = Mask.slice(Next+1, Mask.size());
3196
3197 // FlagsVal contains the complete mask:
3198 // 3-0: Mask
3199 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3200 unsigned FlagsVal = 0;
3201
3202 if (SpecReg == "apsr") {
3203 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003204 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003205 .Case("g", 0x4) // same as CPSR_s
3206 .Case("nzcvqg", 0xc) // same as CPSR_fs
3207 .Default(~0U);
3208
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003209 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003210 if (!Flags.empty())
3211 return MatchOperand_NoMatch;
3212 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003213 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003214 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003215 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003216 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3217 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003218 for (int i = 0, e = Flags.size(); i != e; ++i) {
3219 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3220 .Case("c", 1)
3221 .Case("x", 2)
3222 .Case("s", 4)
3223 .Case("f", 8)
3224 .Default(~0U);
3225
3226 // If some specific flag is already set, it means that some letter is
3227 // present more than once, this is not acceptable.
3228 if (FlagsVal == ~0U || (FlagsVal & Flag))
3229 return MatchOperand_NoMatch;
3230 FlagsVal |= Flag;
3231 }
3232 } else // No match for special register.
3233 return MatchOperand_NoMatch;
3234
Owen Anderson7784f1d2011-10-21 18:43:28 +00003235 // Special register without flags is NOT equivalent to "fc" flags.
3236 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3237 // two lines would enable gas compatibility at the expense of breaking
3238 // round-tripping.
3239 //
3240 // if (!FlagsVal)
3241 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003242
3243 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3244 if (SpecReg == "spsr")
3245 FlagsVal |= 16;
3246
3247 Parser.Lex(); // Eat identifier token.
3248 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3249 return MatchOperand_Success;
3250}
3251
Jim Grosbachf6c05252011-07-21 17:23:04 +00003252ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3253parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3254 int Low, int High) {
3255 const AsmToken &Tok = Parser.getTok();
3256 if (Tok.isNot(AsmToken::Identifier)) {
3257 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3258 return MatchOperand_ParseFail;
3259 }
3260 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003261 std::string LowerOp = Op.lower();
3262 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003263 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3264 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3265 return MatchOperand_ParseFail;
3266 }
3267 Parser.Lex(); // Eat shift type token.
3268
3269 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003270 if (Parser.getTok().isNot(AsmToken::Hash) &&
3271 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003272 Error(Parser.getTok().getLoc(), "'#' expected");
3273 return MatchOperand_ParseFail;
3274 }
3275 Parser.Lex(); // Eat hash token.
3276
3277 const MCExpr *ShiftAmount;
3278 SMLoc Loc = Parser.getTok().getLoc();
3279 if (getParser().ParseExpression(ShiftAmount)) {
3280 Error(Loc, "illegal expression");
3281 return MatchOperand_ParseFail;
3282 }
3283 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3284 if (!CE) {
3285 Error(Loc, "constant expression expected");
3286 return MatchOperand_ParseFail;
3287 }
3288 int Val = CE->getValue();
3289 if (Val < Low || Val > High) {
3290 Error(Loc, "immediate value out of range");
3291 return MatchOperand_ParseFail;
3292 }
3293
3294 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3295
3296 return MatchOperand_Success;
3297}
3298
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003299ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3300parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3301 const AsmToken &Tok = Parser.getTok();
3302 SMLoc S = Tok.getLoc();
3303 if (Tok.isNot(AsmToken::Identifier)) {
3304 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3305 return MatchOperand_ParseFail;
3306 }
3307 int Val = StringSwitch<int>(Tok.getString())
3308 .Case("be", 1)
3309 .Case("le", 0)
3310 .Default(-1);
3311 Parser.Lex(); // Eat the token.
3312
3313 if (Val == -1) {
3314 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3315 return MatchOperand_ParseFail;
3316 }
3317 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3318 getContext()),
3319 S, Parser.getTok().getLoc()));
3320 return MatchOperand_Success;
3321}
3322
Jim Grosbach580f4a92011-07-25 22:20:28 +00003323/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3324/// instructions. Legal values are:
3325/// lsl #n 'n' in [0,31]
3326/// asr #n 'n' in [1,32]
3327/// n == 32 encoded as n == 0.
3328ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3329parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3330 const AsmToken &Tok = Parser.getTok();
3331 SMLoc S = Tok.getLoc();
3332 if (Tok.isNot(AsmToken::Identifier)) {
3333 Error(S, "shift operator 'asr' or 'lsl' expected");
3334 return MatchOperand_ParseFail;
3335 }
3336 StringRef ShiftName = Tok.getString();
3337 bool isASR;
3338 if (ShiftName == "lsl" || ShiftName == "LSL")
3339 isASR = false;
3340 else if (ShiftName == "asr" || ShiftName == "ASR")
3341 isASR = true;
3342 else {
3343 Error(S, "shift operator 'asr' or 'lsl' expected");
3344 return MatchOperand_ParseFail;
3345 }
3346 Parser.Lex(); // Eat the operator.
3347
3348 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003349 if (Parser.getTok().isNot(AsmToken::Hash) &&
3350 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003351 Error(Parser.getTok().getLoc(), "'#' expected");
3352 return MatchOperand_ParseFail;
3353 }
3354 Parser.Lex(); // Eat hash token.
3355
3356 const MCExpr *ShiftAmount;
3357 SMLoc E = Parser.getTok().getLoc();
3358 if (getParser().ParseExpression(ShiftAmount)) {
3359 Error(E, "malformed shift expression");
3360 return MatchOperand_ParseFail;
3361 }
3362 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3363 if (!CE) {
3364 Error(E, "shift amount must be an immediate");
3365 return MatchOperand_ParseFail;
3366 }
3367
3368 int64_t Val = CE->getValue();
3369 if (isASR) {
3370 // Shift amount must be in [1,32]
3371 if (Val < 1 || Val > 32) {
3372 Error(E, "'asr' shift amount must be in range [1,32]");
3373 return MatchOperand_ParseFail;
3374 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003375 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3376 if (isThumb() && Val == 32) {
3377 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3378 return MatchOperand_ParseFail;
3379 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003380 if (Val == 32) Val = 0;
3381 } else {
3382 // Shift amount must be in [1,32]
3383 if (Val < 0 || Val > 31) {
3384 Error(E, "'lsr' shift amount must be in range [0,31]");
3385 return MatchOperand_ParseFail;
3386 }
3387 }
3388
3389 E = Parser.getTok().getLoc();
3390 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3391
3392 return MatchOperand_Success;
3393}
3394
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003395/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3396/// of instructions. Legal values are:
3397/// ror #n 'n' in {0, 8, 16, 24}
3398ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3399parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3400 const AsmToken &Tok = Parser.getTok();
3401 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003402 if (Tok.isNot(AsmToken::Identifier))
3403 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003404 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003405 if (ShiftName != "ror" && ShiftName != "ROR")
3406 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003407 Parser.Lex(); // Eat the operator.
3408
3409 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003410 if (Parser.getTok().isNot(AsmToken::Hash) &&
3411 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003412 Error(Parser.getTok().getLoc(), "'#' expected");
3413 return MatchOperand_ParseFail;
3414 }
3415 Parser.Lex(); // Eat hash token.
3416
3417 const MCExpr *ShiftAmount;
3418 SMLoc E = Parser.getTok().getLoc();
3419 if (getParser().ParseExpression(ShiftAmount)) {
3420 Error(E, "malformed rotate expression");
3421 return MatchOperand_ParseFail;
3422 }
3423 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3424 if (!CE) {
3425 Error(E, "rotate amount must be an immediate");
3426 return MatchOperand_ParseFail;
3427 }
3428
3429 int64_t Val = CE->getValue();
3430 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3431 // normally, zero is represented in asm by omitting the rotate operand
3432 // entirely.
3433 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3434 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3435 return MatchOperand_ParseFail;
3436 }
3437
3438 E = Parser.getTok().getLoc();
3439 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3440
3441 return MatchOperand_Success;
3442}
3443
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003444ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3445parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3446 SMLoc S = Parser.getTok().getLoc();
3447 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003448 if (Parser.getTok().isNot(AsmToken::Hash) &&
3449 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003450 Error(Parser.getTok().getLoc(), "'#' expected");
3451 return MatchOperand_ParseFail;
3452 }
3453 Parser.Lex(); // Eat hash token.
3454
3455 const MCExpr *LSBExpr;
3456 SMLoc E = Parser.getTok().getLoc();
3457 if (getParser().ParseExpression(LSBExpr)) {
3458 Error(E, "malformed immediate expression");
3459 return MatchOperand_ParseFail;
3460 }
3461 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3462 if (!CE) {
3463 Error(E, "'lsb' operand must be an immediate");
3464 return MatchOperand_ParseFail;
3465 }
3466
3467 int64_t LSB = CE->getValue();
3468 // The LSB must be in the range [0,31]
3469 if (LSB < 0 || LSB > 31) {
3470 Error(E, "'lsb' operand must be in the range [0,31]");
3471 return MatchOperand_ParseFail;
3472 }
3473 E = Parser.getTok().getLoc();
3474
3475 // Expect another immediate operand.
3476 if (Parser.getTok().isNot(AsmToken::Comma)) {
3477 Error(Parser.getTok().getLoc(), "too few operands");
3478 return MatchOperand_ParseFail;
3479 }
3480 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003481 if (Parser.getTok().isNot(AsmToken::Hash) &&
3482 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003483 Error(Parser.getTok().getLoc(), "'#' expected");
3484 return MatchOperand_ParseFail;
3485 }
3486 Parser.Lex(); // Eat hash token.
3487
3488 const MCExpr *WidthExpr;
3489 if (getParser().ParseExpression(WidthExpr)) {
3490 Error(E, "malformed immediate expression");
3491 return MatchOperand_ParseFail;
3492 }
3493 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3494 if (!CE) {
3495 Error(E, "'width' operand must be an immediate");
3496 return MatchOperand_ParseFail;
3497 }
3498
3499 int64_t Width = CE->getValue();
3500 // The LSB must be in the range [1,32-lsb]
3501 if (Width < 1 || Width > 32 - LSB) {
3502 Error(E, "'width' operand must be in the range [1,32-lsb]");
3503 return MatchOperand_ParseFail;
3504 }
3505 E = Parser.getTok().getLoc();
3506
3507 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3508
3509 return MatchOperand_Success;
3510}
3511
Jim Grosbach7ce05792011-08-03 23:50:40 +00003512ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3513parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3514 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003515 // postidx_reg := '+' register {, shift}
3516 // | '-' register {, shift}
3517 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003518
3519 // This method must return MatchOperand_NoMatch without consuming any tokens
3520 // in the case where there is no match, as other alternatives take other
3521 // parse methods.
3522 AsmToken Tok = Parser.getTok();
3523 SMLoc S = Tok.getLoc();
3524 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003525 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003526 int Reg = -1;
3527 if (Tok.is(AsmToken::Plus)) {
3528 Parser.Lex(); // Eat the '+' token.
3529 haveEaten = true;
3530 } else if (Tok.is(AsmToken::Minus)) {
3531 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003532 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003533 haveEaten = true;
3534 }
3535 if (Parser.getTok().is(AsmToken::Identifier))
3536 Reg = tryParseRegister();
3537 if (Reg == -1) {
3538 if (!haveEaten)
3539 return MatchOperand_NoMatch;
3540 Error(Parser.getTok().getLoc(), "register expected");
3541 return MatchOperand_ParseFail;
3542 }
3543 SMLoc E = Parser.getTok().getLoc();
3544
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003545 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3546 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003547 if (Parser.getTok().is(AsmToken::Comma)) {
3548 Parser.Lex(); // Eat the ','.
3549 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3550 return MatchOperand_ParseFail;
3551 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003552
3553 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3554 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003555
3556 return MatchOperand_Success;
3557}
3558
Jim Grosbach251bf252011-08-10 21:56:18 +00003559ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3560parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3561 // Check for a post-index addressing register operand. Specifically:
3562 // am3offset := '+' register
3563 // | '-' register
3564 // | register
3565 // | # imm
3566 // | # + imm
3567 // | # - imm
3568
3569 // This method must return MatchOperand_NoMatch without consuming any tokens
3570 // in the case where there is no match, as other alternatives take other
3571 // parse methods.
3572 AsmToken Tok = Parser.getTok();
3573 SMLoc S = Tok.getLoc();
3574
3575 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003576 if (Parser.getTok().is(AsmToken::Hash) ||
3577 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003578 Parser.Lex(); // Eat the '#'.
3579 // Explicitly look for a '-', as we need to encode negative zero
3580 // differently.
3581 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3582 const MCExpr *Offset;
3583 if (getParser().ParseExpression(Offset))
3584 return MatchOperand_ParseFail;
3585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3586 if (!CE) {
3587 Error(S, "constant expression expected");
3588 return MatchOperand_ParseFail;
3589 }
3590 SMLoc E = Tok.getLoc();
3591 // Negative zero is encoded as the flag value INT32_MIN.
3592 int32_t Val = CE->getValue();
3593 if (isNegative && Val == 0)
3594 Val = INT32_MIN;
3595
3596 Operands.push_back(
3597 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3598
3599 return MatchOperand_Success;
3600 }
3601
3602
3603 bool haveEaten = false;
3604 bool isAdd = true;
3605 int Reg = -1;
3606 if (Tok.is(AsmToken::Plus)) {
3607 Parser.Lex(); // Eat the '+' token.
3608 haveEaten = true;
3609 } else if (Tok.is(AsmToken::Minus)) {
3610 Parser.Lex(); // Eat the '-' token.
3611 isAdd = false;
3612 haveEaten = true;
3613 }
3614 if (Parser.getTok().is(AsmToken::Identifier))
3615 Reg = tryParseRegister();
3616 if (Reg == -1) {
3617 if (!haveEaten)
3618 return MatchOperand_NoMatch;
3619 Error(Parser.getTok().getLoc(), "register expected");
3620 return MatchOperand_ParseFail;
3621 }
3622 SMLoc E = Parser.getTok().getLoc();
3623
3624 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3625 0, S, E));
3626
3627 return MatchOperand_Success;
3628}
3629
Jim Grosbacha77295d2011-09-08 22:07:06 +00003630/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3631/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3632/// when they refer multiple MIOperands inside a single one.
3633bool ARMAsmParser::
3634cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3635 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3636 // Rt, Rt2
3637 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3638 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3639 // Create a writeback register dummy placeholder.
3640 Inst.addOperand(MCOperand::CreateReg(0));
3641 // addr
3642 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3643 // pred
3644 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3645 return true;
3646}
3647
3648/// cvtT2StrdPre - Convert parsed operands to MCInst.
3649/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3650/// when they refer multiple MIOperands inside a single one.
3651bool ARMAsmParser::
3652cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3653 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3654 // Create a writeback register dummy placeholder.
3655 Inst.addOperand(MCOperand::CreateReg(0));
3656 // Rt, Rt2
3657 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3658 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3659 // addr
3660 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3661 // pred
3662 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3663 return true;
3664}
3665
Jim Grosbacheeec0252011-09-08 00:39:19 +00003666/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3667/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3668/// when they refer multiple MIOperands inside a single one.
3669bool ARMAsmParser::
3670cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3671 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3672 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3673
3674 // Create a writeback register dummy placeholder.
3675 Inst.addOperand(MCOperand::CreateImm(0));
3676
3677 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3678 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3679 return true;
3680}
3681
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003682/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3683/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3684/// when they refer multiple MIOperands inside a single one.
3685bool ARMAsmParser::
3686cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3687 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3688 // Create a writeback register dummy placeholder.
3689 Inst.addOperand(MCOperand::CreateImm(0));
3690 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3691 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3692 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3693 return true;
3694}
3695
Jim Grosbach1355cf12011-07-26 17:10:22 +00003696/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003697/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3698/// when they refer multiple MIOperands inside a single one.
3699bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003700cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003701 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3702 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3703
3704 // Create a writeback register dummy placeholder.
3705 Inst.addOperand(MCOperand::CreateImm(0));
3706
Jim Grosbach7ce05792011-08-03 23:50:40 +00003707 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003708 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3709 return true;
3710}
3711
Owen Anderson9ab0f252011-08-26 20:43:14 +00003712/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3713/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3714/// when they refer multiple MIOperands inside a single one.
3715bool ARMAsmParser::
3716cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3717 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3718 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3719
3720 // Create a writeback register dummy placeholder.
3721 Inst.addOperand(MCOperand::CreateImm(0));
3722
3723 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3724 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3725 return true;
3726}
3727
3728
Jim Grosbach548340c2011-08-11 19:22:40 +00003729/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3730/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3731/// when they refer multiple MIOperands inside a single one.
3732bool ARMAsmParser::
3733cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3734 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3735 // Create a writeback register dummy placeholder.
3736 Inst.addOperand(MCOperand::CreateImm(0));
3737 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3738 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3739 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3740 return true;
3741}
3742
Jim Grosbach1355cf12011-07-26 17:10:22 +00003743/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003744/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3745/// when they refer multiple MIOperands inside a single one.
3746bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003747cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003748 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3749 // Create a writeback register dummy placeholder.
3750 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003751 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3752 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3753 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003754 return true;
3755}
3756
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003757/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3758/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3759/// when they refer multiple MIOperands inside a single one.
3760bool ARMAsmParser::
3761cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3762 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3763 // Create a writeback register dummy placeholder.
3764 Inst.addOperand(MCOperand::CreateImm(0));
3765 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3766 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3767 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3768 return true;
3769}
3770
Jim Grosbach7ce05792011-08-03 23:50:40 +00003771/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3772/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3773/// when they refer multiple MIOperands inside a single one.
3774bool ARMAsmParser::
3775cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3776 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3777 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003778 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003779 // Create a writeback register dummy placeholder.
3780 Inst.addOperand(MCOperand::CreateImm(0));
3781 // addr
3782 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3783 // offset
3784 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3785 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003786 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3787 return true;
3788}
3789
Jim Grosbach7ce05792011-08-03 23:50:40 +00003790/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003791/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3792/// when they refer multiple MIOperands inside a single one.
3793bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003794cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3795 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3796 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003797 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003798 // Create a writeback register dummy placeholder.
3799 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003800 // addr
3801 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3802 // offset
3803 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3804 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003805 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3806 return true;
3807}
3808
Jim Grosbach7ce05792011-08-03 23:50:40 +00003809/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003810/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3811/// when they refer multiple MIOperands inside a single one.
3812bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003813cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3814 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003815 // Create a writeback register dummy placeholder.
3816 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003817 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003818 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003819 // addr
3820 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3821 // offset
3822 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3823 // pred
3824 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3825 return true;
3826}
3827
3828/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3829/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3830/// when they refer multiple MIOperands inside a single one.
3831bool ARMAsmParser::
3832cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3833 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3834 // Create a writeback register dummy placeholder.
3835 Inst.addOperand(MCOperand::CreateImm(0));
3836 // Rt
3837 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3838 // addr
3839 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3840 // offset
3841 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3842 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003843 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3844 return true;
3845}
3846
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003847/// cvtLdrdPre - Convert parsed operands to MCInst.
3848/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3849/// when they refer multiple MIOperands inside a single one.
3850bool ARMAsmParser::
3851cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3852 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3853 // Rt, Rt2
3854 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3855 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3856 // Create a writeback register dummy placeholder.
3857 Inst.addOperand(MCOperand::CreateImm(0));
3858 // addr
3859 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3860 // pred
3861 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3862 return true;
3863}
3864
Jim Grosbach14605d12011-08-11 20:28:23 +00003865/// cvtStrdPre - Convert parsed operands to MCInst.
3866/// 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::
3869cvtStrdPre(MCInst &Inst, unsigned Opcode,
3870 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3871 // Create a writeback register dummy placeholder.
3872 Inst.addOperand(MCOperand::CreateImm(0));
3873 // Rt, Rt2
3874 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3875 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3876 // addr
3877 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3878 // pred
3879 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3880 return true;
3881}
3882
Jim Grosbach623a4542011-08-10 22:42:16 +00003883/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3884/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3885/// when they refer multiple MIOperands inside a single one.
3886bool ARMAsmParser::
3887cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3888 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3889 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3890 // Create a writeback register dummy placeholder.
3891 Inst.addOperand(MCOperand::CreateImm(0));
3892 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3893 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3894 return true;
3895}
3896
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003897/// cvtThumbMultiple- Convert parsed operands to MCInst.
3898/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3899/// when they refer multiple MIOperands inside a single one.
3900bool ARMAsmParser::
3901cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3902 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3903 // The second source operand must be the same register as the destination
3904 // operand.
3905 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003906 (((ARMOperand*)Operands[3])->getReg() !=
3907 ((ARMOperand*)Operands[5])->getReg()) &&
3908 (((ARMOperand*)Operands[3])->getReg() !=
3909 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003910 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003911 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003912 return false;
3913 }
3914 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3915 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003916 // If we have a three-operand form, make sure to set Rn to be the operand
3917 // that isn't the same as Rd.
3918 unsigned RegOp = 4;
3919 if (Operands.size() == 6 &&
3920 ((ARMOperand*)Operands[4])->getReg() ==
3921 ((ARMOperand*)Operands[3])->getReg())
3922 RegOp = 5;
3923 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3924 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003925 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3926
3927 return true;
3928}
Jim Grosbach623a4542011-08-10 22:42:16 +00003929
Jim Grosbach12431322011-10-24 22:16:58 +00003930bool ARMAsmParser::
3931cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3932 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3933 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003934 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003935 // Create a writeback register dummy placeholder.
3936 Inst.addOperand(MCOperand::CreateImm(0));
3937 // Vn
3938 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3939 // pred
3940 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3941 return true;
3942}
3943
3944bool ARMAsmParser::
3945cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3946 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3947 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003948 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003949 // Create a writeback register dummy placeholder.
3950 Inst.addOperand(MCOperand::CreateImm(0));
3951 // Vn
3952 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3953 // Vm
3954 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3955 // pred
3956 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3957 return true;
3958}
3959
Jim Grosbach4334e032011-10-31 21:50:31 +00003960bool ARMAsmParser::
3961cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3962 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3963 // Create a writeback register dummy placeholder.
3964 Inst.addOperand(MCOperand::CreateImm(0));
3965 // Vn
3966 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3967 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003968 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003969 // pred
3970 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3971 return true;
3972}
3973
3974bool ARMAsmParser::
3975cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3976 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3977 // Create a writeback register dummy placeholder.
3978 Inst.addOperand(MCOperand::CreateImm(0));
3979 // Vn
3980 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3981 // Vm
3982 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3983 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003984 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003985 // pred
3986 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3987 return true;
3988}
3989
Bill Wendlinge7176102010-11-06 22:36:58 +00003990/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003991/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003992bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003993parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003994 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003995 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003996 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003997 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003998 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003999
Sean Callanan18b83232010-01-19 21:44:56 +00004000 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004001 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004002 if (BaseRegNum == -1)
4003 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004004
Daniel Dunbar05710932011-01-18 05:34:17 +00004005 // The next token must either be a comma or a closing bracket.
4006 const AsmToken &Tok = Parser.getTok();
4007 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004008 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004009
Jim Grosbach7ce05792011-08-03 23:50:40 +00004010 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004011 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004012 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004013
Jim Grosbach7ce05792011-08-03 23:50:40 +00004014 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004015 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004016
Jim Grosbachfb12f352011-09-19 18:42:21 +00004017 // If there's a pre-indexing writeback marker, '!', just add it as a token
4018 // operand. It's rather odd, but syntactically valid.
4019 if (Parser.getTok().is(AsmToken::Exclaim)) {
4020 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4021 Parser.Lex(); // Eat the '!'.
4022 }
4023
Jim Grosbach7ce05792011-08-03 23:50:40 +00004024 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004025 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004026
Jim Grosbach7ce05792011-08-03 23:50:40 +00004027 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4028 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004029
Jim Grosbach57dcb852011-10-11 17:29:55 +00004030 // If we have a ':', it's an alignment specifier.
4031 if (Parser.getTok().is(AsmToken::Colon)) {
4032 Parser.Lex(); // Eat the ':'.
4033 E = Parser.getTok().getLoc();
4034
4035 const MCExpr *Expr;
4036 if (getParser().ParseExpression(Expr))
4037 return true;
4038
4039 // The expression has to be a constant. Memory references with relocations
4040 // don't come through here, as they use the <label> forms of the relevant
4041 // instructions.
4042 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4043 if (!CE)
4044 return Error (E, "constant expression expected");
4045
4046 unsigned Align = 0;
4047 switch (CE->getValue()) {
4048 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004049 return Error(E,
4050 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4051 case 16: Align = 2; break;
4052 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004053 case 64: Align = 8; break;
4054 case 128: Align = 16; break;
4055 case 256: Align = 32; break;
4056 }
4057
4058 // Now we should have the closing ']'
4059 E = Parser.getTok().getLoc();
4060 if (Parser.getTok().isNot(AsmToken::RBrac))
4061 return Error(E, "']' expected");
4062 Parser.Lex(); // Eat right bracket token.
4063
4064 // Don't worry about range checking the value here. That's handled by
4065 // the is*() predicates.
4066 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4067 ARM_AM::no_shift, 0, Align,
4068 false, S, E));
4069
4070 // If there's a pre-indexing writeback marker, '!', just add it as a token
4071 // operand.
4072 if (Parser.getTok().is(AsmToken::Exclaim)) {
4073 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4074 Parser.Lex(); // Eat the '!'.
4075 }
4076
4077 return false;
4078 }
4079
4080 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004081 // offset. Be friendly and also accept a plain integer (without a leading
4082 // hash) for gas compatibility.
4083 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004084 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004085 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004086 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004087 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004088 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004089
Owen Anderson0da10cf2011-08-29 19:36:44 +00004090 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004091 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004092 if (getParser().ParseExpression(Offset))
4093 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004094
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>(Offset);
4099 if (!CE)
4100 return Error (E, "constant expression expected");
4101
Owen Anderson0da10cf2011-08-29 19:36:44 +00004102 // If the constant was #-0, represent it as INT32_MIN.
4103 int32_t Val = CE->getValue();
4104 if (isNegative && Val == 0)
4105 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4106
Jim Grosbach7ce05792011-08-03 23:50:40 +00004107 // Now we should have the closing ']'
4108 E = Parser.getTok().getLoc();
4109 if (Parser.getTok().isNot(AsmToken::RBrac))
4110 return Error(E, "']' expected");
4111 Parser.Lex(); // Eat right bracket token.
4112
4113 // Don't worry about range checking the value here. That's handled by
4114 // the is*() predicates.
4115 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004116 ARM_AM::no_shift, 0, 0,
4117 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004118
4119 // If there's a pre-indexing writeback marker, '!', just add it as a token
4120 // operand.
4121 if (Parser.getTok().is(AsmToken::Exclaim)) {
4122 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4123 Parser.Lex(); // Eat the '!'.
4124 }
4125
4126 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004127 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004128
4129 // The register offset is optionally preceded by a '+' or '-'
4130 bool isNegative = false;
4131 if (Parser.getTok().is(AsmToken::Minus)) {
4132 isNegative = true;
4133 Parser.Lex(); // Eat the '-'.
4134 } else if (Parser.getTok().is(AsmToken::Plus)) {
4135 // Nothing to do.
4136 Parser.Lex(); // Eat the '+'.
4137 }
4138
4139 E = Parser.getTok().getLoc();
4140 int OffsetRegNum = tryParseRegister();
4141 if (OffsetRegNum == -1)
4142 return Error(E, "register expected");
4143
4144 // If there's a shift operator, handle it.
4145 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004146 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004147 if (Parser.getTok().is(AsmToken::Comma)) {
4148 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004149 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004150 return true;
4151 }
4152
4153 // Now we should have the closing ']'
4154 E = Parser.getTok().getLoc();
4155 if (Parser.getTok().isNot(AsmToken::RBrac))
4156 return Error(E, "']' expected");
4157 Parser.Lex(); // Eat right bracket token.
4158
4159 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004160 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004161 S, E));
4162
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004163 // If there's a pre-indexing writeback marker, '!', just add it as a token
4164 // operand.
4165 if (Parser.getTok().is(AsmToken::Exclaim)) {
4166 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4167 Parser.Lex(); // Eat the '!'.
4168 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004169
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004170 return false;
4171}
4172
Jim Grosbach7ce05792011-08-03 23:50:40 +00004173/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004174/// ( lsl | lsr | asr | ror ) , # shift_amount
4175/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176/// return true if it parses a shift otherwise it returns false.
4177bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4178 unsigned &Amount) {
4179 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004180 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004181 if (Tok.isNot(AsmToken::Identifier))
4182 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004183 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004184 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4185 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004186 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004187 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004188 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004189 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004190 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004191 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004192 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004193 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004194 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004195 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004196 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004197 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004198
Jim Grosbach7ce05792011-08-03 23:50:40 +00004199 // rrx stands alone.
4200 Amount = 0;
4201 if (St != ARM_AM::rrx) {
4202 Loc = Parser.getTok().getLoc();
4203 // A '#' and a shift amount.
4204 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004205 if (HashTok.isNot(AsmToken::Hash) &&
4206 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004207 return Error(HashTok.getLoc(), "'#' expected");
4208 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004209
Jim Grosbach7ce05792011-08-03 23:50:40 +00004210 const MCExpr *Expr;
4211 if (getParser().ParseExpression(Expr))
4212 return true;
4213 // Range check the immediate.
4214 // lsl, ror: 0 <= imm <= 31
4215 // lsr, asr: 0 <= imm <= 32
4216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4217 if (!CE)
4218 return Error(Loc, "shift amount must be an immediate");
4219 int64_t Imm = CE->getValue();
4220 if (Imm < 0 ||
4221 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4222 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4223 return Error(Loc, "immediate shift value out of range");
4224 Amount = Imm;
4225 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004226
4227 return false;
4228}
4229
Jim Grosbach9d390362011-10-03 23:38:36 +00004230/// parseFPImm - A floating point immediate expression operand.
4231ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4232parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4233 SMLoc S = Parser.getTok().getLoc();
4234
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004235 if (Parser.getTok().isNot(AsmToken::Hash) &&
4236 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004237 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004238
4239 // Disambiguate the VMOV forms that can accept an FP immediate.
4240 // vmov.f32 <sreg>, #imm
4241 // vmov.f64 <dreg>, #imm
4242 // vmov.f32 <dreg>, #imm @ vector f32x2
4243 // vmov.f32 <qreg>, #imm @ vector f32x4
4244 //
4245 // There are also the NEON VMOV instructions which expect an
4246 // integer constant. Make sure we don't try to parse an FPImm
4247 // for these:
4248 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4249 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4250 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4251 TyOp->getToken() != ".f64"))
4252 return MatchOperand_NoMatch;
4253
Jim Grosbach9d390362011-10-03 23:38:36 +00004254 Parser.Lex(); // Eat the '#'.
4255
4256 // Handle negation, as that still comes through as a separate token.
4257 bool isNegative = false;
4258 if (Parser.getTok().is(AsmToken::Minus)) {
4259 isNegative = true;
4260 Parser.Lex();
4261 }
4262 const AsmToken &Tok = Parser.getTok();
4263 if (Tok.is(AsmToken::Real)) {
4264 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4265 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4266 // If we had a '-' in front, toggle the sign bit.
4267 IntVal ^= (uint64_t)isNegative << 63;
4268 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4269 Parser.Lex(); // Eat the token.
4270 if (Val == -1) {
4271 TokError("floating point value out of range");
4272 return MatchOperand_ParseFail;
4273 }
4274 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4275 return MatchOperand_Success;
4276 }
4277 if (Tok.is(AsmToken::Integer)) {
4278 int64_t Val = Tok.getIntVal();
4279 Parser.Lex(); // Eat the token.
4280 if (Val > 255 || Val < 0) {
4281 TokError("encoded floating point value out of range");
4282 return MatchOperand_ParseFail;
4283 }
4284 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4285 return MatchOperand_Success;
4286 }
4287
4288 TokError("invalid floating point immediate");
4289 return MatchOperand_ParseFail;
4290}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004291/// Parse a arm instruction operand. For now this parses the operand regardless
4292/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004293bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004294 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004295 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004296
4297 // Check if the current operand has a custom associated parser, if so, try to
4298 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004299 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4300 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004301 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004302 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4303 // there was a match, but an error occurred, in which case, just return that
4304 // the operand parsing failed.
4305 if (ResTy == MatchOperand_ParseFail)
4306 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004307
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004308 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004309 default:
4310 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004311 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004312 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004313 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004314 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004315 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004316 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004317 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004318 else if (Res == -1) // irrecoverable error
4319 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004320 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004321 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4322 S = Parser.getTok().getLoc();
4323 Parser.Lex();
4324 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4325 return false;
4326 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004327
4328 // Fall though for the Identifier case that is not a register or a
4329 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004330 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004331 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004332 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004333 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004334 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004335 // This was not a register so parse other operands that start with an
4336 // identifier (like labels) as expressions and create them as immediates.
4337 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004338 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004339 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004340 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004341 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004342 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4343 return false;
4344 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004345 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004346 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004347 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004348 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004349 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004350 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004351 // #42 -> immediate.
4352 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004353 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004354 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004355 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004356 const MCExpr *ImmVal;
4357 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004358 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004359 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004360 if (CE) {
4361 int32_t Val = CE->getValue();
4362 if (isNegative && Val == 0)
4363 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004364 }
Sean Callanan76264762010-04-02 22:27:05 +00004365 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004366 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4367 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004368 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004369 case AsmToken::Colon: {
4370 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004371 // FIXME: Check it's an expression prefix,
4372 // e.g. (FOO - :lower16:BAR) isn't legal.
4373 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004374 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004375 return true;
4376
Evan Cheng75972122011-01-13 07:58:56 +00004377 const MCExpr *SubExprVal;
4378 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004379 return true;
4380
Evan Cheng75972122011-01-13 07:58:56 +00004381 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4382 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004383 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004384 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004385 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004386 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004387 }
4388}
4389
Jim Grosbach1355cf12011-07-26 17:10:22 +00004390// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004391// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004392bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004393 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004394
4395 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004396 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004397 Parser.Lex(); // Eat ':'
4398
4399 if (getLexer().isNot(AsmToken::Identifier)) {
4400 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4401 return true;
4402 }
4403
4404 StringRef IDVal = Parser.getTok().getIdentifier();
4405 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004406 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004407 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004408 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004409 } else {
4410 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4411 return true;
4412 }
4413 Parser.Lex();
4414
4415 if (getLexer().isNot(AsmToken::Colon)) {
4416 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4417 return true;
4418 }
4419 Parser.Lex(); // Eat the last ':'
4420 return false;
4421}
4422
Daniel Dunbar352e1482011-01-11 15:59:50 +00004423/// \brief Given a mnemonic, split out possible predication code and carry
4424/// setting letters to form a canonical mnemonic and flags.
4425//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004426// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004427// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004428StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004429 unsigned &PredicationCode,
4430 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004431 unsigned &ProcessorIMod,
4432 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004433 PredicationCode = ARMCC::AL;
4434 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004435 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004436
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004437 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004438 //
4439 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004440 if ((Mnemonic == "movs" && isThumb()) ||
4441 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4442 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4443 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4444 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4445 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4446 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004447 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4448 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004449 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004450
Jim Grosbach3f00e312011-07-11 17:09:57 +00004451 // First, split out any predication code. Ignore mnemonics we know aren't
4452 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004453 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004454 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004455 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004456 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004457 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4458 .Case("eq", ARMCC::EQ)
4459 .Case("ne", ARMCC::NE)
4460 .Case("hs", ARMCC::HS)
4461 .Case("cs", ARMCC::HS)
4462 .Case("lo", ARMCC::LO)
4463 .Case("cc", ARMCC::LO)
4464 .Case("mi", ARMCC::MI)
4465 .Case("pl", ARMCC::PL)
4466 .Case("vs", ARMCC::VS)
4467 .Case("vc", ARMCC::VC)
4468 .Case("hi", ARMCC::HI)
4469 .Case("ls", ARMCC::LS)
4470 .Case("ge", ARMCC::GE)
4471 .Case("lt", ARMCC::LT)
4472 .Case("gt", ARMCC::GT)
4473 .Case("le", ARMCC::LE)
4474 .Case("al", ARMCC::AL)
4475 .Default(~0U);
4476 if (CC != ~0U) {
4477 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4478 PredicationCode = CC;
4479 }
Bill Wendling52925b62010-10-29 23:50:21 +00004480 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004481
Daniel Dunbar352e1482011-01-11 15:59:50 +00004482 // Next, determine if we have a carry setting bit. We explicitly ignore all
4483 // the instructions we know end in 's'.
4484 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004485 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004486 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4487 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4488 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004489 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004490 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004491 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004492 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004493 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004494 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4495 CarrySetting = true;
4496 }
4497
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004498 // The "cps" instruction can have a interrupt mode operand which is glued into
4499 // the mnemonic. Check if this is the case, split it and parse the imod op
4500 if (Mnemonic.startswith("cps")) {
4501 // Split out any imod code.
4502 unsigned IMod =
4503 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4504 .Case("ie", ARM_PROC::IE)
4505 .Case("id", ARM_PROC::ID)
4506 .Default(~0U);
4507 if (IMod != ~0U) {
4508 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4509 ProcessorIMod = IMod;
4510 }
4511 }
4512
Jim Grosbach89df9962011-08-26 21:43:41 +00004513 // The "it" instruction has the condition mask on the end of the mnemonic.
4514 if (Mnemonic.startswith("it")) {
4515 ITMask = Mnemonic.slice(2, Mnemonic.size());
4516 Mnemonic = Mnemonic.slice(0, 2);
4517 }
4518
Daniel Dunbar352e1482011-01-11 15:59:50 +00004519 return Mnemonic;
4520}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004521
4522/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4523/// inclusion of carry set or predication code operands.
4524//
4525// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004526void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004527getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004528 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004529 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4530 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004531 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004532 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004533 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004534 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004535 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004536 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004537 Mnemonic == "mla" || Mnemonic == "smlal" ||
4538 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004539 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004540 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004541 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004542
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004543 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4544 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4545 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4546 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004547 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4548 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004549 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004550 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4551 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4552 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004553 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4554 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004555 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004556 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004557 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004558 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004559
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004560 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004561 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004562 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004563 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004564 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004565}
4566
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004567bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4568 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004569 // FIXME: This is all horribly hacky. We really need a better way to deal
4570 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004571
4572 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4573 // another does not. Specifically, the MOVW instruction does not. So we
4574 // special case it here and remove the defaulted (non-setting) cc_out
4575 // operand if that's the instruction we're trying to match.
4576 //
4577 // We do this as post-processing of the explicit operands rather than just
4578 // conditionally adding the cc_out in the first place because we need
4579 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004580 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004581 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4582 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4583 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4584 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004585
4586 // Register-register 'add' for thumb does not have a cc_out operand
4587 // when there are only two register operands.
4588 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4589 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4590 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4591 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4592 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004593 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004594 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4595 // have to check the immediate range here since Thumb2 has a variant
4596 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004597 if (((isThumb() && Mnemonic == "add") ||
4598 (isThumbTwo() && Mnemonic == "sub")) &&
4599 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004600 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4601 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4602 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004603 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4604 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4605 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004606 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004607 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4608 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004609 // selecting via the generic "add" mnemonic, so to know that we
4610 // should remove the cc_out operand, we have to explicitly check that
4611 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004612 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4613 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004614 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4615 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4616 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4617 // Nest conditions rather than one big 'if' statement for readability.
4618 //
4619 // If either register is a high reg, it's either one of the SP
4620 // variants (handled above) or a 32-bit encoding, so we just
4621 // check against T3.
4622 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4623 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4624 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4625 return false;
4626 // If both registers are low, we're in an IT block, and the immediate is
4627 // in range, we should use encoding T1 instead, which has a cc_out.
4628 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004629 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004630 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4631 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4632 return false;
4633
4634 // Otherwise, we use encoding T4, which does not have a cc_out
4635 // operand.
4636 return true;
4637 }
4638
Jim Grosbach64944f42011-09-14 21:00:40 +00004639 // The thumb2 multiply instruction doesn't have a CCOut register, so
4640 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4641 // use the 16-bit encoding or not.
4642 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4643 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4644 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4645 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4646 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4647 // If the registers aren't low regs, the destination reg isn't the
4648 // same as one of the source regs, or the cc_out operand is zero
4649 // outside of an IT block, we have to use the 32-bit encoding, so
4650 // remove the cc_out operand.
4651 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4652 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004653 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004654 !inITBlock() ||
4655 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4656 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4657 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4658 static_cast<ARMOperand*>(Operands[4])->getReg())))
4659 return true;
4660
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004661 // Also check the 'mul' syntax variant that doesn't specify an explicit
4662 // destination register.
4663 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4664 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4665 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4666 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4667 // If the registers aren't low regs or the cc_out operand is zero
4668 // outside of an IT block, we have to use the 32-bit encoding, so
4669 // remove the cc_out operand.
4670 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4671 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4672 !inITBlock()))
4673 return true;
4674
Jim Grosbach64944f42011-09-14 21:00:40 +00004675
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004676
Jim Grosbachf69c8042011-08-24 21:42:27 +00004677 // Register-register 'add/sub' for thumb does not have a cc_out operand
4678 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4679 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4680 // right, this will result in better diagnostics (which operand is off)
4681 // anyway.
4682 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4683 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004684 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4685 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4686 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4687 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004688
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004689 return false;
4690}
4691
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004692static bool isDataTypeToken(StringRef Tok) {
4693 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4694 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4695 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4696 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4697 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4698 Tok == ".f" || Tok == ".d";
4699}
4700
4701// FIXME: This bit should probably be handled via an explicit match class
4702// in the .td files that matches the suffix instead of having it be
4703// a literal string token the way it is now.
4704static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4705 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4706}
4707
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004708static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004709/// Parse an arm instruction mnemonic followed by its operands.
4710bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4711 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004712 // Apply mnemonic aliases before doing anything else, as the destination
4713 // mnemnonic may include suffices and we want to handle them normally.
4714 // The generic tblgen'erated code does this later, at the start of
4715 // MatchInstructionImpl(), but that's too late for aliases that include
4716 // any sort of suffix.
4717 unsigned AvailableFeatures = getAvailableFeatures();
4718 applyMnemonicAliases(Name, AvailableFeatures);
4719
Jim Grosbacha39cda72011-12-14 02:16:11 +00004720 // First check for the ARM-specific .req directive.
4721 if (Parser.getTok().is(AsmToken::Identifier) &&
4722 Parser.getTok().getIdentifier() == ".req") {
4723 parseDirectiveReq(Name, NameLoc);
4724 // We always return 'error' for this, as we're done with this
4725 // statement and don't need to match the 'instruction."
4726 return true;
4727 }
4728
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004729 // Create the leading tokens for the mnemonic, split by '.' characters.
4730 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004731 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004732
Daniel Dunbar352e1482011-01-11 15:59:50 +00004733 // Split out the predication code and carry setting flag from the mnemonic.
4734 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004735 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004736 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004737 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004738 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004739 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004740
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004741 // In Thumb1, only the branch (B) instruction can be predicated.
4742 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4743 Parser.EatToEndOfStatement();
4744 return Error(NameLoc, "conditional execution not supported in Thumb1");
4745 }
4746
Jim Grosbachffa32252011-07-19 19:13:28 +00004747 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4748
Jim Grosbach89df9962011-08-26 21:43:41 +00004749 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4750 // is the mask as it will be for the IT encoding if the conditional
4751 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4752 // where the conditional bit0 is zero, the instruction post-processing
4753 // will adjust the mask accordingly.
4754 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004755 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4756 if (ITMask.size() > 3) {
4757 Parser.EatToEndOfStatement();
4758 return Error(Loc, "too many conditions on IT instruction");
4759 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004760 unsigned Mask = 8;
4761 for (unsigned i = ITMask.size(); i != 0; --i) {
4762 char pos = ITMask[i - 1];
4763 if (pos != 't' && pos != 'e') {
4764 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004765 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004766 }
4767 Mask >>= 1;
4768 if (ITMask[i - 1] == 't')
4769 Mask |= 8;
4770 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004771 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004772 }
4773
Jim Grosbachffa32252011-07-19 19:13:28 +00004774 // FIXME: This is all a pretty gross hack. We should automatically handle
4775 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004776
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004777 // Next, add the CCOut and ConditionCode operands, if needed.
4778 //
4779 // For mnemonics which can ever incorporate a carry setting bit or predication
4780 // code, our matching model involves us always generating CCOut and
4781 // ConditionCode operands to match the mnemonic "as written" and then we let
4782 // the matcher deal with finding the right instruction or generating an
4783 // appropriate error.
4784 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004785 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004786
Jim Grosbach33c16a22011-07-14 22:04:21 +00004787 // If we had a carry-set on an instruction that can't do that, issue an
4788 // error.
4789 if (!CanAcceptCarrySet && CarrySetting) {
4790 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004791 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004792 "' can not set flags, but 's' suffix specified");
4793 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004794 // If we had a predication code on an instruction that can't do that, issue an
4795 // error.
4796 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4797 Parser.EatToEndOfStatement();
4798 return Error(NameLoc, "instruction '" + Mnemonic +
4799 "' is not predicable, but condition code specified");
4800 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004801
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004802 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004803 if (CanAcceptCarrySet) {
4804 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004805 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004806 Loc));
4807 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004808
4809 // Add the predication code operand, if necessary.
4810 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004811 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4812 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004813 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004814 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004815 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004816
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004817 // Add the processor imod operand, if necessary.
4818 if (ProcessorIMod) {
4819 Operands.push_back(ARMOperand::CreateImm(
4820 MCConstantExpr::Create(ProcessorIMod, getContext()),
4821 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004822 }
4823
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004824 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004825 while (Next != StringRef::npos) {
4826 Start = Next;
4827 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004828 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004829
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004830 // Some NEON instructions have an optional datatype suffix that is
4831 // completely ignored. Check for that.
4832 if (isDataTypeToken(ExtraToken) &&
4833 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4834 continue;
4835
Jim Grosbach81d2e392011-09-07 16:06:04 +00004836 if (ExtraToken != ".n") {
4837 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4838 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4839 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004840 }
4841
4842 // Read the remaining operands.
4843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004844 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004845 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004846 Parser.EatToEndOfStatement();
4847 return true;
4848 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004849
4850 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004851 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004852
4853 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004854 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004855 Parser.EatToEndOfStatement();
4856 return true;
4857 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004858 }
4859 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004860
Chris Lattnercbf8a982010-09-11 16:18:25 +00004861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004862 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004863 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004864 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004865 }
Bill Wendling146018f2010-11-06 21:42:12 +00004866
Chris Lattner34e53142010-09-08 05:10:46 +00004867 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004868
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004869 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4870 // do and don't have a cc_out optional-def operand. With some spot-checks
4871 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004872 // parse and adjust accordingly before actually matching. We shouldn't ever
4873 // try to remove a cc_out operand that was explicitly set on the the
4874 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4875 // table driven matcher doesn't fit well with the ARM instruction set.
4876 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004877 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4878 Operands.erase(Operands.begin() + 1);
4879 delete Op;
4880 }
4881
Jim Grosbachcf121c32011-07-28 21:57:55 +00004882 // ARM mode 'blx' need special handling, as the register operand version
4883 // is predicable, but the label operand version is not. So, we can't rely
4884 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004885 // a k_CondCode operand in the list. If we're trying to match the label
4886 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004887 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4888 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4889 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4890 Operands.erase(Operands.begin() + 1);
4891 delete Op;
4892 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004893
4894 // The vector-compare-to-zero instructions have a literal token "#0" at
4895 // the end that comes to here as an immediate operand. Convert it to a
4896 // token to play nicely with the matcher.
4897 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4898 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4899 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4900 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4901 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4902 if (CE && CE->getValue() == 0) {
4903 Operands.erase(Operands.begin() + 5);
4904 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4905 delete Op;
4906 }
4907 }
Jim Grosbach68259142011-10-03 22:30:24 +00004908 // VCMP{E} does the same thing, but with a different operand count.
4909 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4910 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4911 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4912 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4913 if (CE && CE->getValue() == 0) {
4914 Operands.erase(Operands.begin() + 4);
4915 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4916 delete Op;
4917 }
4918 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004919 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004920 // end. Convert it to a token here. Take care not to convert those
4921 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004922 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004923 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4924 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004925 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4926 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004928 if (CE && CE->getValue() == 0 &&
4929 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004930 // The cc_out operand matches the IT block.
4931 ((inITBlock() != CarrySetting) &&
4932 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004933 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004934 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004935 Operands.erase(Operands.begin() + 5);
4936 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4937 delete Op;
4938 }
4939 }
4940
Chris Lattner98986712010-01-14 22:21:20 +00004941 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004942}
4943
Jim Grosbach189610f2011-07-26 18:25:39 +00004944// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004945
4946// return 'true' if register list contains non-low GPR registers,
4947// 'false' otherwise. If Reg is in the register list or is HiReg, set
4948// 'containsReg' to true.
4949static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4950 unsigned HiReg, bool &containsReg) {
4951 containsReg = false;
4952 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4953 unsigned OpReg = Inst.getOperand(i).getReg();
4954 if (OpReg == Reg)
4955 containsReg = true;
4956 // Anything other than a low register isn't legal here.
4957 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4958 return true;
4959 }
4960 return false;
4961}
4962
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004963// Check if the specified regisgter is in the register list of the inst,
4964// starting at the indicated operand number.
4965static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4966 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4967 unsigned OpReg = Inst.getOperand(i).getReg();
4968 if (OpReg == Reg)
4969 return true;
4970 }
4971 return false;
4972}
4973
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004974// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4975// the ARMInsts array) instead. Getting that here requires awkward
4976// API changes, though. Better way?
4977namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004978extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004979}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004980static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004981 return ARMInsts[Opcode];
4982}
4983
Jim Grosbach189610f2011-07-26 18:25:39 +00004984// FIXME: We would really like to be able to tablegen'erate this.
4985bool ARMAsmParser::
4986validateInstruction(MCInst &Inst,
4987 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004988 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004989 SMLoc Loc = Operands[0]->getStartLoc();
4990 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004991 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4992 // being allowed in IT blocks, but not being predicable. It just always
4993 // executes.
4994 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004995 unsigned bit = 1;
4996 if (ITState.FirstCond)
4997 ITState.FirstCond = false;
4998 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004999 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005000 // The instruction must be predicable.
5001 if (!MCID.isPredicable())
5002 return Error(Loc, "instructions in IT block must be predicable");
5003 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5004 unsigned ITCond = bit ? ITState.Cond :
5005 ARMCC::getOppositeCondition(ITState.Cond);
5006 if (Cond != ITCond) {
5007 // Find the condition code Operand to get its SMLoc information.
5008 SMLoc CondLoc;
5009 for (unsigned i = 1; i < Operands.size(); ++i)
5010 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5011 CondLoc = Operands[i]->getStartLoc();
5012 return Error(CondLoc, "incorrect condition in IT block; got '" +
5013 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5014 "', but expected '" +
5015 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5016 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005017 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005018 } else if (isThumbTwo() && MCID.isPredicable() &&
5019 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005020 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5021 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005022 return Error(Loc, "predicated instructions must be in IT block");
5023
Jim Grosbach189610f2011-07-26 18:25:39 +00005024 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005025 case ARM::LDRD:
5026 case ARM::LDRD_PRE:
5027 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005028 case ARM::LDREXD: {
5029 // Rt2 must be Rt + 1.
5030 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5031 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5032 if (Rt2 != Rt + 1)
5033 return Error(Operands[3]->getStartLoc(),
5034 "destination operands must be sequential");
5035 return false;
5036 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005037 case ARM::STRD: {
5038 // Rt2 must be Rt + 1.
5039 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5040 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5041 if (Rt2 != Rt + 1)
5042 return Error(Operands[3]->getStartLoc(),
5043 "source operands must be sequential");
5044 return false;
5045 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005046 case ARM::STRD_PRE:
5047 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005048 case ARM::STREXD: {
5049 // Rt2 must be Rt + 1.
5050 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5051 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5052 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005053 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005054 "source operands must be sequential");
5055 return false;
5056 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005057 case ARM::SBFX:
5058 case ARM::UBFX: {
5059 // width must be in range [1, 32-lsb]
5060 unsigned lsb = Inst.getOperand(2).getImm();
5061 unsigned widthm1 = Inst.getOperand(3).getImm();
5062 if (widthm1 >= 32 - lsb)
5063 return Error(Operands[5]->getStartLoc(),
5064 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005065 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005066 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005067 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005068 // If we're parsing Thumb2, the .w variant is available and handles
5069 // most cases that are normally illegal for a Thumb1 LDM
5070 // instruction. We'll make the transformation in processInstruction()
5071 // if necessary.
5072 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005073 // Thumb LDM instructions are writeback iff the base register is not
5074 // in the register list.
5075 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005076 bool hasWritebackToken =
5077 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5078 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005079 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005080 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005081 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5082 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005083 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005084 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005085 return Error(Operands[2]->getStartLoc(),
5086 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005087 // If we should not have writeback, there must not be a '!'. This is
5088 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005089 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005090 return Error(Operands[3]->getStartLoc(),
5091 "writeback operator '!' not allowed when base register "
5092 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005093
5094 break;
5095 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005096 case ARM::t2LDMIA_UPD: {
5097 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5098 return Error(Operands[4]->getStartLoc(),
5099 "writeback operator '!' not allowed when base register "
5100 "in register list");
5101 break;
5102 }
Jim Grosbach54026372011-11-10 23:17:11 +00005103 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5104 // so only issue a diagnostic for thumb1. The instructions will be
5105 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005106 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005107 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005108 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5109 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005110 return Error(Operands[2]->getStartLoc(),
5111 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005112 break;
5113 }
5114 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005115 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005116 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5117 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005118 return Error(Operands[2]->getStartLoc(),
5119 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005120 break;
5121 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005122 case ARM::tSTMIA_UPD: {
5123 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005124 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005125 return Error(Operands[4]->getStartLoc(),
5126 "registers must be in range r0-r7");
5127 break;
5128 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005129 }
5130
5131 return false;
5132}
5133
Jim Grosbach5b484312011-12-20 20:46:29 +00005134static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005135 switch(Opc) {
5136 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005137 // VST1LN
5138 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5139 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5140 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005141 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005142 return ARM::VST1LNd8_UPD;
5143 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5144 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5145 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005146 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005147 return ARM::VST1LNd16_UPD;
5148 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5149 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5150 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005151 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005152 return ARM::VST1LNd32_UPD;
5153 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5154 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5155 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005156 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005157 return ARM::VST1LNd8_UPD;
5158 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5159 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5160 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005161 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005162 return ARM::VST1LNd16_UPD;
5163 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5164 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5165 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005166 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005167 return ARM::VST1LNd32_UPD;
5168 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5169 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5170 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005171 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005172 return ARM::VST1LNd8;
5173 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5174 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5175 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005176 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005177 return ARM::VST1LNd16;
5178 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5179 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5180 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005181 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005182 return ARM::VST1LNd32;
5183
5184 // VST2LN
5185 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5186 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5187 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005188 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005189 return ARM::VST2LNd8_UPD;
5190 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5191 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5192 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005193 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005194 return ARM::VST2LNd16_UPD;
5195 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5196 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5197 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005198 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005199 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005200 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5201 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5202 case ARM::VST2LNqWB_fixed_Asm_U16:
5203 Spacing = 2;
5204 return ARM::VST2LNq16_UPD;
5205 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5206 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5207 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5208 Spacing = 2;
5209 return ARM::VST2LNq32_UPD;
5210
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005211 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5212 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5213 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005214 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005215 return ARM::VST2LNd8_UPD;
5216 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5217 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5218 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005219 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005220 return ARM::VST2LNd16_UPD;
5221 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5222 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5223 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005224 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005225 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005226 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5227 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5228 case ARM::VST2LNqWB_register_Asm_U16:
5229 Spacing = 2;
5230 return ARM::VST2LNq16_UPD;
5231 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5232 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5233 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5234 Spacing = 2;
5235 return ARM::VST2LNq32_UPD;
5236
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005237 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5238 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5239 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005240 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005241 return ARM::VST2LNd8;
5242 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5243 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5244 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005245 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005246 return ARM::VST2LNd16;
5247 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5248 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5249 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005250 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005251 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005252 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5253 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5254 case ARM::VST2LNqAsm_U16:
5255 Spacing = 2;
5256 return ARM::VST2LNq16;
5257 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5258 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5259 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5260 Spacing = 2;
5261 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005262 }
5263}
5264
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005265static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005266 switch(Opc) {
5267 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005268 // VLD1LN
5269 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5270 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5271 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005272 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005273 return ARM::VLD1LNd8_UPD;
5274 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5275 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5276 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005277 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005278 return ARM::VLD1LNd16_UPD;
5279 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5280 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5281 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005282 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005283 return ARM::VLD1LNd32_UPD;
5284 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5285 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5286 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005287 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005288 return ARM::VLD1LNd8_UPD;
5289 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5290 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5291 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005292 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005293 return ARM::VLD1LNd16_UPD;
5294 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5295 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5296 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005297 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005298 return ARM::VLD1LNd32_UPD;
5299 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5300 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5301 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005302 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005303 return ARM::VLD1LNd8;
5304 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5305 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5306 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005307 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005308 return ARM::VLD1LNd16;
5309 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5310 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5311 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005312 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005313 return ARM::VLD1LNd32;
5314
5315 // VLD2LN
5316 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5317 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5318 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005319 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005320 return ARM::VLD2LNd8_UPD;
5321 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5322 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5323 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005324 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005325 return ARM::VLD2LNd16_UPD;
5326 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5327 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5328 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005329 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005330 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005331 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5332 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5333 case ARM::VLD2LNqWB_fixed_Asm_U16:
5334 Spacing = 1;
5335 return ARM::VLD2LNq16_UPD;
5336 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5337 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5338 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5339 Spacing = 2;
5340 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005341 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5342 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5343 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005344 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005345 return ARM::VLD2LNd8_UPD;
5346 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5347 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5348 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005349 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005350 return ARM::VLD2LNd16_UPD;
5351 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5352 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5353 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005354 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005355 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005356 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5357 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5358 case ARM::VLD2LNqWB_register_Asm_U16:
5359 Spacing = 2;
5360 return ARM::VLD2LNq16_UPD;
5361 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5362 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5363 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5364 Spacing = 2;
5365 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005366 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5367 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5368 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005369 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005370 return ARM::VLD2LNd8;
5371 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5372 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5373 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005374 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005375 return ARM::VLD2LNd16;
5376 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5377 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5378 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005379 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005380 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005381 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5382 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5383 case ARM::VLD2LNqAsm_U16:
5384 Spacing = 2;
5385 return ARM::VLD2LNq16;
5386 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5387 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5388 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5389 Spacing = 2;
5390 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005391 }
5392}
5393
Jim Grosbach83ec8772011-11-10 23:42:14 +00005394bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005395processInstruction(MCInst &Inst,
5396 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5397 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005398 // Handle NEON VST complex aliases.
5399 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5400 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5401 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5402 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5403 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5404 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5405 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5406 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005407 MCInst TmpInst;
5408 // Shuffle the operands around so the lane index operand is in the
5409 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005410 unsigned Spacing;
5411 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005412 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5413 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5414 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5415 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5416 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5417 TmpInst.addOperand(Inst.getOperand(1)); // lane
5418 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5419 TmpInst.addOperand(Inst.getOperand(6));
5420 Inst = TmpInst;
5421 return true;
5422 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005423
Jim Grosbach5b484312011-12-20 20:46:29 +00005424 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5425 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5426 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005427 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5428 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005429 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005430 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005431 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5432 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5433 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5434 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5435 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5436 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5437 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005438 MCInst TmpInst;
5439 // Shuffle the operands around so the lane index operand is in the
5440 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005441 unsigned Spacing;
5442 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005443 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5444 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5445 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5446 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5447 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005448 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5449 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005450 TmpInst.addOperand(Inst.getOperand(1)); // lane
5451 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5452 TmpInst.addOperand(Inst.getOperand(6));
5453 Inst = TmpInst;
5454 return true;
5455 }
5456 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5457 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5458 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5459 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5460 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5461 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5462 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5463 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005464 MCInst TmpInst;
5465 // Shuffle the operands around so the lane index operand is in the
5466 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005467 unsigned Spacing;
5468 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005469 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5470 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5471 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5472 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5473 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5474 TmpInst.addOperand(Inst.getOperand(1)); // lane
5475 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5476 TmpInst.addOperand(Inst.getOperand(5));
5477 Inst = TmpInst;
5478 return true;
5479 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005480
Jim Grosbach5b484312011-12-20 20:46:29 +00005481 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5482 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5483 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005484 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5485 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005486 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005487 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005488 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5489 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5490 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5491 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5492 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5493 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5494 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005495 MCInst TmpInst;
5496 // Shuffle the operands around so the lane index operand is in the
5497 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005498 unsigned Spacing;
5499 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005500 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5501 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5502 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5503 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5504 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005505 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5506 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005507 TmpInst.addOperand(Inst.getOperand(1)); // lane
5508 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5509 TmpInst.addOperand(Inst.getOperand(5));
5510 Inst = TmpInst;
5511 return true;
5512 }
5513 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5514 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5515 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5516 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5517 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005518 case ARM::VST1LNdAsm_U32: {
5519 MCInst TmpInst;
5520 // Shuffle the operands around so the lane index operand is in the
5521 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005522 unsigned Spacing;
5523 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005524 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5525 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5526 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5527 TmpInst.addOperand(Inst.getOperand(1)); // lane
5528 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5529 TmpInst.addOperand(Inst.getOperand(5));
5530 Inst = TmpInst;
5531 return true;
5532 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005533
Jim Grosbach5b484312011-12-20 20:46:29 +00005534 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5535 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005536 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005537 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005538 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005539 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5540 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5541 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5542 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005543 MCInst TmpInst;
5544 // Shuffle the operands around so the lane index operand is in the
5545 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005546 unsigned Spacing;
5547 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005548 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5549 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5550 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005551 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5552 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005553 TmpInst.addOperand(Inst.getOperand(1)); // lane
5554 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5555 TmpInst.addOperand(Inst.getOperand(5));
5556 Inst = TmpInst;
5557 return true;
5558 }
5559 // Handle NEON VLD complex aliases.
5560 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5561 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5562 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5563 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5564 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5565 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5566 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5567 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005568 MCInst TmpInst;
5569 // Shuffle the operands around so the lane index operand is in the
5570 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005571 unsigned Spacing;
5572 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005573 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5574 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5575 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5576 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5577 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5578 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5579 TmpInst.addOperand(Inst.getOperand(1)); // lane
5580 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5581 TmpInst.addOperand(Inst.getOperand(6));
5582 Inst = TmpInst;
5583 return true;
5584 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005585
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005586 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5587 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5588 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005589 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5590 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005591 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005592 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005593 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005594 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5595 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5596 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5597 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5598 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5599 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005600 MCInst TmpInst;
5601 // Shuffle the operands around so the lane index operand is in the
5602 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005603 unsigned Spacing;
5604 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005605 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005606 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5607 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005608 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5609 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5610 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5611 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5612 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005613 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5614 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005615 TmpInst.addOperand(Inst.getOperand(1)); // lane
5616 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5617 TmpInst.addOperand(Inst.getOperand(6));
5618 Inst = TmpInst;
5619 return true;
5620 }
5621
5622 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5623 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5624 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5625 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5626 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5627 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5628 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5629 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005630 MCInst TmpInst;
5631 // Shuffle the operands around so the lane index operand is in the
5632 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005633 unsigned Spacing;
5634 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005635 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5636 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5637 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5638 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5639 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5640 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5641 TmpInst.addOperand(Inst.getOperand(1)); // lane
5642 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5643 TmpInst.addOperand(Inst.getOperand(5));
5644 Inst = TmpInst;
5645 return true;
5646 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005647
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005648 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5649 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5650 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005651 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5652 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005653 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005654 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005655 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005656 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5657 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5658 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5659 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5660 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5661 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005662 MCInst TmpInst;
5663 // Shuffle the operands around so the lane index operand is in the
5664 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005665 unsigned Spacing;
5666 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005667 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005668 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5669 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005670 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5671 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5672 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5673 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5674 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005675 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5676 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005677 TmpInst.addOperand(Inst.getOperand(1)); // lane
5678 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5679 TmpInst.addOperand(Inst.getOperand(5));
5680 Inst = TmpInst;
5681 return true;
5682 }
5683
Jim Grosbach5b484312011-12-20 20:46:29 +00005684 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5685 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005686 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005687 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005688 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005689 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005690 MCInst TmpInst;
5691 // Shuffle the operands around so the lane index operand is in the
5692 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005693 unsigned Spacing;
5694 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005695 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5696 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5697 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5698 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5699 TmpInst.addOperand(Inst.getOperand(1)); // lane
5700 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5701 TmpInst.addOperand(Inst.getOperand(5));
5702 Inst = TmpInst;
5703 return true;
5704 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005705
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005706 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5707 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005708 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005709 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005710 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005711 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5712 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5713 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5714 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5715 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005716 MCInst TmpInst;
5717 // Shuffle the operands around so the lane index operand is in the
5718 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005719 unsigned Spacing;
5720 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005721 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005722 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5723 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005724 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5725 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5726 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005727 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5728 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005729 TmpInst.addOperand(Inst.getOperand(1)); // lane
5730 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5731 TmpInst.addOperand(Inst.getOperand(5));
5732 Inst = TmpInst;
5733 return true;
5734 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005735 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00005736 case ARM::t2MOVsr:
5737 case ARM::t2MOVSsr: {
5738 // Which instruction to expand to depends on the CCOut operand and
5739 // whether we're in an IT block if the register operands are low
5740 // registers.
5741 bool isNarrow = false;
5742 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5743 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5744 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5745 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5746 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5747 isNarrow = true;
5748 MCInst TmpInst;
5749 unsigned newOpc;
5750 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5751 default: llvm_unreachable("unexpected opcode!");
5752 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5753 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5754 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5755 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5756 }
5757 TmpInst.setOpcode(newOpc);
5758 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5759 if (isNarrow)
5760 TmpInst.addOperand(MCOperand::CreateReg(
5761 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5762 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5763 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5764 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5765 TmpInst.addOperand(Inst.getOperand(5));
5766 if (!isNarrow)
5767 TmpInst.addOperand(MCOperand::CreateReg(
5768 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5769 Inst = TmpInst;
5770 return true;
5771 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005772 case ARM::t2MOVsi:
5773 case ARM::t2MOVSsi: {
5774 // Which instruction to expand to depends on the CCOut operand and
5775 // whether we're in an IT block if the register operands are low
5776 // registers.
5777 bool isNarrow = false;
5778 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5779 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5780 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5781 isNarrow = true;
5782 MCInst TmpInst;
5783 unsigned newOpc;
5784 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5785 default: llvm_unreachable("unexpected opcode!");
5786 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5787 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5788 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5789 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00005790 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00005791 }
5792 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5793 if (Ammount == 32) Ammount = 0;
5794 TmpInst.setOpcode(newOpc);
5795 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5796 if (isNarrow)
5797 TmpInst.addOperand(MCOperand::CreateReg(
5798 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5799 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00005800 if (newOpc != ARM::t2RRX)
5801 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00005802 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5803 TmpInst.addOperand(Inst.getOperand(4));
5804 if (!isNarrow)
5805 TmpInst.addOperand(MCOperand::CreateReg(
5806 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5807 Inst = TmpInst;
5808 return true;
5809 }
5810 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005811 case ARM::ASRr:
5812 case ARM::LSRr:
5813 case ARM::LSLr:
5814 case ARM::RORr: {
5815 ARM_AM::ShiftOpc ShiftTy;
5816 switch(Inst.getOpcode()) {
5817 default: llvm_unreachable("unexpected opcode!");
5818 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5819 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5820 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5821 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5822 }
Jim Grosbach23f22072011-11-16 18:31:45 +00005823 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5824 MCInst TmpInst;
5825 TmpInst.setOpcode(ARM::MOVsr);
5826 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5827 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5828 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5829 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5830 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5831 TmpInst.addOperand(Inst.getOperand(4));
5832 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5833 Inst = TmpInst;
5834 return true;
5835 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005836 case ARM::ASRi:
5837 case ARM::LSRi:
5838 case ARM::LSLi:
5839 case ARM::RORi: {
5840 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005841 switch(Inst.getOpcode()) {
5842 default: llvm_unreachable("unexpected opcode!");
5843 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5844 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5845 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5846 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5847 }
5848 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005849 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005850 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5851 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005852 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005853 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005854 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5855 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005856 if (Opc == ARM::MOVsi)
5857 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005858 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5859 TmpInst.addOperand(Inst.getOperand(4));
5860 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5861 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005862 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005863 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005864 case ARM::RRXi: {
5865 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5866 MCInst TmpInst;
5867 TmpInst.setOpcode(ARM::MOVsi);
5868 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5869 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5870 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5871 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5872 TmpInst.addOperand(Inst.getOperand(3));
5873 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5874 Inst = TmpInst;
5875 return true;
5876 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005877 case ARM::t2LDMIA_UPD: {
5878 // If this is a load of a single register, then we should use
5879 // a post-indexed LDR instruction instead, per the ARM ARM.
5880 if (Inst.getNumOperands() != 5)
5881 return false;
5882 MCInst TmpInst;
5883 TmpInst.setOpcode(ARM::t2LDR_POST);
5884 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5885 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5886 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5887 TmpInst.addOperand(MCOperand::CreateImm(4));
5888 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5889 TmpInst.addOperand(Inst.getOperand(3));
5890 Inst = TmpInst;
5891 return true;
5892 }
5893 case ARM::t2STMDB_UPD: {
5894 // If this is a store of a single register, then we should use
5895 // a pre-indexed STR instruction instead, per the ARM ARM.
5896 if (Inst.getNumOperands() != 5)
5897 return false;
5898 MCInst TmpInst;
5899 TmpInst.setOpcode(ARM::t2STR_PRE);
5900 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5901 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5902 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5903 TmpInst.addOperand(MCOperand::CreateImm(-4));
5904 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5905 TmpInst.addOperand(Inst.getOperand(3));
5906 Inst = TmpInst;
5907 return true;
5908 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005909 case ARM::LDMIA_UPD:
5910 // If this is a load of a single register via a 'pop', then we should use
5911 // a post-indexed LDR instruction instead, per the ARM ARM.
5912 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5913 Inst.getNumOperands() == 5) {
5914 MCInst TmpInst;
5915 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5916 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5917 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5918 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5919 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5920 TmpInst.addOperand(MCOperand::CreateImm(4));
5921 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5922 TmpInst.addOperand(Inst.getOperand(3));
5923 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005924 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005925 }
5926 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005927 case ARM::STMDB_UPD:
5928 // If this is a store of a single register via a 'push', then we should use
5929 // a pre-indexed STR instruction instead, per the ARM ARM.
5930 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5931 Inst.getNumOperands() == 5) {
5932 MCInst TmpInst;
5933 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5934 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5935 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5936 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5937 TmpInst.addOperand(MCOperand::CreateImm(-4));
5938 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5939 TmpInst.addOperand(Inst.getOperand(3));
5940 Inst = TmpInst;
5941 }
5942 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005943 case ARM::t2ADDri12:
5944 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5945 // mnemonic was used (not "addw"), encoding T3 is preferred.
5946 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5947 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5948 break;
5949 Inst.setOpcode(ARM::t2ADDri);
5950 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5951 break;
5952 case ARM::t2SUBri12:
5953 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5954 // mnemonic was used (not "subw"), encoding T3 is preferred.
5955 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5956 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5957 break;
5958 Inst.setOpcode(ARM::t2SUBri);
5959 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5960 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005961 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005962 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5963 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5964 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5965 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005966 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005967 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005968 return true;
5969 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005970 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005971 case ARM::tSUBi8:
5972 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5973 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5974 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5975 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005976 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005977 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005978 return true;
5979 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005980 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005981 case ARM::t2ADDrr: {
5982 // If the destination and first source operand are the same, and
5983 // there's no setting of the flags, use encoding T2 instead of T3.
5984 // Note that this is only for ADD, not SUB. This mirrors the system
5985 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5986 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5987 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005988 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5989 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005990 break;
5991 MCInst TmpInst;
5992 TmpInst.setOpcode(ARM::tADDhirr);
5993 TmpInst.addOperand(Inst.getOperand(0));
5994 TmpInst.addOperand(Inst.getOperand(0));
5995 TmpInst.addOperand(Inst.getOperand(2));
5996 TmpInst.addOperand(Inst.getOperand(3));
5997 TmpInst.addOperand(Inst.getOperand(4));
5998 Inst = TmpInst;
5999 return true;
6000 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006001 case ARM::tB:
6002 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006003 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006004 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006005 return true;
6006 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006007 break;
6008 case ARM::t2B:
6009 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006010 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006011 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006012 return true;
6013 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00006014 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00006015 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00006016 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006017 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00006018 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006019 return true;
6020 }
Jim Grosbachc0755102011-08-31 21:17:31 +00006021 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00006022 case ARM::tBcc:
6023 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00006024 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00006025 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006026 return true;
6027 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006028 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006029 case ARM::tLDMIA: {
6030 // If the register list contains any high registers, or if the writeback
6031 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6032 // instead if we're in Thumb2. Otherwise, this should have generated
6033 // an error in validateInstruction().
6034 unsigned Rn = Inst.getOperand(0).getReg();
6035 bool hasWritebackToken =
6036 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6037 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6038 bool listContainsBase;
6039 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6040 (!listContainsBase && !hasWritebackToken) ||
6041 (listContainsBase && hasWritebackToken)) {
6042 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6043 assert (isThumbTwo());
6044 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6045 // If we're switching to the updating version, we need to insert
6046 // the writeback tied operand.
6047 if (hasWritebackToken)
6048 Inst.insert(Inst.begin(),
6049 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006050 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006051 }
6052 break;
6053 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006054 case ARM::tSTMIA_UPD: {
6055 // If the register list contains any high registers, we need to use
6056 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6057 // should have generated an error in validateInstruction().
6058 unsigned Rn = Inst.getOperand(0).getReg();
6059 bool listContainsBase;
6060 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6061 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6062 assert (isThumbTwo());
6063 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006064 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006065 }
6066 break;
6067 }
Jim Grosbach54026372011-11-10 23:17:11 +00006068 case ARM::tPOP: {
6069 bool listContainsBase;
6070 // If the register list contains any high registers, we need to use
6071 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6072 // should have generated an error in validateInstruction().
6073 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006074 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006075 assert (isThumbTwo());
6076 Inst.setOpcode(ARM::t2LDMIA_UPD);
6077 // Add the base register and writeback operands.
6078 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6079 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006080 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006081 }
6082 case ARM::tPUSH: {
6083 bool listContainsBase;
6084 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006085 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006086 assert (isThumbTwo());
6087 Inst.setOpcode(ARM::t2STMDB_UPD);
6088 // Add the base register and writeback operands.
6089 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6090 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006091 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006092 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006093 case ARM::t2MOVi: {
6094 // If we can use the 16-bit encoding and the user didn't explicitly
6095 // request the 32-bit variant, transform it here.
6096 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6097 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006098 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6099 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6100 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006101 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6102 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6103 // The operands aren't in the same order for tMOVi8...
6104 MCInst TmpInst;
6105 TmpInst.setOpcode(ARM::tMOVi8);
6106 TmpInst.addOperand(Inst.getOperand(0));
6107 TmpInst.addOperand(Inst.getOperand(4));
6108 TmpInst.addOperand(Inst.getOperand(1));
6109 TmpInst.addOperand(Inst.getOperand(2));
6110 TmpInst.addOperand(Inst.getOperand(3));
6111 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006112 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006113 }
6114 break;
6115 }
6116 case ARM::t2MOVr: {
6117 // If we can use the 16-bit encoding and the user didn't explicitly
6118 // request the 32-bit variant, transform it here.
6119 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6120 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6121 Inst.getOperand(2).getImm() == ARMCC::AL &&
6122 Inst.getOperand(4).getReg() == ARM::CPSR &&
6123 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6124 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6125 // The operands aren't the same for tMOV[S]r... (no cc_out)
6126 MCInst TmpInst;
6127 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6128 TmpInst.addOperand(Inst.getOperand(0));
6129 TmpInst.addOperand(Inst.getOperand(1));
6130 TmpInst.addOperand(Inst.getOperand(2));
6131 TmpInst.addOperand(Inst.getOperand(3));
6132 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006133 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006134 }
6135 break;
6136 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006137 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006138 case ARM::t2SXTB:
6139 case ARM::t2UXTH:
6140 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006141 // If we can use the 16-bit encoding and the user didn't explicitly
6142 // request the 32-bit variant, transform it here.
6143 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6144 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6145 Inst.getOperand(2).getImm() == 0 &&
6146 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6147 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006148 unsigned NewOpc;
6149 switch (Inst.getOpcode()) {
6150 default: llvm_unreachable("Illegal opcode!");
6151 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6152 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6153 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6154 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6155 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006156 // The operands aren't the same for thumb1 (no rotate operand).
6157 MCInst TmpInst;
6158 TmpInst.setOpcode(NewOpc);
6159 TmpInst.addOperand(Inst.getOperand(0));
6160 TmpInst.addOperand(Inst.getOperand(1));
6161 TmpInst.addOperand(Inst.getOperand(3));
6162 TmpInst.addOperand(Inst.getOperand(4));
6163 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006164 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006165 }
6166 break;
6167 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006168 case ARM::MOVsi: {
6169 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6170 if (SOpc == ARM_AM::rrx) return false;
6171 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6172 // Shifting by zero is accepted as a vanilla 'MOVr'
6173 MCInst TmpInst;
6174 TmpInst.setOpcode(ARM::MOVr);
6175 TmpInst.addOperand(Inst.getOperand(0));
6176 TmpInst.addOperand(Inst.getOperand(1));
6177 TmpInst.addOperand(Inst.getOperand(3));
6178 TmpInst.addOperand(Inst.getOperand(4));
6179 TmpInst.addOperand(Inst.getOperand(5));
6180 Inst = TmpInst;
6181 return true;
6182 }
6183 return false;
6184 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006185 case ARM::ANDrsi:
6186 case ARM::ORRrsi:
6187 case ARM::EORrsi:
6188 case ARM::BICrsi:
6189 case ARM::SUBrsi:
6190 case ARM::ADDrsi: {
6191 unsigned newOpc;
6192 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6193 if (SOpc == ARM_AM::rrx) return false;
6194 switch (Inst.getOpcode()) {
6195 default: assert("unexpected opcode!");
6196 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6197 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6198 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6199 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6200 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6201 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6202 }
6203 // If the shift is by zero, use the non-shifted instruction definition.
6204 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6205 MCInst TmpInst;
6206 TmpInst.setOpcode(newOpc);
6207 TmpInst.addOperand(Inst.getOperand(0));
6208 TmpInst.addOperand(Inst.getOperand(1));
6209 TmpInst.addOperand(Inst.getOperand(2));
6210 TmpInst.addOperand(Inst.getOperand(4));
6211 TmpInst.addOperand(Inst.getOperand(5));
6212 TmpInst.addOperand(Inst.getOperand(6));
6213 Inst = TmpInst;
6214 return true;
6215 }
6216 return false;
6217 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006218 case ARM::t2IT: {
6219 // The mask bits for all but the first condition are represented as
6220 // the low bit of the condition code value implies 't'. We currently
6221 // always have 1 implies 't', so XOR toggle the bits if the low bit
6222 // of the condition code is zero. The encoding also expects the low
6223 // bit of the condition to be encoded as bit 4 of the mask operand,
6224 // so mask that in if needed
6225 MCOperand &MO = Inst.getOperand(1);
6226 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006227 unsigned OrigMask = Mask;
6228 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006229 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006230 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6231 for (unsigned i = 3; i != TZ; --i)
6232 Mask ^= 1 << i;
6233 } else
6234 Mask |= 0x10;
6235 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006236
6237 // Set up the IT block state according to the IT instruction we just
6238 // matched.
6239 assert(!inITBlock() && "nested IT blocks?!");
6240 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6241 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6242 ITState.CurPosition = 0;
6243 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006244 break;
6245 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006246 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006247 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006248}
6249
Jim Grosbach47a0d522011-08-16 20:45:50 +00006250unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6251 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6252 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006253 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006254 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006255 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6256 assert(MCID.hasOptionalDef() &&
6257 "optionally flag setting instruction missing optional def operand");
6258 assert(MCID.NumOperands == Inst.getNumOperands() &&
6259 "operand count mismatch!");
6260 // Find the optional-def operand (cc_out).
6261 unsigned OpNo;
6262 for (OpNo = 0;
6263 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6264 ++OpNo)
6265 ;
6266 // If we're parsing Thumb1, reject it completely.
6267 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6268 return Match_MnemonicFail;
6269 // If we're parsing Thumb2, which form is legal depends on whether we're
6270 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006271 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6272 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006273 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006274 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6275 inITBlock())
6276 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006277 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006278 // Some high-register supporting Thumb1 encodings only allow both registers
6279 // to be from r0-r7 when in Thumb2.
6280 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6281 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6282 isARMLowRegister(Inst.getOperand(2).getReg()))
6283 return Match_RequiresThumb2;
6284 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006285 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006286 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6287 isARMLowRegister(Inst.getOperand(1).getReg()))
6288 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006289 return Match_Success;
6290}
6291
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006292bool ARMAsmParser::
6293MatchAndEmitInstruction(SMLoc IDLoc,
6294 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6295 MCStreamer &Out) {
6296 MCInst Inst;
6297 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006298 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006299 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006300 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006301 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006302 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006303 // Context sensitive operand constraints aren't handled by the matcher,
6304 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006305 if (validateInstruction(Inst, Operands)) {
6306 // Still progress the IT block, otherwise one wrong condition causes
6307 // nasty cascading errors.
6308 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006309 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006310 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006311
Jim Grosbachf8fce712011-08-11 17:35:48 +00006312 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006313 // encoding is selected. Loop on it while changes happen so the
6314 // individual transformations can chain off each other. E.g.,
6315 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6316 while (processInstruction(Inst, Operands))
6317 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006318
Jim Grosbacha1109882011-09-02 23:22:08 +00006319 // Only move forward at the very end so that everything in validate
6320 // and process gets a consistent answer about whether we're in an IT
6321 // block.
6322 forwardITPosition();
6323
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006324 Out.EmitInstruction(Inst);
6325 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006326 case Match_MissingFeature:
6327 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6328 return true;
6329 case Match_InvalidOperand: {
6330 SMLoc ErrorLoc = IDLoc;
6331 if (ErrorInfo != ~0U) {
6332 if (ErrorInfo >= Operands.size())
6333 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006334
Chris Lattnere73d4f82010-10-28 21:41:58 +00006335 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6336 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6337 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006338
Chris Lattnere73d4f82010-10-28 21:41:58 +00006339 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006340 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006341 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006342 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006343 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006344 // The converter function will have already emited a diagnostic.
6345 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006346 case Match_RequiresNotITBlock:
6347 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006348 case Match_RequiresITBlock:
6349 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006350 case Match_RequiresV6:
6351 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6352 case Match_RequiresThumb2:
6353 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006354 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006355
Eric Christopherc223e2b2010-10-29 09:26:59 +00006356 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006357 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006358}
6359
Jim Grosbach1355cf12011-07-26 17:10:22 +00006360/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006361bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6362 StringRef IDVal = DirectiveID.getIdentifier();
6363 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006364 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006365 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006366 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006367 else if (IDVal == ".arm")
6368 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006369 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006370 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006371 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006372 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006373 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006374 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006375 else if (IDVal == ".unreq")
6376 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006377 else if (IDVal == ".arch")
6378 return parseDirectiveArch(DirectiveID.getLoc());
6379 else if (IDVal == ".eabi_attribute")
6380 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006381 return true;
6382}
6383
Jim Grosbach1355cf12011-07-26 17:10:22 +00006384/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006385/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006386bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006387 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6388 for (;;) {
6389 const MCExpr *Value;
6390 if (getParser().ParseExpression(Value))
6391 return true;
6392
Chris Lattneraaec2052010-01-19 19:46:13 +00006393 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006394
6395 if (getLexer().is(AsmToken::EndOfStatement))
6396 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006397
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006398 // FIXME: Improve diagnostic.
6399 if (getLexer().isNot(AsmToken::Comma))
6400 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006401 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006402 }
6403 }
6404
Sean Callananb9a25b72010-01-19 20:27:46 +00006405 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006406 return false;
6407}
6408
Jim Grosbach1355cf12011-07-26 17:10:22 +00006409/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006410/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006411bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006412 if (getLexer().isNot(AsmToken::EndOfStatement))
6413 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006414 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006415
Jim Grosbach9a70df92011-12-07 18:04:19 +00006416 if (!isThumb())
6417 SwitchMode();
6418 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6419 return false;
6420}
6421
6422/// parseDirectiveARM
6423/// ::= .arm
6424bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6425 if (getLexer().isNot(AsmToken::EndOfStatement))
6426 return Error(L, "unexpected token in directive");
6427 Parser.Lex();
6428
6429 if (isThumb())
6430 SwitchMode();
6431 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006432 return false;
6433}
6434
Jim Grosbach1355cf12011-07-26 17:10:22 +00006435/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006436/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006437bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006438 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6439 bool isMachO = MAI.hasSubsectionsViaSymbols();
6440 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006441 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006442
Jim Grosbachde4d8392011-12-21 22:30:16 +00006443 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006444 // ELF doesn't
6445 if (isMachO) {
6446 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006447 if (Tok.isNot(AsmToken::EndOfStatement)) {
6448 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6449 return Error(L, "unexpected token in .thumb_func directive");
6450 Name = Tok.getIdentifier();
6451 Parser.Lex(); // Consume the identifier token.
6452 needFuncName = false;
6453 }
Rafael Espindola64695402011-05-16 16:17:21 +00006454 }
6455
Jim Grosbachde4d8392011-12-21 22:30:16 +00006456 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006457 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006458
6459 // Eat the end of statement and any blank lines that follow.
6460 while (getLexer().is(AsmToken::EndOfStatement))
6461 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006462
Rafael Espindola64695402011-05-16 16:17:21 +00006463 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006464 // We really should be checking the next symbol definition even if there's
6465 // stuff in between.
6466 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006467 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006468 }
6469
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006470 // Mark symbol as a thumb symbol.
6471 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6472 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006473 return false;
6474}
6475
Jim Grosbach1355cf12011-07-26 17:10:22 +00006476/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006477/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006478bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006479 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006480 if (Tok.isNot(AsmToken::Identifier))
6481 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006482 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006483 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006484 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006485 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006486 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006487 else
6488 return Error(L, "unrecognized syntax mode in .syntax directive");
6489
6490 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006491 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006492 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006493
6494 // TODO tell the MC streamer the mode
6495 // getParser().getStreamer().Emit???();
6496 return false;
6497}
6498
Jim Grosbach1355cf12011-07-26 17:10:22 +00006499/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006500/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006501bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006502 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006503 if (Tok.isNot(AsmToken::Integer))
6504 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006505 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006506 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006507 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006508 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006509 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006510 else
6511 return Error(L, "invalid operand to .code directive");
6512
6513 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006514 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006515 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006516
Evan Cheng32869202011-07-08 22:36:29 +00006517 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006518 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006519 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006520 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006521 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006522 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006523 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006524 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006525 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006526
Kevin Enderby515d5092009-10-15 20:48:48 +00006527 return false;
6528}
6529
Jim Grosbacha39cda72011-12-14 02:16:11 +00006530/// parseDirectiveReq
6531/// ::= name .req registername
6532bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6533 Parser.Lex(); // Eat the '.req' token.
6534 unsigned Reg;
6535 SMLoc SRegLoc, ERegLoc;
6536 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6537 Parser.EatToEndOfStatement();
6538 return Error(SRegLoc, "register name expected");
6539 }
6540
6541 // Shouldn't be anything else.
6542 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6543 Parser.EatToEndOfStatement();
6544 return Error(Parser.getTok().getLoc(),
6545 "unexpected input in .req directive.");
6546 }
6547
6548 Parser.Lex(); // Consume the EndOfStatement
6549
6550 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6551 return Error(SRegLoc, "redefinition of '" + Name +
6552 "' does not match original.");
6553
6554 return false;
6555}
6556
6557/// parseDirectiveUneq
6558/// ::= .unreq registername
6559bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6560 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6561 Parser.EatToEndOfStatement();
6562 return Error(L, "unexpected input in .unreq directive.");
6563 }
6564 RegisterReqs.erase(Parser.getTok().getIdentifier());
6565 Parser.Lex(); // Eat the identifier.
6566 return false;
6567}
6568
Jason W Kimd7c9e082011-12-20 17:38:12 +00006569/// parseDirectiveArch
6570/// ::= .arch token
6571bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6572 return true;
6573}
6574
6575/// parseDirectiveEabiAttr
6576/// ::= .eabi_attribute int, int
6577bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6578 return true;
6579}
6580
Sean Callanan90b70972010-04-07 20:29:34 +00006581extern "C" void LLVMInitializeARMAsmLexer();
6582
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006583/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006584extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006585 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6586 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006587 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006588}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006589
Chris Lattner0692ee62010-09-06 19:11:01 +00006590#define GET_REGISTER_MATCHER
6591#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006592#include "ARMGenAsmMatcher.inc"