blob: ca559571089cfe09cfc854f0207cade6a6b9764a [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 Grosbacha77295d2011-09-08 22:07:06 +0000550 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000551 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
556 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000557 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000558 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
563 }
564 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000565 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
570 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000571 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000572 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return Value >= 0 && Value < 256;
577 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000578 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000579 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000580 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
581 if (!CE) return false;
582 int64_t Value = CE->getValue();
583 return Value >= 0 && Value < 2;
584 }
585 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000586 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
588 if (!CE) return false;
589 int64_t Value = CE->getValue();
590 return Value >= 0 && Value < 4;
591 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000592 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000593 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000594 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
595 if (!CE) return false;
596 int64_t Value = CE->getValue();
597 return Value >= 0 && Value < 8;
598 }
599 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000600 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 16;
605 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000606 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000607 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 32;
612 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000613 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000614 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 64;
619 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000620 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000621 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value == 8;
626 }
627 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000628 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 if (!CE) return false;
631 int64_t Value = CE->getValue();
632 return Value == 16;
633 }
634 bool isImm32() 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 == 32;
640 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000641 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000642 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value > 0 && Value <= 8;
647 }
648 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000649 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 16;
654 }
655 bool isShrImm32() 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 <= 32;
661 }
662 bool isShrImm64() 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 <= 64;
668 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000669 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000670 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value < 8;
675 }
676 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000677 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value < 16;
682 }
683 bool isImm1_31() 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 < 32;
689 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000690 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000691 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000692 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693 if (!CE) return false;
694 int64_t Value = CE->getValue();
695 return Value > 0 && Value < 17;
696 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000697 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000698 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700 if (!CE) return false;
701 int64_t Value = CE->getValue();
702 return Value > 0 && Value < 33;
703 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000704 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000705 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707 if (!CE) return false;
708 int64_t Value = CE->getValue();
709 return Value >= 0 && Value < 33;
710 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000711 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000712 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value >= 0 && Value < 65536;
717 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000718 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000719 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721 // If it's not a constant expression, it'll generate a fixup and be
722 // handled later.
723 if (!CE) return true;
724 int64_t Value = CE->getValue();
725 return Value >= 0 && Value < 65536;
726 }
Jim Grosbached838482011-07-26 16:24:27 +0000727 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000728 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value <= 0xffffff;
733 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000734 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value > 0 && Value < 33;
740 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000741 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value >= 0 && Value < 32;
747 }
748 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value > 0 && Value <= 32;
754 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000755 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return ARM_AM::getSOImmVal(Value) != -1;
761 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000762 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Value = CE->getValue();
767 return ARM_AM::getSOImmVal(~Value) != -1;
768 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000769 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000770 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +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 Grosbach6b8f1e32011-06-27 23:54:06 +0000776 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000777 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000778 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779 if (!CE) return false;
780 int64_t Value = CE->getValue();
781 return ARM_AM::getT2SOImmVal(Value) != -1;
782 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000783 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000784 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getT2SOImmVal(~Value) != -1;
789 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000790 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000791 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +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 Grosbachc27d4f92011-07-22 17:44:50 +0000797 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000798 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
800 if (!CE) return false;
801 int64_t Value = CE->getValue();
802 return Value == 1 || Value == 0;
803 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000804 bool isReg() const { return Kind == k_Register; }
805 bool isRegList() const { return Kind == k_RegisterList; }
806 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
807 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
808 bool isToken() const { return Kind == k_Token; }
809 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
810 bool isMemory() const { return Kind == k_Memory; }
811 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
812 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
813 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
814 bool isRotImm() const { return Kind == k_RotateImmediate; }
815 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
816 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000817 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000818 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000819 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000820 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000821 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000822 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000823 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000824 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
825 (alignOK || Memory.Alignment == 0);
826 }
827 bool isAlignedMemory() const {
828 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000829 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000831 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000832 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000833 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000834 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000835 if (!Memory.OffsetImm) return true;
836 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000837 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000838 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000839 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000840 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000841 // Immediate offset in range [-4095, 4095].
842 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
843 if (!CE) return false;
844 int64_t Val = CE->getValue();
845 return Val > -4096 && Val < 4096;
846 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000847 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000848 // If we have an immediate that's not a constant, treat it as a label
849 // reference needing a fixup. If it is a constant, it's something else
850 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000851 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000852 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000853 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000854 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000856 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000857 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000858 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000859 if (!Memory.OffsetImm) return true;
860 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000861 return Val > -256 && Val < 256;
862 }
863 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000864 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000865 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000866 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000867 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
868 // Immediate offset in range [-255, 255].
869 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
870 if (!CE) return false;
871 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000872 // Special case, #-0 is INT32_MIN.
873 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000874 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000875 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000876 // If we have an immediate that's not a constant, treat it as a label
877 // reference needing a fixup. If it is a constant, it's something else
878 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000879 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000880 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000881 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000883 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000884 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000885 if (!Memory.OffsetImm) return true;
886 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000887 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000888 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000889 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000890 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000891 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000892 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000893 return false;
894 return true;
895 }
896 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000897 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000898 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
899 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000900 return false;
901 return true;
902 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000903 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000904 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000905 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000906 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000907 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000908 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000909 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
910 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000911 return false;
912 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000913 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000914 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000915 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000916 return false;
917 return true;
918 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000919 bool isMemThumbRR() const {
920 // Thumb reg+reg addressing is simple. Just two registers, a base and
921 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000923 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000924 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000925 return isARMLowRegister(Memory.BaseRegNum) &&
926 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000927 }
928 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000929 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000930 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000931 return false;
932 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000933 if (!Memory.OffsetImm) return true;
934 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000935 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
936 }
Jim Grosbach38466302011-08-19 18:55:51 +0000937 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000938 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000939 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000940 return false;
941 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000942 if (!Memory.OffsetImm) return true;
943 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000944 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
945 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000946 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000947 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000949 return false;
950 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!Memory.OffsetImm) return true;
952 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000953 return Val >= 0 && Val <= 31;
954 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000955 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000956 if (!isMemory() || Memory.OffsetRegNum != 0 ||
957 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000958 return false;
959 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000962 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000963 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000964 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000965 // If we have an immediate that's not a constant, treat it as a label
966 // reference needing a fixup. If it is a constant, it's something else
967 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000968 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000969 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000970 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000971 return false;
972 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000973 if (!Memory.OffsetImm) return true;
974 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000975 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
976 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000977 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000978 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000979 return false;
980 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000981 if (!Memory.OffsetImm) return true;
982 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000983 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
984 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000985 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000986 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000987 return false;
988 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000991 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000992 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000993 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000995 return false;
996 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000999 return Val >= 0 && Val < 256;
1000 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001001 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001002 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001003 return false;
1004 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001005 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001006 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001007 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001008 }
1009 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001010 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001011 return false;
1012 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001013 if (!Memory.OffsetImm) return true;
1014 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001015 return (Val >= 0 && Val < 4096);
1016 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001017 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001018 // If we have an immediate that's not a constant, treat it as a label
1019 // reference needing a fixup. If it is a constant, it's something else
1020 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001021 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001022 return true;
1023
Jim Grosbach57dcb852011-10-11 17:29:55 +00001024 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001025 return false;
1026 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001027 if (!Memory.OffsetImm) return true;
1028 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001029 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001030 }
1031 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001032 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001033 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1034 if (!CE) return false;
1035 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001036 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001037 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001038 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001039 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1041 if (!CE) return false;
1042 int64_t Val = CE->getValue();
1043 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1044 (Val == INT32_MIN);
1045 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001046
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001047 bool isMSRMask() const { return Kind == k_MSRMask; }
1048 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001049
Jim Grosbach0e387b22011-10-17 22:26:03 +00001050 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001051 bool isSingleSpacedVectorList() const {
1052 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1053 }
1054 bool isDoubleSpacedVectorList() const {
1055 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1056 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001057 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001058 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001059 return VectorList.Count == 1;
1060 }
1061
Jim Grosbach280dfad2011-10-21 18:54:25 +00001062 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001063 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001064 return VectorList.Count == 2;
1065 }
1066
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001067 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001068 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001069 return VectorList.Count == 3;
1070 }
1071
Jim Grosbachb6310312011-10-21 20:35:01 +00001072 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001073 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001074 return VectorList.Count == 4;
1075 }
1076
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001077 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001078 if (!isDoubleSpacedVectorList()) return false;
1079 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001080 }
1081
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001082 bool isSingleSpacedVectorAllLanes() const {
1083 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1084 }
1085 bool isDoubleSpacedVectorAllLanes() const {
1086 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1087 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001088 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001089 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001090 return VectorList.Count == 1;
1091 }
1092
Jim Grosbach13af2222011-11-30 18:21:25 +00001093 bool isVecListTwoDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001094 if (!isSingleSpacedVectorAllLanes()) return false;
1095 return VectorList.Count == 2;
1096 }
1097
1098 bool isVecListTwoQAllLanes() const {
1099 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001100 return VectorList.Count == 2;
1101 }
1102
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001103 bool isSingleSpacedVectorIndexed() const {
1104 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1105 }
1106 bool isDoubleSpacedVectorIndexed() const {
1107 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1108 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001109 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001110 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001111 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1112 }
1113
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001114 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001115 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001116 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1117 }
1118
1119 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001120 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001121 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1122 }
1123
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001124 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001125 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001126 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1127 }
1128
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001129 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001130 if (!isSingleSpacedVectorIndexed()) return false;
1131 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1132 }
1133
1134 bool isVecListTwoQWordIndexed() const {
1135 if (!isDoubleSpacedVectorIndexed()) return false;
1136 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1137 }
1138
1139 bool isVecListTwoQHWordIndexed() const {
1140 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001141 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1142 }
1143
1144 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001145 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001146 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1147 }
1148
Jim Grosbach460a9052011-10-07 23:56:00 +00001149 bool isVectorIndex8() const {
1150 if (Kind != k_VectorIndex) return false;
1151 return VectorIndex.Val < 8;
1152 }
1153 bool isVectorIndex16() const {
1154 if (Kind != k_VectorIndex) return false;
1155 return VectorIndex.Val < 4;
1156 }
1157 bool isVectorIndex32() const {
1158 if (Kind != k_VectorIndex) return false;
1159 return VectorIndex.Val < 2;
1160 }
1161
Jim Grosbach0e387b22011-10-17 22:26:03 +00001162 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001163 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001164 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1165 // Must be a constant.
1166 if (!CE) return false;
1167 int64_t Value = CE->getValue();
1168 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1169 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001170 return Value >= 0 && Value < 256;
1171 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001172
Jim Grosbachea461102011-10-17 23:09:09 +00001173 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001174 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001175 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1176 // Must be a constant.
1177 if (!CE) return false;
1178 int64_t Value = CE->getValue();
1179 // i16 value in the range [0,255] or [0x0100, 0xff00]
1180 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1181 }
1182
Jim Grosbach6248a542011-10-18 00:22:00 +00001183 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001184 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001185 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1186 // Must be a constant.
1187 if (!CE) return false;
1188 int64_t Value = CE->getValue();
1189 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1190 return (Value >= 0 && Value < 256) ||
1191 (Value >= 0x0100 && Value <= 0xff00) ||
1192 (Value >= 0x010000 && Value <= 0xff0000) ||
1193 (Value >= 0x01000000 && Value <= 0xff000000);
1194 }
1195
1196 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001197 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001198 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1199 // Must be a constant.
1200 if (!CE) return false;
1201 int64_t Value = CE->getValue();
1202 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1203 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1204 return (Value >= 0 && Value < 256) ||
1205 (Value >= 0x0100 && Value <= 0xff00) ||
1206 (Value >= 0x010000 && Value <= 0xff0000) ||
1207 (Value >= 0x01000000 && Value <= 0xff000000) ||
1208 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1209 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1210 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001211 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001212 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1214 // Must be a constant.
1215 if (!CE) return false;
1216 int64_t Value = ~CE->getValue();
1217 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1218 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1219 return (Value >= 0 && Value < 256) ||
1220 (Value >= 0x0100 && Value <= 0xff00) ||
1221 (Value >= 0x010000 && Value <= 0xff0000) ||
1222 (Value >= 0x01000000 && Value <= 0xff000000) ||
1223 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1224 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1225 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001226
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001227 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001228 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1230 // Must be a constant.
1231 if (!CE) return false;
1232 uint64_t Value = CE->getValue();
1233 // i64 value with each byte being either 0 or 0xff.
1234 for (unsigned i = 0; i < 8; ++i)
1235 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1236 return true;
1237 }
1238
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001239 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001240 // Add as immediates when possible. Null MCExpr = 0.
1241 if (Expr == 0)
1242 Inst.addOperand(MCOperand::CreateImm(0));
1243 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001244 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1245 else
1246 Inst.addOperand(MCOperand::CreateExpr(Expr));
1247 }
1248
Daniel Dunbar8462b302010-08-11 06:36:53 +00001249 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001250 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001251 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001252 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1253 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001254 }
1255
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001256 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1257 assert(N == 1 && "Invalid number of operands!");
1258 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1259 }
1260
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001261 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1264 }
1265
1266 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1269 }
1270
Jim Grosbach89df9962011-08-26 21:43:41 +00001271 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1274 }
1275
1276 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1279 }
1280
Jim Grosbachd67641b2010-12-06 18:21:12 +00001281 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 1 && "Invalid number of operands!");
1283 Inst.addOperand(MCOperand::CreateReg(getReg()));
1284 }
1285
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001286 void addRegOperands(MCInst &Inst, unsigned N) const {
1287 assert(N == 1 && "Invalid number of operands!");
1288 Inst.addOperand(MCOperand::CreateReg(getReg()));
1289 }
1290
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001291 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001292 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001293 assert(isRegShiftedReg() &&
1294 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001295 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1296 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001297 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001298 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001299 }
1300
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001301 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001302 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001303 assert(isRegShiftedImm() &&
1304 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001305 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001306 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001307 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001308 }
1309
Jim Grosbach580f4a92011-07-25 22:20:28 +00001310 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001311 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001312 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1313 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001314 }
1315
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001316 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001317 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001318 const SmallVectorImpl<unsigned> &RegList = getRegList();
1319 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001320 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1321 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001322 }
1323
Bill Wendling0f630752010-11-17 04:32:08 +00001324 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1325 addRegListOperands(Inst, N);
1326 }
1327
1328 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1329 addRegListOperands(Inst, N);
1330 }
1331
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001332 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1333 assert(N == 1 && "Invalid number of operands!");
1334 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1335 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1336 }
1337
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001338 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 // Munge the lsb/width into a bitfield mask.
1341 unsigned lsb = Bitfield.LSB;
1342 unsigned width = Bitfield.Width;
1343 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1344 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1345 (32 - (lsb + width)));
1346 Inst.addOperand(MCOperand::CreateImm(Mask));
1347 }
1348
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001349 void addImmOperands(MCInst &Inst, unsigned N) const {
1350 assert(N == 1 && "Invalid number of operands!");
1351 addExpr(Inst, getImm());
1352 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001353
Jim Grosbach9d390362011-10-03 23:38:36 +00001354 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
1356 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1357 }
1358
Jim Grosbacha77295d2011-09-08 22:07:06 +00001359 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1360 assert(N == 1 && "Invalid number of operands!");
1361 // FIXME: We really want to scale the value here, but the LDRD/STRD
1362 // instruction don't encode operands that way yet.
1363 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1364 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1365 }
1366
Jim Grosbach72f39f82011-08-24 21:22:15 +00001367 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1368 assert(N == 1 && "Invalid number of operands!");
1369 // The immediate is scaled by four in the encoding and is stored
1370 // in the MCInst as such. Lop off the low two bits here.
1371 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1372 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1373 }
1374
1375 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
1377 // The immediate is scaled by four in the encoding and is stored
1378 // in the MCInst as such. Lop off the low two bits here.
1379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1380 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1381 }
1382
Jim Grosbachf4943352011-07-25 23:09:14 +00001383 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 // The constant encodes as the immediate-1, and we store in the instruction
1386 // the bits as encoded, so subtract off one here.
1387 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1388 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1389 }
1390
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001391 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1392 assert(N == 1 && "Invalid number of operands!");
1393 // The constant encodes as the immediate-1, and we store in the instruction
1394 // the bits as encoded, so subtract off one here.
1395 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1396 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1397 }
1398
Jim Grosbach70939ee2011-08-17 21:51:27 +00001399 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 // The constant encodes as the immediate, except for 32, which encodes as
1402 // zero.
1403 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1404 unsigned Imm = CE->getValue();
1405 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1406 }
1407
Jim Grosbachf6c05252011-07-21 17:23:04 +00001408 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1409 assert(N == 1 && "Invalid number of operands!");
1410 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1411 // the instruction as well.
1412 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1413 int Val = CE->getValue();
1414 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1415 }
1416
Jim Grosbach89a63372011-10-28 22:36:30 +00001417 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 // The operand is actually a t2_so_imm, but we have its bitwise
1420 // negation in the assembly source, so twiddle it here.
1421 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1422 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1423 }
1424
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001425 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 // The operand is actually a t2_so_imm, but we have its
1428 // negation in the assembly source, so twiddle it here.
1429 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1430 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1431 }
1432
Jim Grosbache70ec842011-10-28 22:50:54 +00001433 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 // The operand is actually a so_imm, but we have its bitwise
1436 // negation in the assembly source, so twiddle it here.
1437 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1438 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1439 }
1440
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001441 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 // The operand is actually a so_imm, but we have its
1444 // negation in the assembly source, so twiddle it here.
1445 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1446 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1447 }
1448
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001449 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1452 }
1453
Jim Grosbach7ce05792011-08-03 23:50:40 +00001454 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1455 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001457 }
1458
Jim Grosbach57dcb852011-10-11 17:29:55 +00001459 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 2 && "Invalid number of operands!");
1461 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1462 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1463 }
1464
Jim Grosbach7ce05792011-08-03 23:50:40 +00001465 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1466 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001467 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1468 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001469 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1470 // Special case for #-0
1471 if (Val == INT32_MIN) Val = 0;
1472 if (Val < 0) Val = -Val;
1473 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1474 } else {
1475 // For register offset, we encode the shift type and negation flag
1476 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001477 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1478 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001479 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001480 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1481 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001482 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001483 }
1484
Jim Grosbach039c2e12011-08-04 23:01:30 +00001485 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 2 && "Invalid number of operands!");
1487 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1488 assert(CE && "non-constant AM2OffsetImm operand!");
1489 int32_t Val = CE->getValue();
1490 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1491 // Special case for #-0
1492 if (Val == INT32_MIN) Val = 0;
1493 if (Val < 0) Val = -Val;
1494 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1495 Inst.addOperand(MCOperand::CreateReg(0));
1496 Inst.addOperand(MCOperand::CreateImm(Val));
1497 }
1498
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001499 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001501 // If we have an immediate that's not a constant, treat it as a label
1502 // reference needing a fixup. If it is a constant, it's something else
1503 // and we reject it.
1504 if (isImm()) {
1505 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1506 Inst.addOperand(MCOperand::CreateReg(0));
1507 Inst.addOperand(MCOperand::CreateImm(0));
1508 return;
1509 }
1510
Jim Grosbache53c87b2011-10-11 15:59:20 +00001511 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1512 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001513 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1514 // Special case for #-0
1515 if (Val == INT32_MIN) Val = 0;
1516 if (Val < 0) Val = -Val;
1517 Val = ARM_AM::getAM3Opc(AddSub, Val);
1518 } else {
1519 // For register offset, we encode the shift type and negation flag
1520 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001521 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001522 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001523 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1524 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001525 Inst.addOperand(MCOperand::CreateImm(Val));
1526 }
1527
1528 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001530 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001531 int32_t Val =
1532 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1533 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1534 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001535 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001536 }
1537
1538 // Constant offset.
1539 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1540 int32_t Val = CE->getValue();
1541 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1542 // Special case for #-0
1543 if (Val == INT32_MIN) Val = 0;
1544 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001545 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001546 Inst.addOperand(MCOperand::CreateReg(0));
1547 Inst.addOperand(MCOperand::CreateImm(Val));
1548 }
1549
Jim Grosbach7ce05792011-08-03 23:50:40 +00001550 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1551 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001552 // If we have an immediate that's not a constant, treat it as a label
1553 // reference needing a fixup. If it is a constant, it's something else
1554 // and we reject it.
1555 if (isImm()) {
1556 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1557 Inst.addOperand(MCOperand::CreateImm(0));
1558 return;
1559 }
1560
Jim Grosbach7ce05792011-08-03 23:50:40 +00001561 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001562 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001563 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1564 // Special case for #-0
1565 if (Val == INT32_MIN) Val = 0;
1566 if (Val < 0) Val = -Val;
1567 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001568 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001569 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001570 }
1571
Jim Grosbacha77295d2011-09-08 22:07:06 +00001572 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1573 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001574 // If we have an immediate that's not a constant, treat it as a label
1575 // reference needing a fixup. If it is a constant, it's something else
1576 // and we reject it.
1577 if (isImm()) {
1578 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1579 Inst.addOperand(MCOperand::CreateImm(0));
1580 return;
1581 }
1582
Jim Grosbache53c87b2011-10-11 15:59:20 +00001583 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1584 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001585 Inst.addOperand(MCOperand::CreateImm(Val));
1586 }
1587
Jim Grosbachb6aed502011-09-09 18:37:27 +00001588 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 2 && "Invalid number of operands!");
1590 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001591 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1592 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001593 Inst.addOperand(MCOperand::CreateImm(Val));
1594 }
1595
Jim Grosbach7ce05792011-08-03 23:50:40 +00001596 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1597 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001598 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1599 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001600 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001601 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001602
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001603 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1604 addMemImm8OffsetOperands(Inst, N);
1605 }
1606
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001607 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001608 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001609 }
1610
1611 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1612 assert(N == 2 && "Invalid number of operands!");
1613 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001614 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001615 addExpr(Inst, getImm());
1616 Inst.addOperand(MCOperand::CreateImm(0));
1617 return;
1618 }
1619
1620 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001621 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1622 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001623 Inst.addOperand(MCOperand::CreateImm(Val));
1624 }
1625
Jim Grosbach7ce05792011-08-03 23:50:40 +00001626 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001628 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001629 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001630 addExpr(Inst, getImm());
1631 Inst.addOperand(MCOperand::CreateImm(0));
1632 return;
1633 }
1634
1635 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001636 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1637 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001638 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001639 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001640
Jim Grosbach7f739be2011-09-19 22:21:13 +00001641 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1642 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001643 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1644 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001645 }
1646
1647 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1648 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001649 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1650 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001651 }
1652
Jim Grosbach7ce05792011-08-03 23:50:40 +00001653 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1654 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001655 unsigned Val =
1656 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1657 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001658 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1659 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001660 Inst.addOperand(MCOperand::CreateImm(Val));
1661 }
1662
Jim Grosbachab899c12011-09-07 23:10:15 +00001663 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001665 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1666 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1667 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001668 }
1669
Jim Grosbach7ce05792011-08-03 23:50:40 +00001670 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001672 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1673 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001674 }
1675
Jim Grosbach60f91a32011-08-19 17:55:24 +00001676 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1677 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001678 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1679 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001680 Inst.addOperand(MCOperand::CreateImm(Val));
1681 }
1682
Jim Grosbach38466302011-08-19 18:55:51 +00001683 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1684 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001685 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1686 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001687 Inst.addOperand(MCOperand::CreateImm(Val));
1688 }
1689
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001690 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1691 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001692 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1693 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001694 Inst.addOperand(MCOperand::CreateImm(Val));
1695 }
1696
Jim Grosbachecd85892011-08-19 18:13:48 +00001697 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1698 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001699 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1700 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001701 Inst.addOperand(MCOperand::CreateImm(Val));
1702 }
1703
Jim Grosbach7ce05792011-08-03 23:50:40 +00001704 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1705 assert(N == 1 && "Invalid number of operands!");
1706 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1707 assert(CE && "non-constant post-idx-imm8 operand!");
1708 int Imm = CE->getValue();
1709 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001710 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001711 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1712 Inst.addOperand(MCOperand::CreateImm(Imm));
1713 }
1714
Jim Grosbach2bd01182011-10-11 21:55:36 +00001715 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1716 assert(N == 1 && "Invalid number of operands!");
1717 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1718 assert(CE && "non-constant post-idx-imm8s4 operand!");
1719 int Imm = CE->getValue();
1720 bool isAdd = Imm >= 0;
1721 if (Imm == INT32_MIN) Imm = 0;
1722 // Immediate is scaled by 4.
1723 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1724 Inst.addOperand(MCOperand::CreateImm(Imm));
1725 }
1726
Jim Grosbach7ce05792011-08-03 23:50:40 +00001727 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1728 assert(N == 2 && "Invalid number of operands!");
1729 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001730 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1731 }
1732
1733 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1734 assert(N == 2 && "Invalid number of operands!");
1735 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1736 // The sign, shift type, and shift amount are encoded in a single operand
1737 // using the AM2 encoding helpers.
1738 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1739 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1740 PostIdxReg.ShiftTy);
1741 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001742 }
1743
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001744 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1745 assert(N == 1 && "Invalid number of operands!");
1746 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1747 }
1748
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001749 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1752 }
1753
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001754 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001755 assert(N == 1 && "Invalid number of operands!");
1756 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1757 }
1758
Jim Grosbach7636bf62011-12-02 00:35:16 +00001759 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 2 && "Invalid number of operands!");
1761 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1762 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1763 }
1764
Jim Grosbach460a9052011-10-07 23:56:00 +00001765 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1766 assert(N == 1 && "Invalid number of operands!");
1767 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1768 }
1769
1770 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1771 assert(N == 1 && "Invalid number of operands!");
1772 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1773 }
1774
1775 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1776 assert(N == 1 && "Invalid number of operands!");
1777 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1778 }
1779
Jim Grosbach0e387b22011-10-17 22:26:03 +00001780 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1781 assert(N == 1 && "Invalid number of operands!");
1782 // The immediate encodes the type of constant as well as the value.
1783 // Mask in that this is an i8 splat.
1784 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1785 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1786 }
1787
Jim Grosbachea461102011-10-17 23:09:09 +00001788 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1789 assert(N == 1 && "Invalid number of operands!");
1790 // The immediate encodes the type of constant as well as the value.
1791 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1792 unsigned Value = CE->getValue();
1793 if (Value >= 256)
1794 Value = (Value >> 8) | 0xa00;
1795 else
1796 Value |= 0x800;
1797 Inst.addOperand(MCOperand::CreateImm(Value));
1798 }
1799
Jim Grosbach6248a542011-10-18 00:22:00 +00001800 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1801 assert(N == 1 && "Invalid number of operands!");
1802 // The immediate encodes the type of constant as well as the value.
1803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1804 unsigned Value = CE->getValue();
1805 if (Value >= 256 && Value <= 0xff00)
1806 Value = (Value >> 8) | 0x200;
1807 else if (Value > 0xffff && Value <= 0xff0000)
1808 Value = (Value >> 16) | 0x400;
1809 else if (Value > 0xffffff)
1810 Value = (Value >> 24) | 0x600;
1811 Inst.addOperand(MCOperand::CreateImm(Value));
1812 }
1813
1814 void addNEONi32vmovOperands(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 && Value <= 0xffff)
1820 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1821 else if (Value > 0xffff && Value <= 0xffffff)
1822 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1823 else if (Value > 0xffffff)
1824 Value = (Value >> 24) | 0x600;
1825 Inst.addOperand(MCOperand::CreateImm(Value));
1826 }
1827
Jim Grosbach9b087852011-12-19 23:51:07 +00001828 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1829 assert(N == 1 && "Invalid number of operands!");
1830 // The immediate encodes the type of constant as well as the value.
1831 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1832 unsigned Value = ~CE->getValue();
1833 if (Value >= 256 && Value <= 0xffff)
1834 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1835 else if (Value > 0xffff && Value <= 0xffffff)
1836 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1837 else if (Value > 0xffffff)
1838 Value = (Value >> 24) | 0x600;
1839 Inst.addOperand(MCOperand::CreateImm(Value));
1840 }
1841
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001842 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1843 assert(N == 1 && "Invalid number of operands!");
1844 // The immediate encodes the type of constant as well as the value.
1845 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1846 uint64_t Value = CE->getValue();
1847 unsigned Imm = 0;
1848 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1849 Imm |= (Value & 1) << i;
1850 }
1851 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1852 }
1853
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001854 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001855
Jim Grosbach89df9962011-08-26 21:43:41 +00001856 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001857 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001858 Op->ITMask.Mask = Mask;
1859 Op->StartLoc = S;
1860 Op->EndLoc = S;
1861 return Op;
1862 }
1863
Chris Lattner3a697562010-10-28 17:20:03 +00001864 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001865 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001866 Op->CC.Val = CC;
1867 Op->StartLoc = S;
1868 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001869 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001870 }
1871
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001872 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001873 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001874 Op->Cop.Val = CopVal;
1875 Op->StartLoc = S;
1876 Op->EndLoc = S;
1877 return Op;
1878 }
1879
1880 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001881 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001882 Op->Cop.Val = CopVal;
1883 Op->StartLoc = S;
1884 Op->EndLoc = S;
1885 return Op;
1886 }
1887
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001888 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1889 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1890 Op->Cop.Val = Val;
1891 Op->StartLoc = S;
1892 Op->EndLoc = E;
1893 return Op;
1894 }
1895
Jim Grosbachd67641b2010-12-06 18:21:12 +00001896 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001897 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001898 Op->Reg.RegNum = RegNum;
1899 Op->StartLoc = S;
1900 Op->EndLoc = S;
1901 return Op;
1902 }
1903
Chris Lattner3a697562010-10-28 17:20:03 +00001904 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001905 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001906 Op->Tok.Data = Str.data();
1907 Op->Tok.Length = Str.size();
1908 Op->StartLoc = S;
1909 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001910 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001911 }
1912
Bill Wendling50d0f582010-11-18 23:43:05 +00001913 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001914 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001915 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001916 Op->StartLoc = S;
1917 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001918 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001919 }
1920
Jim Grosbache8606dc2011-07-13 17:50:29 +00001921 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1922 unsigned SrcReg,
1923 unsigned ShiftReg,
1924 unsigned ShiftImm,
1925 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001927 Op->RegShiftedReg.ShiftTy = ShTy;
1928 Op->RegShiftedReg.SrcReg = SrcReg;
1929 Op->RegShiftedReg.ShiftReg = ShiftReg;
1930 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001931 Op->StartLoc = S;
1932 Op->EndLoc = E;
1933 return Op;
1934 }
1935
Owen Anderson92a20222011-07-21 18:54:16 +00001936 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1937 unsigned SrcReg,
1938 unsigned ShiftImm,
1939 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001941 Op->RegShiftedImm.ShiftTy = ShTy;
1942 Op->RegShiftedImm.SrcReg = SrcReg;
1943 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001944 Op->StartLoc = S;
1945 Op->EndLoc = E;
1946 return Op;
1947 }
1948
Jim Grosbach580f4a92011-07-25 22:20:28 +00001949 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001950 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001951 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001952 Op->ShifterImm.isASR = isASR;
1953 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001954 Op->StartLoc = S;
1955 Op->EndLoc = E;
1956 return Op;
1957 }
1958
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001959 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001960 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001961 Op->RotImm.Imm = Imm;
1962 Op->StartLoc = S;
1963 Op->EndLoc = E;
1964 return Op;
1965 }
1966
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001967 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1968 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001970 Op->Bitfield.LSB = LSB;
1971 Op->Bitfield.Width = Width;
1972 Op->StartLoc = S;
1973 Op->EndLoc = E;
1974 return Op;
1975 }
1976
Bill Wendling7729e062010-11-09 22:44:22 +00001977 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001978 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001979 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001980 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001981
Jim Grosbachd300b942011-09-13 22:56:44 +00001982 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001983 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001984 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001985 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001986 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001987
1988 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001989 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001990 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001991 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001992 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001993 Op->StartLoc = StartLoc;
1994 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001995 return Op;
1996 }
1997
Jim Grosbach862019c2011-10-18 23:02:30 +00001998 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001999 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002000 ARMOperand *Op = new ARMOperand(k_VectorList);
2001 Op->VectorList.RegNum = RegNum;
2002 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002003 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002004 Op->StartLoc = S;
2005 Op->EndLoc = E;
2006 return Op;
2007 }
2008
Jim Grosbach98b05a52011-11-30 01:09:44 +00002009 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002010 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002011 SMLoc S, SMLoc E) {
2012 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2013 Op->VectorList.RegNum = RegNum;
2014 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002015 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002016 Op->StartLoc = S;
2017 Op->EndLoc = E;
2018 return Op;
2019 }
2020
Jim Grosbach7636bf62011-12-02 00:35:16 +00002021 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002022 unsigned Index,
2023 bool isDoubleSpaced,
2024 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002025 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2026 Op->VectorList.RegNum = RegNum;
2027 Op->VectorList.Count = Count;
2028 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002029 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002030 Op->StartLoc = S;
2031 Op->EndLoc = E;
2032 return Op;
2033 }
2034
Jim Grosbach460a9052011-10-07 23:56:00 +00002035 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2036 MCContext &Ctx) {
2037 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2038 Op->VectorIndex.Val = Idx;
2039 Op->StartLoc = S;
2040 Op->EndLoc = E;
2041 return Op;
2042 }
2043
Chris Lattner3a697562010-10-28 17:20:03 +00002044 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002046 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002047 Op->StartLoc = S;
2048 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002049 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002050 }
2051
Jim Grosbach9d390362011-10-03 23:38:36 +00002052 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002053 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002054 Op->FPImm.Val = Val;
2055 Op->StartLoc = S;
2056 Op->EndLoc = S;
2057 return Op;
2058 }
2059
Jim Grosbach7ce05792011-08-03 23:50:40 +00002060 static ARMOperand *CreateMem(unsigned BaseRegNum,
2061 const MCConstantExpr *OffsetImm,
2062 unsigned OffsetRegNum,
2063 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002064 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002065 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002066 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002067 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002068 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002069 Op->Memory.BaseRegNum = BaseRegNum;
2070 Op->Memory.OffsetImm = OffsetImm;
2071 Op->Memory.OffsetRegNum = OffsetRegNum;
2072 Op->Memory.ShiftType = ShiftType;
2073 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002074 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002075 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002076 Op->StartLoc = S;
2077 Op->EndLoc = E;
2078 return Op;
2079 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002080
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002081 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2082 ARM_AM::ShiftOpc ShiftTy,
2083 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002084 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002085 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002086 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002087 Op->PostIdxReg.isAdd = isAdd;
2088 Op->PostIdxReg.ShiftTy = ShiftTy;
2089 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002090 Op->StartLoc = S;
2091 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002092 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002093 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002094
2095 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002096 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002097 Op->MBOpt.Val = Opt;
2098 Op->StartLoc = S;
2099 Op->EndLoc = S;
2100 return Op;
2101 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002102
2103 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002104 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002105 Op->IFlags.Val = IFlags;
2106 Op->StartLoc = S;
2107 Op->EndLoc = S;
2108 return Op;
2109 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002110
2111 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002112 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002113 Op->MMask.Val = MMask;
2114 Op->StartLoc = S;
2115 Op->EndLoc = S;
2116 return Op;
2117 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002118};
2119
2120} // end anonymous namespace.
2121
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002122void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002123 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002124 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002125 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2126 << ") >";
2127 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002128 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002129 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002130 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002131 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002132 OS << "<ccout " << getReg() << ">";
2133 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002134 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002135 static const char *MaskStr[] = {
2136 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2137 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2138 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002139 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2140 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2141 break;
2142 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002143 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002144 OS << "<coprocessor number: " << getCoproc() << ">";
2145 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002146 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002147 OS << "<coprocessor register: " << getCoproc() << ">";
2148 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002149 case k_CoprocOption:
2150 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2151 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002152 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002153 OS << "<mask: " << getMSRMask() << ">";
2154 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002155 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002156 getImm()->print(OS);
2157 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002158 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002159 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2160 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002161 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002162 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002163 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002164 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002165 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002166 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002167 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2168 << PostIdxReg.RegNum;
2169 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2170 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2171 << PostIdxReg.ShiftImm;
2172 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002173 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002174 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002175 OS << "<ARM_PROC::";
2176 unsigned IFlags = getProcIFlags();
2177 for (int i=2; i >= 0; --i)
2178 if (IFlags & (1 << i))
2179 OS << ARM_PROC::IFlagsToString(1 << i);
2180 OS << ">";
2181 break;
2182 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002183 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002184 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002185 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002186 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002187 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2188 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002189 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002190 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002191 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002192 << RegShiftedReg.SrcReg << " "
2193 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2194 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002195 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002196 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002197 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002198 << RegShiftedImm.SrcReg << " "
2199 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2200 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002201 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002202 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002203 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2204 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002205 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002206 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2207 << ", width: " << Bitfield.Width << ">";
2208 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002209 case k_RegisterList:
2210 case k_DPRRegisterList:
2211 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002212 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002213
Bill Wendling5fa22a12010-11-09 23:28:44 +00002214 const SmallVectorImpl<unsigned> &RegList = getRegList();
2215 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002216 I = RegList.begin(), E = RegList.end(); I != E; ) {
2217 OS << *I;
2218 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002219 }
2220
2221 OS << ">";
2222 break;
2223 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002224 case k_VectorList:
2225 OS << "<vector_list " << VectorList.Count << " * "
2226 << VectorList.RegNum << ">";
2227 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002228 case k_VectorListAllLanes:
2229 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2230 << VectorList.RegNum << ">";
2231 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002232 case k_VectorListIndexed:
2233 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2234 << VectorList.Count << " * " << VectorList.RegNum << ">";
2235 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002236 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002237 OS << "'" << getToken() << "'";
2238 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002239 case k_VectorIndex:
2240 OS << "<vectorindex " << getVectorIndex() << ">";
2241 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002242 }
2243}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002244
2245/// @name Auto-generated Match Functions
2246/// {
2247
2248static unsigned MatchRegisterName(StringRef Name);
2249
2250/// }
2251
Bob Wilson69df7232011-02-03 21:46:10 +00002252bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2253 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002254 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002255 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002256 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002257
2258 return (RegNo == (unsigned)-1);
2259}
2260
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002261/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002262/// and if it is a register name the token is eaten and the register number is
2263/// returned. Otherwise return -1.
2264///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002265int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002266 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002267 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002268
Benjamin Kramer59085362011-11-06 20:37:06 +00002269 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002270 unsigned RegNum = MatchRegisterName(lowerCase);
2271 if (!RegNum) {
2272 RegNum = StringSwitch<unsigned>(lowerCase)
2273 .Case("r13", ARM::SP)
2274 .Case("r14", ARM::LR)
2275 .Case("r15", ARM::PC)
2276 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002277 // Additional register name aliases for 'gas' compatibility.
2278 .Case("a1", ARM::R0)
2279 .Case("a2", ARM::R1)
2280 .Case("a3", ARM::R2)
2281 .Case("a4", ARM::R3)
2282 .Case("v1", ARM::R4)
2283 .Case("v2", ARM::R5)
2284 .Case("v3", ARM::R6)
2285 .Case("v4", ARM::R7)
2286 .Case("v5", ARM::R8)
2287 .Case("v6", ARM::R9)
2288 .Case("v7", ARM::R10)
2289 .Case("v8", ARM::R11)
2290 .Case("sb", ARM::R9)
2291 .Case("sl", ARM::R10)
2292 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002293 .Default(0);
2294 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002295 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002296 // Check for aliases registered via .req. Canonicalize to lower case.
2297 // That's more consistent since register names are case insensitive, and
2298 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2299 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002300 // If no match, return failure.
2301 if (Entry == RegisterReqs.end())
2302 return -1;
2303 Parser.Lex(); // Eat identifier token.
2304 return Entry->getValue();
2305 }
Bob Wilson69df7232011-02-03 21:46:10 +00002306
Chris Lattnere5658fa2010-10-30 04:09:10 +00002307 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002308
Chris Lattnere5658fa2010-10-30 04:09:10 +00002309 return RegNum;
2310}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002311
Jim Grosbach19906722011-07-13 18:49:30 +00002312// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2313// If a recoverable error occurs, return 1. If an irrecoverable error
2314// occurs, return -1. An irrecoverable error is one where tokens have been
2315// consumed in the process of trying to parse the shifter (i.e., when it is
2316// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002317int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002318 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2319 SMLoc S = Parser.getTok().getLoc();
2320 const AsmToken &Tok = Parser.getTok();
2321 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2322
Benjamin Kramer59085362011-11-06 20:37:06 +00002323 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002324 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002325 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002326 .Case("lsl", ARM_AM::lsl)
2327 .Case("lsr", ARM_AM::lsr)
2328 .Case("asr", ARM_AM::asr)
2329 .Case("ror", ARM_AM::ror)
2330 .Case("rrx", ARM_AM::rrx)
2331 .Default(ARM_AM::no_shift);
2332
2333 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002334 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002335
Jim Grosbache8606dc2011-07-13 17:50:29 +00002336 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002337
Jim Grosbache8606dc2011-07-13 17:50:29 +00002338 // The source register for the shift has already been added to the
2339 // operand list, so we need to pop it off and combine it into the shifted
2340 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002341 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002342 if (!PrevOp->isReg())
2343 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2344 int SrcReg = PrevOp->getReg();
2345 int64_t Imm = 0;
2346 int ShiftReg = 0;
2347 if (ShiftTy == ARM_AM::rrx) {
2348 // RRX Doesn't have an explicit shift amount. The encoder expects
2349 // the shift register to be the same as the source register. Seems odd,
2350 // but OK.
2351 ShiftReg = SrcReg;
2352 } else {
2353 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002354 if (Parser.getTok().is(AsmToken::Hash) ||
2355 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002356 Parser.Lex(); // Eat hash.
2357 SMLoc ImmLoc = Parser.getTok().getLoc();
2358 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002359 if (getParser().ParseExpression(ShiftExpr)) {
2360 Error(ImmLoc, "invalid immediate shift value");
2361 return -1;
2362 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002363 // The expression must be evaluatable as an immediate.
2364 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002365 if (!CE) {
2366 Error(ImmLoc, "invalid immediate shift value");
2367 return -1;
2368 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002369 // Range check the immediate.
2370 // lsl, ror: 0 <= imm <= 31
2371 // lsr, asr: 0 <= imm <= 32
2372 Imm = CE->getValue();
2373 if (Imm < 0 ||
2374 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2375 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002376 Error(ImmLoc, "immediate shift value out of range");
2377 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002378 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002379 // shift by zero is a nop. Always send it through as lsl.
2380 // ('as' compatibility)
2381 if (Imm == 0)
2382 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002383 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002384 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002385 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002386 if (ShiftReg == -1) {
2387 Error (L, "expected immediate or register in shift operand");
2388 return -1;
2389 }
2390 } else {
2391 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002392 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002393 return -1;
2394 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002395 }
2396
Owen Anderson92a20222011-07-21 18:54:16 +00002397 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2398 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002399 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002400 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002401 else
2402 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2403 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002404
Jim Grosbach19906722011-07-13 18:49:30 +00002405 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002406}
2407
2408
Bill Wendling50d0f582010-11-18 23:43:05 +00002409/// Try to parse a register name. The token must be an Identifier when called.
2410/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2411/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002412///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002413/// TODO this is likely to change to allow different register types and or to
2414/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002415bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002416tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002417 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002418 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002419 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002420 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002421
Bill Wendling50d0f582010-11-18 23:43:05 +00002422 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002423
Chris Lattnere5658fa2010-10-30 04:09:10 +00002424 const AsmToken &ExclaimTok = Parser.getTok();
2425 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002426 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2427 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002428 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002429 return false;
2430 }
2431
2432 // Also check for an index operand. This is only legal for vector registers,
2433 // but that'll get caught OK in operand matching, so we don't need to
2434 // explicitly filter everything else out here.
2435 if (Parser.getTok().is(AsmToken::LBrac)) {
2436 SMLoc SIdx = Parser.getTok().getLoc();
2437 Parser.Lex(); // Eat left bracket token.
2438
2439 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002440 if (getParser().ParseExpression(ImmVal))
2441 return MatchOperand_ParseFail;
2442 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2443 if (!MCE) {
2444 TokError("immediate value expected for vector index");
2445 return MatchOperand_ParseFail;
2446 }
2447
2448 SMLoc E = Parser.getTok().getLoc();
2449 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2450 Error(E, "']' expected");
2451 return MatchOperand_ParseFail;
2452 }
2453
2454 Parser.Lex(); // Eat right bracket token.
2455
2456 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2457 SIdx, E,
2458 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002459 }
2460
Bill Wendling50d0f582010-11-18 23:43:05 +00002461 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002462}
2463
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002464/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2465/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2466/// "c5", ...
2467static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002468 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2469 // but efficient.
2470 switch (Name.size()) {
2471 default: break;
2472 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002473 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002474 return -1;
2475 switch (Name[1]) {
2476 default: return -1;
2477 case '0': return 0;
2478 case '1': return 1;
2479 case '2': return 2;
2480 case '3': return 3;
2481 case '4': return 4;
2482 case '5': return 5;
2483 case '6': return 6;
2484 case '7': return 7;
2485 case '8': return 8;
2486 case '9': return 9;
2487 }
2488 break;
2489 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002490 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002491 return -1;
2492 switch (Name[2]) {
2493 default: return -1;
2494 case '0': return 10;
2495 case '1': return 11;
2496 case '2': return 12;
2497 case '3': return 13;
2498 case '4': return 14;
2499 case '5': return 15;
2500 }
2501 break;
2502 }
2503
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002504 return -1;
2505}
2506
Jim Grosbach89df9962011-08-26 21:43:41 +00002507/// parseITCondCode - Try to parse a condition code for an IT instruction.
2508ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2509parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2510 SMLoc S = Parser.getTok().getLoc();
2511 const AsmToken &Tok = Parser.getTok();
2512 if (!Tok.is(AsmToken::Identifier))
2513 return MatchOperand_NoMatch;
2514 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2515 .Case("eq", ARMCC::EQ)
2516 .Case("ne", ARMCC::NE)
2517 .Case("hs", ARMCC::HS)
2518 .Case("cs", ARMCC::HS)
2519 .Case("lo", ARMCC::LO)
2520 .Case("cc", ARMCC::LO)
2521 .Case("mi", ARMCC::MI)
2522 .Case("pl", ARMCC::PL)
2523 .Case("vs", ARMCC::VS)
2524 .Case("vc", ARMCC::VC)
2525 .Case("hi", ARMCC::HI)
2526 .Case("ls", ARMCC::LS)
2527 .Case("ge", ARMCC::GE)
2528 .Case("lt", ARMCC::LT)
2529 .Case("gt", ARMCC::GT)
2530 .Case("le", ARMCC::LE)
2531 .Case("al", ARMCC::AL)
2532 .Default(~0U);
2533 if (CC == ~0U)
2534 return MatchOperand_NoMatch;
2535 Parser.Lex(); // Eat the token.
2536
2537 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2538
2539 return MatchOperand_Success;
2540}
2541
Jim Grosbach43904292011-07-25 20:14:50 +00002542/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002543/// token must be an Identifier when called, and if it is a coprocessor
2544/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002545ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002546parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002547 SMLoc S = Parser.getTok().getLoc();
2548 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002549 if (Tok.isNot(AsmToken::Identifier))
2550 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002551
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002552 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002553 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002554 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002555
2556 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002557 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002558 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002559}
2560
Jim Grosbach43904292011-07-25 20:14:50 +00002561/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002562/// token must be an Identifier when called, and if it is a coprocessor
2563/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002564ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002565parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002566 SMLoc S = Parser.getTok().getLoc();
2567 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002568 if (Tok.isNot(AsmToken::Identifier))
2569 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002570
2571 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2572 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002573 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002574
2575 Parser.Lex(); // Eat identifier token.
2576 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002577 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002578}
2579
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002580/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2581/// coproc_option : '{' imm0_255 '}'
2582ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2583parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2584 SMLoc S = Parser.getTok().getLoc();
2585
2586 // If this isn't a '{', this isn't a coprocessor immediate operand.
2587 if (Parser.getTok().isNot(AsmToken::LCurly))
2588 return MatchOperand_NoMatch;
2589 Parser.Lex(); // Eat the '{'
2590
2591 const MCExpr *Expr;
2592 SMLoc Loc = Parser.getTok().getLoc();
2593 if (getParser().ParseExpression(Expr)) {
2594 Error(Loc, "illegal expression");
2595 return MatchOperand_ParseFail;
2596 }
2597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2598 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2599 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2600 return MatchOperand_ParseFail;
2601 }
2602 int Val = CE->getValue();
2603
2604 // Check for and consume the closing '}'
2605 if (Parser.getTok().isNot(AsmToken::RCurly))
2606 return MatchOperand_ParseFail;
2607 SMLoc E = Parser.getTok().getLoc();
2608 Parser.Lex(); // Eat the '}'
2609
2610 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2611 return MatchOperand_Success;
2612}
2613
Jim Grosbachd0588e22011-09-14 18:08:35 +00002614// For register list parsing, we need to map from raw GPR register numbering
2615// to the enumeration values. The enumeration values aren't sorted by
2616// register number due to our using "sp", "lr" and "pc" as canonical names.
2617static unsigned getNextRegister(unsigned Reg) {
2618 // If this is a GPR, we need to do it manually, otherwise we can rely
2619 // on the sort ordering of the enumeration since the other reg-classes
2620 // are sane.
2621 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2622 return Reg + 1;
2623 switch(Reg) {
2624 default: assert(0 && "Invalid GPR number!");
2625 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2626 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2627 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2628 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2629 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2630 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2631 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2632 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2633 }
2634}
2635
Jim Grosbachce485e72011-11-11 21:27:40 +00002636// Return the low-subreg of a given Q register.
2637static unsigned getDRegFromQReg(unsigned QReg) {
2638 switch (QReg) {
2639 default: llvm_unreachable("expected a Q register!");
2640 case ARM::Q0: return ARM::D0;
2641 case ARM::Q1: return ARM::D2;
2642 case ARM::Q2: return ARM::D4;
2643 case ARM::Q3: return ARM::D6;
2644 case ARM::Q4: return ARM::D8;
2645 case ARM::Q5: return ARM::D10;
2646 case ARM::Q6: return ARM::D12;
2647 case ARM::Q7: return ARM::D14;
2648 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002649 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002650 case ARM::Q10: return ARM::D20;
2651 case ARM::Q11: return ARM::D22;
2652 case ARM::Q12: return ARM::D24;
2653 case ARM::Q13: return ARM::D26;
2654 case ARM::Q14: return ARM::D28;
2655 case ARM::Q15: return ARM::D30;
2656 }
2657}
2658
Jim Grosbachd0588e22011-09-14 18:08:35 +00002659/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002660bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002661parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002662 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002663 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002664 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002665 Parser.Lex(); // Eat '{' token.
2666 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002667
Jim Grosbachd0588e22011-09-14 18:08:35 +00002668 // Check the first register in the list to see what register class
2669 // this is a list of.
2670 int Reg = tryParseRegister();
2671 if (Reg == -1)
2672 return Error(RegLoc, "register expected");
2673
Jim Grosbachce485e72011-11-11 21:27:40 +00002674 // The reglist instructions have at most 16 registers, so reserve
2675 // space for that many.
2676 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2677
2678 // Allow Q regs and just interpret them as the two D sub-registers.
2679 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2680 Reg = getDRegFromQReg(Reg);
2681 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2682 ++Reg;
2683 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002684 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002685 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2686 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2687 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2688 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2689 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2690 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2691 else
2692 return Error(RegLoc, "invalid register in register list");
2693
Jim Grosbachce485e72011-11-11 21:27:40 +00002694 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002695 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002696
Jim Grosbachd0588e22011-09-14 18:08:35 +00002697 // This starts immediately after the first register token in the list,
2698 // so we can see either a comma or a minus (range separator) as a legal
2699 // next token.
2700 while (Parser.getTok().is(AsmToken::Comma) ||
2701 Parser.getTok().is(AsmToken::Minus)) {
2702 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002703 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002704 SMLoc EndLoc = Parser.getTok().getLoc();
2705 int EndReg = tryParseRegister();
2706 if (EndReg == -1)
2707 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002708 // Allow Q regs and just interpret them as the two D sub-registers.
2709 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2710 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002711 // If the register is the same as the start reg, there's nothing
2712 // more to do.
2713 if (Reg == EndReg)
2714 continue;
2715 // The register must be in the same register class as the first.
2716 if (!RC->contains(EndReg))
2717 return Error(EndLoc, "invalid register in register list");
2718 // Ranges must go from low to high.
2719 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2720 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002721
Jim Grosbachd0588e22011-09-14 18:08:35 +00002722 // Add all the registers in the range to the register list.
2723 while (Reg != EndReg) {
2724 Reg = getNextRegister(Reg);
2725 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2726 }
2727 continue;
2728 }
2729 Parser.Lex(); // Eat the comma.
2730 RegLoc = Parser.getTok().getLoc();
2731 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002732 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002733 Reg = tryParseRegister();
2734 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002735 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002736 // Allow Q regs and just interpret them as the two D sub-registers.
2737 bool isQReg = false;
2738 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2739 Reg = getDRegFromQReg(Reg);
2740 isQReg = true;
2741 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002742 // The register must be in the same register class as the first.
2743 if (!RC->contains(Reg))
2744 return Error(RegLoc, "invalid register in register list");
2745 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002746 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002747 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002748 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2749 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2750 ") in register list");
2751 continue;
2752 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002753 // VFP register lists must also be contiguous.
2754 // It's OK to use the enumeration values directly here rather, as the
2755 // VFP register classes have the enum sorted properly.
2756 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2757 Reg != OldReg + 1)
2758 return Error(RegLoc, "non-contiguous register range");
2759 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002760 if (isQReg)
2761 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002762 }
2763
Jim Grosbachd0588e22011-09-14 18:08:35 +00002764 SMLoc E = Parser.getTok().getLoc();
2765 if (Parser.getTok().isNot(AsmToken::RCurly))
2766 return Error(E, "'}' expected");
2767 Parser.Lex(); // Eat '}' token.
2768
Jim Grosbach27debd62011-12-13 21:48:29 +00002769 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002770 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002771
2772 // The ARM system instruction variants for LDM/STM have a '^' token here.
2773 if (Parser.getTok().is(AsmToken::Caret)) {
2774 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2775 Parser.Lex(); // Eat '^' token.
2776 }
2777
Bill Wendling50d0f582010-11-18 23:43:05 +00002778 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002779}
2780
Jim Grosbach98b05a52011-11-30 01:09:44 +00002781// Helper function to parse the lane index for vector lists.
2782ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002783parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2784 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002785 if (Parser.getTok().is(AsmToken::LBrac)) {
2786 Parser.Lex(); // Eat the '['.
2787 if (Parser.getTok().is(AsmToken::RBrac)) {
2788 // "Dn[]" is the 'all lanes' syntax.
2789 LaneKind = AllLanes;
2790 Parser.Lex(); // Eat the ']'.
2791 return MatchOperand_Success;
2792 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002793 const MCExpr *LaneIndex;
2794 SMLoc Loc = Parser.getTok().getLoc();
2795 if (getParser().ParseExpression(LaneIndex)) {
2796 Error(Loc, "illegal expression");
2797 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002798 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2800 if (!CE) {
2801 Error(Loc, "lane index must be empty or an integer");
2802 return MatchOperand_ParseFail;
2803 }
2804 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2805 Error(Parser.getTok().getLoc(), "']' expected");
2806 return MatchOperand_ParseFail;
2807 }
2808 Parser.Lex(); // Eat the ']'.
2809 int64_t Val = CE->getValue();
2810
2811 // FIXME: Make this range check context sensitive for .8, .16, .32.
2812 if (Val < 0 || Val > 7) {
2813 Error(Parser.getTok().getLoc(), "lane index out of range");
2814 return MatchOperand_ParseFail;
2815 }
2816 Index = Val;
2817 LaneKind = IndexedLane;
2818 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002819 }
2820 LaneKind = NoLanes;
2821 return MatchOperand_Success;
2822}
2823
Jim Grosbach862019c2011-10-18 23:02:30 +00002824// parse a vector register list
2825ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2826parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002827 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002828 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002829 SMLoc S = Parser.getTok().getLoc();
2830 // As an extension (to match gas), support a plain D register or Q register
2831 // (without encosing curly braces) as a single or double entry list,
2832 // respectively.
2833 if (Parser.getTok().is(AsmToken::Identifier)) {
2834 int Reg = tryParseRegister();
2835 if (Reg == -1)
2836 return MatchOperand_NoMatch;
2837 SMLoc E = Parser.getTok().getLoc();
2838 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002839 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002840 if (Res != MatchOperand_Success)
2841 return Res;
2842 switch (LaneKind) {
2843 default:
2844 assert(0 && "unexpected lane kind!");
2845 case NoLanes:
2846 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002847 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002848 break;
2849 case AllLanes:
2850 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002851 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
2852 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002853 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002854 case IndexedLane:
2855 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002856 LaneIndex,
2857 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002858 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002859 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002860 return MatchOperand_Success;
2861 }
2862 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2863 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002864 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002865 if (Res != MatchOperand_Success)
2866 return Res;
2867 switch (LaneKind) {
2868 default:
2869 assert(0 && "unexpected lane kind!");
2870 case NoLanes:
2871 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002872 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002873 break;
2874 case AllLanes:
2875 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002876 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
2877 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002878 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002879 case IndexedLane:
2880 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002881 LaneIndex,
2882 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002883 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002884 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002885 return MatchOperand_Success;
2886 }
2887 Error(S, "vector register expected");
2888 return MatchOperand_ParseFail;
2889 }
2890
2891 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002892 return MatchOperand_NoMatch;
2893
Jim Grosbach862019c2011-10-18 23:02:30 +00002894 Parser.Lex(); // Eat '{' token.
2895 SMLoc RegLoc = Parser.getTok().getLoc();
2896
2897 int Reg = tryParseRegister();
2898 if (Reg == -1) {
2899 Error(RegLoc, "register expected");
2900 return MatchOperand_ParseFail;
2901 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002902 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002903 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002904 unsigned FirstReg = Reg;
2905 // The list is of D registers, but we also allow Q regs and just interpret
2906 // them as the two D sub-registers.
2907 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2908 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002909 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2910 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002911 ++Reg;
2912 ++Count;
2913 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002914 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002915 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002916
Jim Grosbache43862b2011-11-15 23:19:15 +00002917 while (Parser.getTok().is(AsmToken::Comma) ||
2918 Parser.getTok().is(AsmToken::Minus)) {
2919 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002920 if (!Spacing)
2921 Spacing = 1; // Register range implies a single spaced list.
2922 else if (Spacing == 2) {
2923 Error(Parser.getTok().getLoc(),
2924 "sequential registers in double spaced list");
2925 return MatchOperand_ParseFail;
2926 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002927 Parser.Lex(); // Eat the minus.
2928 SMLoc EndLoc = Parser.getTok().getLoc();
2929 int EndReg = tryParseRegister();
2930 if (EndReg == -1) {
2931 Error(EndLoc, "register expected");
2932 return MatchOperand_ParseFail;
2933 }
2934 // Allow Q regs and just interpret them as the two D sub-registers.
2935 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2936 EndReg = getDRegFromQReg(EndReg) + 1;
2937 // If the register is the same as the start reg, there's nothing
2938 // more to do.
2939 if (Reg == EndReg)
2940 continue;
2941 // The register must be in the same register class as the first.
2942 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2943 Error(EndLoc, "invalid register in register list");
2944 return MatchOperand_ParseFail;
2945 }
2946 // Ranges must go from low to high.
2947 if (Reg > EndReg) {
2948 Error(EndLoc, "bad range in register list");
2949 return MatchOperand_ParseFail;
2950 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002951 // Parse the lane specifier if present.
2952 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002953 unsigned NextLaneIndex;
2954 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002955 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002956 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002957 Error(EndLoc, "mismatched lane index in register list");
2958 return MatchOperand_ParseFail;
2959 }
2960 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002961
2962 // Add all the registers in the range to the register list.
2963 Count += EndReg - Reg;
2964 Reg = EndReg;
2965 continue;
2966 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002967 Parser.Lex(); // Eat the comma.
2968 RegLoc = Parser.getTok().getLoc();
2969 int OldReg = Reg;
2970 Reg = tryParseRegister();
2971 if (Reg == -1) {
2972 Error(RegLoc, "register expected");
2973 return MatchOperand_ParseFail;
2974 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002975 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002976 // It's OK to use the enumeration values directly here rather, as the
2977 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002978 //
2979 // The list is of D registers, but we also allow Q regs and just interpret
2980 // them as the two D sub-registers.
2981 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002982 if (!Spacing)
2983 Spacing = 1; // Register range implies a single spaced list.
2984 else if (Spacing == 2) {
2985 Error(RegLoc,
2986 "invalid register in double-spaced list (must be 'D' register')");
2987 return MatchOperand_ParseFail;
2988 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002989 Reg = getDRegFromQReg(Reg);
2990 if (Reg != OldReg + 1) {
2991 Error(RegLoc, "non-contiguous register range");
2992 return MatchOperand_ParseFail;
2993 }
2994 ++Reg;
2995 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002996 // Parse the lane specifier if present.
2997 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002998 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002999 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003000 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003001 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003002 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003003 Error(EndLoc, "mismatched lane index in register list");
3004 return MatchOperand_ParseFail;
3005 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003006 continue;
3007 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003008 // Normal D register.
3009 // Figure out the register spacing (single or double) of the list if
3010 // we don't know it already.
3011 if (!Spacing)
3012 Spacing = 1 + (Reg == OldReg + 2);
3013
3014 // Just check that it's contiguous and keep going.
3015 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003016 Error(RegLoc, "non-contiguous register range");
3017 return MatchOperand_ParseFail;
3018 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003019 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003020 // Parse the lane specifier if present.
3021 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003022 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003023 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003024 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003025 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003026 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003027 Error(EndLoc, "mismatched lane index in register list");
3028 return MatchOperand_ParseFail;
3029 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003030 }
3031
3032 SMLoc E = Parser.getTok().getLoc();
3033 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3034 Error(E, "'}' expected");
3035 return MatchOperand_ParseFail;
3036 }
3037 Parser.Lex(); // Eat '}' token.
3038
Jim Grosbach98b05a52011-11-30 01:09:44 +00003039 switch (LaneKind) {
3040 default:
3041 assert(0 && "unexpected lane kind in register list.");
3042 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003043 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3044 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003045 break;
3046 case AllLanes:
3047 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003048 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 S, E));
3050 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003051 case IndexedLane:
3052 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003053 LaneIndex,
3054 (Spacing == 2),
3055 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003056 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003057 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003058 return MatchOperand_Success;
3059}
3060
Jim Grosbach43904292011-07-25 20:14:50 +00003061/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003062ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003063parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003064 SMLoc S = Parser.getTok().getLoc();
3065 const AsmToken &Tok = Parser.getTok();
3066 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3067 StringRef OptStr = Tok.getString();
3068
3069 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3070 .Case("sy", ARM_MB::SY)
3071 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003072 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003073 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003074 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003075 .Case("ishst", ARM_MB::ISHST)
3076 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003077 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003078 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003079 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003080 .Case("osh", ARM_MB::OSH)
3081 .Case("oshst", ARM_MB::OSHST)
3082 .Default(~0U);
3083
3084 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003085 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003086
3087 Parser.Lex(); // Eat identifier token.
3088 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003089 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003090}
3091
Jim Grosbach43904292011-07-25 20:14:50 +00003092/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003093ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003094parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003095 SMLoc S = Parser.getTok().getLoc();
3096 const AsmToken &Tok = Parser.getTok();
3097 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3098 StringRef IFlagsStr = Tok.getString();
3099
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003100 // An iflags string of "none" is interpreted to mean that none of the AIF
3101 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003102 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003103 if (IFlagsStr != "none") {
3104 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3105 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3106 .Case("a", ARM_PROC::A)
3107 .Case("i", ARM_PROC::I)
3108 .Case("f", ARM_PROC::F)
3109 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003110
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003111 // If some specific iflag is already set, it means that some letter is
3112 // present more than once, this is not acceptable.
3113 if (Flag == ~0U || (IFlags & Flag))
3114 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003115
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003116 IFlags |= Flag;
3117 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003118 }
3119
3120 Parser.Lex(); // Eat identifier token.
3121 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3122 return MatchOperand_Success;
3123}
3124
Jim Grosbach43904292011-07-25 20:14:50 +00003125/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003126ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003127parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003128 SMLoc S = Parser.getTok().getLoc();
3129 const AsmToken &Tok = Parser.getTok();
3130 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3131 StringRef Mask = Tok.getString();
3132
James Molloyacad68d2011-09-28 14:21:38 +00003133 if (isMClass()) {
3134 // See ARMv6-M 10.1.1
3135 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3136 .Case("apsr", 0)
3137 .Case("iapsr", 1)
3138 .Case("eapsr", 2)
3139 .Case("xpsr", 3)
3140 .Case("ipsr", 5)
3141 .Case("epsr", 6)
3142 .Case("iepsr", 7)
3143 .Case("msp", 8)
3144 .Case("psp", 9)
3145 .Case("primask", 16)
3146 .Case("basepri", 17)
3147 .Case("basepri_max", 18)
3148 .Case("faultmask", 19)
3149 .Case("control", 20)
3150 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003151
James Molloyacad68d2011-09-28 14:21:38 +00003152 if (FlagsVal == ~0U)
3153 return MatchOperand_NoMatch;
3154
3155 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3156 // basepri, basepri_max and faultmask only valid for V7m.
3157 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003158
James Molloyacad68d2011-09-28 14:21:38 +00003159 Parser.Lex(); // Eat identifier token.
3160 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3161 return MatchOperand_Success;
3162 }
3163
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003164 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3165 size_t Start = 0, Next = Mask.find('_');
3166 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003167 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003168 if (Next != StringRef::npos)
3169 Flags = Mask.slice(Next+1, Mask.size());
3170
3171 // FlagsVal contains the complete mask:
3172 // 3-0: Mask
3173 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3174 unsigned FlagsVal = 0;
3175
3176 if (SpecReg == "apsr") {
3177 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003178 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003179 .Case("g", 0x4) // same as CPSR_s
3180 .Case("nzcvqg", 0xc) // same as CPSR_fs
3181 .Default(~0U);
3182
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003183 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003184 if (!Flags.empty())
3185 return MatchOperand_NoMatch;
3186 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003187 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003188 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003189 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003190 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3191 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003192 for (int i = 0, e = Flags.size(); i != e; ++i) {
3193 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3194 .Case("c", 1)
3195 .Case("x", 2)
3196 .Case("s", 4)
3197 .Case("f", 8)
3198 .Default(~0U);
3199
3200 // If some specific flag is already set, it means that some letter is
3201 // present more than once, this is not acceptable.
3202 if (FlagsVal == ~0U || (FlagsVal & Flag))
3203 return MatchOperand_NoMatch;
3204 FlagsVal |= Flag;
3205 }
3206 } else // No match for special register.
3207 return MatchOperand_NoMatch;
3208
Owen Anderson7784f1d2011-10-21 18:43:28 +00003209 // Special register without flags is NOT equivalent to "fc" flags.
3210 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3211 // two lines would enable gas compatibility at the expense of breaking
3212 // round-tripping.
3213 //
3214 // if (!FlagsVal)
3215 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003216
3217 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3218 if (SpecReg == "spsr")
3219 FlagsVal |= 16;
3220
3221 Parser.Lex(); // Eat identifier token.
3222 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3223 return MatchOperand_Success;
3224}
3225
Jim Grosbachf6c05252011-07-21 17:23:04 +00003226ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3227parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3228 int Low, int High) {
3229 const AsmToken &Tok = Parser.getTok();
3230 if (Tok.isNot(AsmToken::Identifier)) {
3231 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3232 return MatchOperand_ParseFail;
3233 }
3234 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003235 std::string LowerOp = Op.lower();
3236 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003237 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3238 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3239 return MatchOperand_ParseFail;
3240 }
3241 Parser.Lex(); // Eat shift type token.
3242
3243 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003244 if (Parser.getTok().isNot(AsmToken::Hash) &&
3245 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003246 Error(Parser.getTok().getLoc(), "'#' expected");
3247 return MatchOperand_ParseFail;
3248 }
3249 Parser.Lex(); // Eat hash token.
3250
3251 const MCExpr *ShiftAmount;
3252 SMLoc Loc = Parser.getTok().getLoc();
3253 if (getParser().ParseExpression(ShiftAmount)) {
3254 Error(Loc, "illegal expression");
3255 return MatchOperand_ParseFail;
3256 }
3257 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3258 if (!CE) {
3259 Error(Loc, "constant expression expected");
3260 return MatchOperand_ParseFail;
3261 }
3262 int Val = CE->getValue();
3263 if (Val < Low || Val > High) {
3264 Error(Loc, "immediate value out of range");
3265 return MatchOperand_ParseFail;
3266 }
3267
3268 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3269
3270 return MatchOperand_Success;
3271}
3272
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003273ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3274parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3275 const AsmToken &Tok = Parser.getTok();
3276 SMLoc S = Tok.getLoc();
3277 if (Tok.isNot(AsmToken::Identifier)) {
3278 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3279 return MatchOperand_ParseFail;
3280 }
3281 int Val = StringSwitch<int>(Tok.getString())
3282 .Case("be", 1)
3283 .Case("le", 0)
3284 .Default(-1);
3285 Parser.Lex(); // Eat the token.
3286
3287 if (Val == -1) {
3288 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3289 return MatchOperand_ParseFail;
3290 }
3291 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3292 getContext()),
3293 S, Parser.getTok().getLoc()));
3294 return MatchOperand_Success;
3295}
3296
Jim Grosbach580f4a92011-07-25 22:20:28 +00003297/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3298/// instructions. Legal values are:
3299/// lsl #n 'n' in [0,31]
3300/// asr #n 'n' in [1,32]
3301/// n == 32 encoded as n == 0.
3302ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3303parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3304 const AsmToken &Tok = Parser.getTok();
3305 SMLoc S = Tok.getLoc();
3306 if (Tok.isNot(AsmToken::Identifier)) {
3307 Error(S, "shift operator 'asr' or 'lsl' expected");
3308 return MatchOperand_ParseFail;
3309 }
3310 StringRef ShiftName = Tok.getString();
3311 bool isASR;
3312 if (ShiftName == "lsl" || ShiftName == "LSL")
3313 isASR = false;
3314 else if (ShiftName == "asr" || ShiftName == "ASR")
3315 isASR = true;
3316 else {
3317 Error(S, "shift operator 'asr' or 'lsl' expected");
3318 return MatchOperand_ParseFail;
3319 }
3320 Parser.Lex(); // Eat the operator.
3321
3322 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003323 if (Parser.getTok().isNot(AsmToken::Hash) &&
3324 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003325 Error(Parser.getTok().getLoc(), "'#' expected");
3326 return MatchOperand_ParseFail;
3327 }
3328 Parser.Lex(); // Eat hash token.
3329
3330 const MCExpr *ShiftAmount;
3331 SMLoc E = Parser.getTok().getLoc();
3332 if (getParser().ParseExpression(ShiftAmount)) {
3333 Error(E, "malformed shift expression");
3334 return MatchOperand_ParseFail;
3335 }
3336 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3337 if (!CE) {
3338 Error(E, "shift amount must be an immediate");
3339 return MatchOperand_ParseFail;
3340 }
3341
3342 int64_t Val = CE->getValue();
3343 if (isASR) {
3344 // Shift amount must be in [1,32]
3345 if (Val < 1 || Val > 32) {
3346 Error(E, "'asr' shift amount must be in range [1,32]");
3347 return MatchOperand_ParseFail;
3348 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003349 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3350 if (isThumb() && Val == 32) {
3351 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3352 return MatchOperand_ParseFail;
3353 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003354 if (Val == 32) Val = 0;
3355 } else {
3356 // Shift amount must be in [1,32]
3357 if (Val < 0 || Val > 31) {
3358 Error(E, "'lsr' shift amount must be in range [0,31]");
3359 return MatchOperand_ParseFail;
3360 }
3361 }
3362
3363 E = Parser.getTok().getLoc();
3364 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3365
3366 return MatchOperand_Success;
3367}
3368
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003369/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3370/// of instructions. Legal values are:
3371/// ror #n 'n' in {0, 8, 16, 24}
3372ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3373parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3374 const AsmToken &Tok = Parser.getTok();
3375 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003376 if (Tok.isNot(AsmToken::Identifier))
3377 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003378 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003379 if (ShiftName != "ror" && ShiftName != "ROR")
3380 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003381 Parser.Lex(); // Eat the operator.
3382
3383 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003384 if (Parser.getTok().isNot(AsmToken::Hash) &&
3385 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003386 Error(Parser.getTok().getLoc(), "'#' expected");
3387 return MatchOperand_ParseFail;
3388 }
3389 Parser.Lex(); // Eat hash token.
3390
3391 const MCExpr *ShiftAmount;
3392 SMLoc E = Parser.getTok().getLoc();
3393 if (getParser().ParseExpression(ShiftAmount)) {
3394 Error(E, "malformed rotate expression");
3395 return MatchOperand_ParseFail;
3396 }
3397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3398 if (!CE) {
3399 Error(E, "rotate amount must be an immediate");
3400 return MatchOperand_ParseFail;
3401 }
3402
3403 int64_t Val = CE->getValue();
3404 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3405 // normally, zero is represented in asm by omitting the rotate operand
3406 // entirely.
3407 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3408 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3409 return MatchOperand_ParseFail;
3410 }
3411
3412 E = Parser.getTok().getLoc();
3413 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3414
3415 return MatchOperand_Success;
3416}
3417
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003418ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3419parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3420 SMLoc S = Parser.getTok().getLoc();
3421 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003422 if (Parser.getTok().isNot(AsmToken::Hash) &&
3423 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003424 Error(Parser.getTok().getLoc(), "'#' expected");
3425 return MatchOperand_ParseFail;
3426 }
3427 Parser.Lex(); // Eat hash token.
3428
3429 const MCExpr *LSBExpr;
3430 SMLoc E = Parser.getTok().getLoc();
3431 if (getParser().ParseExpression(LSBExpr)) {
3432 Error(E, "malformed immediate expression");
3433 return MatchOperand_ParseFail;
3434 }
3435 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3436 if (!CE) {
3437 Error(E, "'lsb' operand must be an immediate");
3438 return MatchOperand_ParseFail;
3439 }
3440
3441 int64_t LSB = CE->getValue();
3442 // The LSB must be in the range [0,31]
3443 if (LSB < 0 || LSB > 31) {
3444 Error(E, "'lsb' operand must be in the range [0,31]");
3445 return MatchOperand_ParseFail;
3446 }
3447 E = Parser.getTok().getLoc();
3448
3449 // Expect another immediate operand.
3450 if (Parser.getTok().isNot(AsmToken::Comma)) {
3451 Error(Parser.getTok().getLoc(), "too few operands");
3452 return MatchOperand_ParseFail;
3453 }
3454 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003455 if (Parser.getTok().isNot(AsmToken::Hash) &&
3456 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003457 Error(Parser.getTok().getLoc(), "'#' expected");
3458 return MatchOperand_ParseFail;
3459 }
3460 Parser.Lex(); // Eat hash token.
3461
3462 const MCExpr *WidthExpr;
3463 if (getParser().ParseExpression(WidthExpr)) {
3464 Error(E, "malformed immediate expression");
3465 return MatchOperand_ParseFail;
3466 }
3467 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3468 if (!CE) {
3469 Error(E, "'width' operand must be an immediate");
3470 return MatchOperand_ParseFail;
3471 }
3472
3473 int64_t Width = CE->getValue();
3474 // The LSB must be in the range [1,32-lsb]
3475 if (Width < 1 || Width > 32 - LSB) {
3476 Error(E, "'width' operand must be in the range [1,32-lsb]");
3477 return MatchOperand_ParseFail;
3478 }
3479 E = Parser.getTok().getLoc();
3480
3481 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3482
3483 return MatchOperand_Success;
3484}
3485
Jim Grosbach7ce05792011-08-03 23:50:40 +00003486ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3487parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3488 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003489 // postidx_reg := '+' register {, shift}
3490 // | '-' register {, shift}
3491 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003492
3493 // This method must return MatchOperand_NoMatch without consuming any tokens
3494 // in the case where there is no match, as other alternatives take other
3495 // parse methods.
3496 AsmToken Tok = Parser.getTok();
3497 SMLoc S = Tok.getLoc();
3498 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003499 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003500 int Reg = -1;
3501 if (Tok.is(AsmToken::Plus)) {
3502 Parser.Lex(); // Eat the '+' token.
3503 haveEaten = true;
3504 } else if (Tok.is(AsmToken::Minus)) {
3505 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003506 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003507 haveEaten = true;
3508 }
3509 if (Parser.getTok().is(AsmToken::Identifier))
3510 Reg = tryParseRegister();
3511 if (Reg == -1) {
3512 if (!haveEaten)
3513 return MatchOperand_NoMatch;
3514 Error(Parser.getTok().getLoc(), "register expected");
3515 return MatchOperand_ParseFail;
3516 }
3517 SMLoc E = Parser.getTok().getLoc();
3518
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003519 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3520 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003521 if (Parser.getTok().is(AsmToken::Comma)) {
3522 Parser.Lex(); // Eat the ','.
3523 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3524 return MatchOperand_ParseFail;
3525 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003526
3527 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3528 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003529
3530 return MatchOperand_Success;
3531}
3532
Jim Grosbach251bf252011-08-10 21:56:18 +00003533ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3534parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3535 // Check for a post-index addressing register operand. Specifically:
3536 // am3offset := '+' register
3537 // | '-' register
3538 // | register
3539 // | # imm
3540 // | # + imm
3541 // | # - imm
3542
3543 // This method must return MatchOperand_NoMatch without consuming any tokens
3544 // in the case where there is no match, as other alternatives take other
3545 // parse methods.
3546 AsmToken Tok = Parser.getTok();
3547 SMLoc S = Tok.getLoc();
3548
3549 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003550 if (Parser.getTok().is(AsmToken::Hash) ||
3551 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003552 Parser.Lex(); // Eat the '#'.
3553 // Explicitly look for a '-', as we need to encode negative zero
3554 // differently.
3555 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3556 const MCExpr *Offset;
3557 if (getParser().ParseExpression(Offset))
3558 return MatchOperand_ParseFail;
3559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3560 if (!CE) {
3561 Error(S, "constant expression expected");
3562 return MatchOperand_ParseFail;
3563 }
3564 SMLoc E = Tok.getLoc();
3565 // Negative zero is encoded as the flag value INT32_MIN.
3566 int32_t Val = CE->getValue();
3567 if (isNegative && Val == 0)
3568 Val = INT32_MIN;
3569
3570 Operands.push_back(
3571 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3572
3573 return MatchOperand_Success;
3574 }
3575
3576
3577 bool haveEaten = false;
3578 bool isAdd = true;
3579 int Reg = -1;
3580 if (Tok.is(AsmToken::Plus)) {
3581 Parser.Lex(); // Eat the '+' token.
3582 haveEaten = true;
3583 } else if (Tok.is(AsmToken::Minus)) {
3584 Parser.Lex(); // Eat the '-' token.
3585 isAdd = false;
3586 haveEaten = true;
3587 }
3588 if (Parser.getTok().is(AsmToken::Identifier))
3589 Reg = tryParseRegister();
3590 if (Reg == -1) {
3591 if (!haveEaten)
3592 return MatchOperand_NoMatch;
3593 Error(Parser.getTok().getLoc(), "register expected");
3594 return MatchOperand_ParseFail;
3595 }
3596 SMLoc E = Parser.getTok().getLoc();
3597
3598 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3599 0, S, E));
3600
3601 return MatchOperand_Success;
3602}
3603
Jim Grosbacha77295d2011-09-08 22:07:06 +00003604/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3605/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3606/// when they refer multiple MIOperands inside a single one.
3607bool ARMAsmParser::
3608cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3609 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3610 // Rt, Rt2
3611 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3612 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3613 // Create a writeback register dummy placeholder.
3614 Inst.addOperand(MCOperand::CreateReg(0));
3615 // addr
3616 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3617 // pred
3618 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3619 return true;
3620}
3621
3622/// cvtT2StrdPre - Convert parsed operands to MCInst.
3623/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3624/// when they refer multiple MIOperands inside a single one.
3625bool ARMAsmParser::
3626cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3627 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3628 // Create a writeback register dummy placeholder.
3629 Inst.addOperand(MCOperand::CreateReg(0));
3630 // Rt, Rt2
3631 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3632 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3633 // addr
3634 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3635 // pred
3636 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3637 return true;
3638}
3639
Jim Grosbacheeec0252011-09-08 00:39:19 +00003640/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3641/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3642/// when they refer multiple MIOperands inside a single one.
3643bool ARMAsmParser::
3644cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3645 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3646 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3647
3648 // Create a writeback register dummy placeholder.
3649 Inst.addOperand(MCOperand::CreateImm(0));
3650
3651 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3652 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3653 return true;
3654}
3655
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003656/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3657/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3658/// when they refer multiple MIOperands inside a single one.
3659bool ARMAsmParser::
3660cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3661 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3662 // Create a writeback register dummy placeholder.
3663 Inst.addOperand(MCOperand::CreateImm(0));
3664 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3665 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3666 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3667 return true;
3668}
3669
Jim Grosbach1355cf12011-07-26 17:10:22 +00003670/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003671/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3672/// when they refer multiple MIOperands inside a single one.
3673bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003674cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003675 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3676 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3677
3678 // Create a writeback register dummy placeholder.
3679 Inst.addOperand(MCOperand::CreateImm(0));
3680
Jim Grosbach7ce05792011-08-03 23:50:40 +00003681 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003682 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3683 return true;
3684}
3685
Owen Anderson9ab0f252011-08-26 20:43:14 +00003686/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3687/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3688/// when they refer multiple MIOperands inside a single one.
3689bool ARMAsmParser::
3690cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3691 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3692 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3693
3694 // Create a writeback register dummy placeholder.
3695 Inst.addOperand(MCOperand::CreateImm(0));
3696
3697 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3698 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3699 return true;
3700}
3701
3702
Jim Grosbach548340c2011-08-11 19:22:40 +00003703/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3704/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3705/// when they refer multiple MIOperands inside a single one.
3706bool ARMAsmParser::
3707cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3708 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3709 // Create a writeback register dummy placeholder.
3710 Inst.addOperand(MCOperand::CreateImm(0));
3711 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3712 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3713 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3714 return true;
3715}
3716
Jim Grosbach1355cf12011-07-26 17:10:22 +00003717/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003718/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3719/// when they refer multiple MIOperands inside a single one.
3720bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003721cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003722 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3723 // Create a writeback register dummy placeholder.
3724 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003725 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3726 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3727 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003728 return true;
3729}
3730
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003731/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3732/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3733/// when they refer multiple MIOperands inside a single one.
3734bool ARMAsmParser::
3735cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3736 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3737 // Create a writeback register dummy placeholder.
3738 Inst.addOperand(MCOperand::CreateImm(0));
3739 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3740 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3741 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3742 return true;
3743}
3744
Jim Grosbach7ce05792011-08-03 23:50:40 +00003745/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3746/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3747/// when they refer multiple MIOperands inside a single one.
3748bool ARMAsmParser::
3749cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3750 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3751 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003752 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003753 // Create a writeback register dummy placeholder.
3754 Inst.addOperand(MCOperand::CreateImm(0));
3755 // addr
3756 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3757 // offset
3758 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3759 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003760 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3761 return true;
3762}
3763
Jim Grosbach7ce05792011-08-03 23:50:40 +00003764/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003765/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3766/// when they refer multiple MIOperands inside a single one.
3767bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003768cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3769 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3770 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003771 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003772 // Create a writeback register dummy placeholder.
3773 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003774 // addr
3775 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3776 // offset
3777 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3778 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003779 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3780 return true;
3781}
3782
Jim Grosbach7ce05792011-08-03 23:50:40 +00003783/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003784/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3785/// when they refer multiple MIOperands inside a single one.
3786bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003787cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3788 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003789 // Create a writeback register dummy placeholder.
3790 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003791 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003792 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003793 // addr
3794 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3795 // offset
3796 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3797 // pred
3798 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3799 return true;
3800}
3801
3802/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3803/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3804/// when they refer multiple MIOperands inside a single one.
3805bool ARMAsmParser::
3806cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3807 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3808 // Create a writeback register dummy placeholder.
3809 Inst.addOperand(MCOperand::CreateImm(0));
3810 // Rt
3811 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3812 // addr
3813 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3814 // offset
3815 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3816 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003817 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3818 return true;
3819}
3820
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003821/// cvtLdrdPre - Convert parsed operands to MCInst.
3822/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3823/// when they refer multiple MIOperands inside a single one.
3824bool ARMAsmParser::
3825cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3826 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3827 // Rt, Rt2
3828 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3829 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3830 // Create a writeback register dummy placeholder.
3831 Inst.addOperand(MCOperand::CreateImm(0));
3832 // addr
3833 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3834 // pred
3835 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3836 return true;
3837}
3838
Jim Grosbach14605d12011-08-11 20:28:23 +00003839/// cvtStrdPre - Convert parsed operands to MCInst.
3840/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3841/// when they refer multiple MIOperands inside a single one.
3842bool ARMAsmParser::
3843cvtStrdPre(MCInst &Inst, unsigned Opcode,
3844 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3845 // Create a writeback register dummy placeholder.
3846 Inst.addOperand(MCOperand::CreateImm(0));
3847 // Rt, Rt2
3848 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3849 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3850 // addr
3851 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3852 // pred
3853 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3854 return true;
3855}
3856
Jim Grosbach623a4542011-08-10 22:42:16 +00003857/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3858/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3859/// when they refer multiple MIOperands inside a single one.
3860bool ARMAsmParser::
3861cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3862 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3863 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3864 // Create a writeback register dummy placeholder.
3865 Inst.addOperand(MCOperand::CreateImm(0));
3866 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3867 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3868 return true;
3869}
3870
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003871/// cvtThumbMultiple- Convert parsed operands to MCInst.
3872/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3873/// when they refer multiple MIOperands inside a single one.
3874bool ARMAsmParser::
3875cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3876 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3877 // The second source operand must be the same register as the destination
3878 // operand.
3879 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003880 (((ARMOperand*)Operands[3])->getReg() !=
3881 ((ARMOperand*)Operands[5])->getReg()) &&
3882 (((ARMOperand*)Operands[3])->getReg() !=
3883 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003884 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003885 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003886 return false;
3887 }
3888 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3889 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003890 // If we have a three-operand form, make sure to set Rn to be the operand
3891 // that isn't the same as Rd.
3892 unsigned RegOp = 4;
3893 if (Operands.size() == 6 &&
3894 ((ARMOperand*)Operands[4])->getReg() ==
3895 ((ARMOperand*)Operands[3])->getReg())
3896 RegOp = 5;
3897 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3898 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003899 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3900
3901 return true;
3902}
Jim Grosbach623a4542011-08-10 22:42:16 +00003903
Jim Grosbach12431322011-10-24 22:16:58 +00003904bool ARMAsmParser::
3905cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3906 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3907 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003908 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003909 // Create a writeback register dummy placeholder.
3910 Inst.addOperand(MCOperand::CreateImm(0));
3911 // Vn
3912 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3913 // pred
3914 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3915 return true;
3916}
3917
3918bool ARMAsmParser::
3919cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3920 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3921 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003922 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003923 // Create a writeback register dummy placeholder.
3924 Inst.addOperand(MCOperand::CreateImm(0));
3925 // Vn
3926 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3927 // Vm
3928 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3929 // pred
3930 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3931 return true;
3932}
3933
Jim Grosbach4334e032011-10-31 21:50:31 +00003934bool ARMAsmParser::
3935cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3936 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3937 // Create a writeback register dummy placeholder.
3938 Inst.addOperand(MCOperand::CreateImm(0));
3939 // Vn
3940 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3941 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003942 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003943 // pred
3944 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3945 return true;
3946}
3947
3948bool ARMAsmParser::
3949cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3950 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3951 // Create a writeback register dummy placeholder.
3952 Inst.addOperand(MCOperand::CreateImm(0));
3953 // Vn
3954 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3955 // Vm
3956 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3957 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003958 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003959 // pred
3960 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3961 return true;
3962}
3963
Bill Wendlinge7176102010-11-06 22:36:58 +00003964/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003965/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003966bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003967parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003968 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003969 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003970 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003971 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003972 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003973
Sean Callanan18b83232010-01-19 21:44:56 +00003974 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003975 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003976 if (BaseRegNum == -1)
3977 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003978
Daniel Dunbar05710932011-01-18 05:34:17 +00003979 // The next token must either be a comma or a closing bracket.
3980 const AsmToken &Tok = Parser.getTok();
3981 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003982 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003983
Jim Grosbach7ce05792011-08-03 23:50:40 +00003984 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003985 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003986 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003987
Jim Grosbach7ce05792011-08-03 23:50:40 +00003988 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003989 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003990
Jim Grosbachfb12f352011-09-19 18:42:21 +00003991 // If there's a pre-indexing writeback marker, '!', just add it as a token
3992 // operand. It's rather odd, but syntactically valid.
3993 if (Parser.getTok().is(AsmToken::Exclaim)) {
3994 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3995 Parser.Lex(); // Eat the '!'.
3996 }
3997
Jim Grosbach7ce05792011-08-03 23:50:40 +00003998 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003999 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004000
Jim Grosbach7ce05792011-08-03 23:50:40 +00004001 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4002 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004003
Jim Grosbach57dcb852011-10-11 17:29:55 +00004004 // If we have a ':', it's an alignment specifier.
4005 if (Parser.getTok().is(AsmToken::Colon)) {
4006 Parser.Lex(); // Eat the ':'.
4007 E = Parser.getTok().getLoc();
4008
4009 const MCExpr *Expr;
4010 if (getParser().ParseExpression(Expr))
4011 return true;
4012
4013 // The expression has to be a constant. Memory references with relocations
4014 // don't come through here, as they use the <label> forms of the relevant
4015 // instructions.
4016 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4017 if (!CE)
4018 return Error (E, "constant expression expected");
4019
4020 unsigned Align = 0;
4021 switch (CE->getValue()) {
4022 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004023 return Error(E,
4024 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4025 case 16: Align = 2; break;
4026 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004027 case 64: Align = 8; break;
4028 case 128: Align = 16; break;
4029 case 256: Align = 32; break;
4030 }
4031
4032 // Now we should have the closing ']'
4033 E = Parser.getTok().getLoc();
4034 if (Parser.getTok().isNot(AsmToken::RBrac))
4035 return Error(E, "']' expected");
4036 Parser.Lex(); // Eat right bracket token.
4037
4038 // Don't worry about range checking the value here. That's handled by
4039 // the is*() predicates.
4040 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4041 ARM_AM::no_shift, 0, Align,
4042 false, S, E));
4043
4044 // If there's a pre-indexing writeback marker, '!', just add it as a token
4045 // operand.
4046 if (Parser.getTok().is(AsmToken::Exclaim)) {
4047 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4048 Parser.Lex(); // Eat the '!'.
4049 }
4050
4051 return false;
4052 }
4053
4054 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004055 // offset. Be friendly and also accept a plain integer (without a leading
4056 // hash) for gas compatibility.
4057 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004058 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004059 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004060 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004061 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004062 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004063
Owen Anderson0da10cf2011-08-29 19:36:44 +00004064 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004065 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004066 if (getParser().ParseExpression(Offset))
4067 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004068
4069 // The expression has to be a constant. Memory references with relocations
4070 // don't come through here, as they use the <label> forms of the relevant
4071 // instructions.
4072 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4073 if (!CE)
4074 return Error (E, "constant expression expected");
4075
Owen Anderson0da10cf2011-08-29 19:36:44 +00004076 // If the constant was #-0, represent it as INT32_MIN.
4077 int32_t Val = CE->getValue();
4078 if (isNegative && Val == 0)
4079 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4080
Jim Grosbach7ce05792011-08-03 23:50:40 +00004081 // Now we should have the closing ']'
4082 E = Parser.getTok().getLoc();
4083 if (Parser.getTok().isNot(AsmToken::RBrac))
4084 return Error(E, "']' expected");
4085 Parser.Lex(); // Eat right bracket token.
4086
4087 // Don't worry about range checking the value here. That's handled by
4088 // the is*() predicates.
4089 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004090 ARM_AM::no_shift, 0, 0,
4091 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004092
4093 // If there's a pre-indexing writeback marker, '!', just add it as a token
4094 // operand.
4095 if (Parser.getTok().is(AsmToken::Exclaim)) {
4096 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4097 Parser.Lex(); // Eat the '!'.
4098 }
4099
4100 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004101 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004102
4103 // The register offset is optionally preceded by a '+' or '-'
4104 bool isNegative = false;
4105 if (Parser.getTok().is(AsmToken::Minus)) {
4106 isNegative = true;
4107 Parser.Lex(); // Eat the '-'.
4108 } else if (Parser.getTok().is(AsmToken::Plus)) {
4109 // Nothing to do.
4110 Parser.Lex(); // Eat the '+'.
4111 }
4112
4113 E = Parser.getTok().getLoc();
4114 int OffsetRegNum = tryParseRegister();
4115 if (OffsetRegNum == -1)
4116 return Error(E, "register expected");
4117
4118 // If there's a shift operator, handle it.
4119 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004120 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004121 if (Parser.getTok().is(AsmToken::Comma)) {
4122 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004123 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004124 return true;
4125 }
4126
4127 // Now we should have the closing ']'
4128 E = Parser.getTok().getLoc();
4129 if (Parser.getTok().isNot(AsmToken::RBrac))
4130 return Error(E, "']' expected");
4131 Parser.Lex(); // Eat right bracket token.
4132
4133 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004134 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004135 S, E));
4136
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004137 // If there's a pre-indexing writeback marker, '!', just add it as a token
4138 // operand.
4139 if (Parser.getTok().is(AsmToken::Exclaim)) {
4140 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4141 Parser.Lex(); // Eat the '!'.
4142 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004143
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004144 return false;
4145}
4146
Jim Grosbach7ce05792011-08-03 23:50:40 +00004147/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004148/// ( lsl | lsr | asr | ror ) , # shift_amount
4149/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004150/// return true if it parses a shift otherwise it returns false.
4151bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4152 unsigned &Amount) {
4153 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004154 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004155 if (Tok.isNot(AsmToken::Identifier))
4156 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004157 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004158 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4159 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004160 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004161 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004162 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004163 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004164 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004165 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004166 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004167 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004168 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004169 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004170 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004171 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004172
Jim Grosbach7ce05792011-08-03 23:50:40 +00004173 // rrx stands alone.
4174 Amount = 0;
4175 if (St != ARM_AM::rrx) {
4176 Loc = Parser.getTok().getLoc();
4177 // A '#' and a shift amount.
4178 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004179 if (HashTok.isNot(AsmToken::Hash) &&
4180 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004181 return Error(HashTok.getLoc(), "'#' expected");
4182 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004183
Jim Grosbach7ce05792011-08-03 23:50:40 +00004184 const MCExpr *Expr;
4185 if (getParser().ParseExpression(Expr))
4186 return true;
4187 // Range check the immediate.
4188 // lsl, ror: 0 <= imm <= 31
4189 // lsr, asr: 0 <= imm <= 32
4190 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4191 if (!CE)
4192 return Error(Loc, "shift amount must be an immediate");
4193 int64_t Imm = CE->getValue();
4194 if (Imm < 0 ||
4195 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4196 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4197 return Error(Loc, "immediate shift value out of range");
4198 Amount = Imm;
4199 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004200
4201 return false;
4202}
4203
Jim Grosbach9d390362011-10-03 23:38:36 +00004204/// parseFPImm - A floating point immediate expression operand.
4205ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4206parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4207 SMLoc S = Parser.getTok().getLoc();
4208
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004209 if (Parser.getTok().isNot(AsmToken::Hash) &&
4210 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004211 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004212
4213 // Disambiguate the VMOV forms that can accept an FP immediate.
4214 // vmov.f32 <sreg>, #imm
4215 // vmov.f64 <dreg>, #imm
4216 // vmov.f32 <dreg>, #imm @ vector f32x2
4217 // vmov.f32 <qreg>, #imm @ vector f32x4
4218 //
4219 // There are also the NEON VMOV instructions which expect an
4220 // integer constant. Make sure we don't try to parse an FPImm
4221 // for these:
4222 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4223 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4224 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4225 TyOp->getToken() != ".f64"))
4226 return MatchOperand_NoMatch;
4227
Jim Grosbach9d390362011-10-03 23:38:36 +00004228 Parser.Lex(); // Eat the '#'.
4229
4230 // Handle negation, as that still comes through as a separate token.
4231 bool isNegative = false;
4232 if (Parser.getTok().is(AsmToken::Minus)) {
4233 isNegative = true;
4234 Parser.Lex();
4235 }
4236 const AsmToken &Tok = Parser.getTok();
4237 if (Tok.is(AsmToken::Real)) {
4238 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4239 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4240 // If we had a '-' in front, toggle the sign bit.
4241 IntVal ^= (uint64_t)isNegative << 63;
4242 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4243 Parser.Lex(); // Eat the token.
4244 if (Val == -1) {
4245 TokError("floating point value out of range");
4246 return MatchOperand_ParseFail;
4247 }
4248 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4249 return MatchOperand_Success;
4250 }
4251 if (Tok.is(AsmToken::Integer)) {
4252 int64_t Val = Tok.getIntVal();
4253 Parser.Lex(); // Eat the token.
4254 if (Val > 255 || Val < 0) {
4255 TokError("encoded floating point value out of range");
4256 return MatchOperand_ParseFail;
4257 }
4258 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4259 return MatchOperand_Success;
4260 }
4261
4262 TokError("invalid floating point immediate");
4263 return MatchOperand_ParseFail;
4264}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004265/// Parse a arm instruction operand. For now this parses the operand regardless
4266/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004267bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004268 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004269 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004270
4271 // Check if the current operand has a custom associated parser, if so, try to
4272 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004273 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4274 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004275 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004276 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4277 // there was a match, but an error occurred, in which case, just return that
4278 // the operand parsing failed.
4279 if (ResTy == MatchOperand_ParseFail)
4280 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004281
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004282 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004283 default:
4284 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004285 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004286 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004287 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004288 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004289 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004290 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004291 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004292 else if (Res == -1) // irrecoverable error
4293 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004294 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004295 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4296 S = Parser.getTok().getLoc();
4297 Parser.Lex();
4298 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4299 return false;
4300 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004301
4302 // Fall though for the Identifier case that is not a register or a
4303 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004304 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004305 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004306 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004307 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004308 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004309 // This was not a register so parse other operands that start with an
4310 // identifier (like labels) as expressions and create them as immediates.
4311 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004312 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004313 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004314 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004315 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004316 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4317 return false;
4318 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004319 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004320 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004321 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004322 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004323 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004324 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004325 // #42 -> immediate.
4326 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004327 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004328 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004329 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004330 const MCExpr *ImmVal;
4331 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004332 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004333 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004334 if (CE) {
4335 int32_t Val = CE->getValue();
4336 if (isNegative && Val == 0)
4337 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004338 }
Sean Callanan76264762010-04-02 22:27:05 +00004339 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004340 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4341 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004342 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004343 case AsmToken::Colon: {
4344 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004345 // FIXME: Check it's an expression prefix,
4346 // e.g. (FOO - :lower16:BAR) isn't legal.
4347 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004348 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004349 return true;
4350
Evan Cheng75972122011-01-13 07:58:56 +00004351 const MCExpr *SubExprVal;
4352 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004353 return true;
4354
Evan Cheng75972122011-01-13 07:58:56 +00004355 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4356 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004357 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004358 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004359 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004360 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004361 }
4362}
4363
Jim Grosbach1355cf12011-07-26 17:10:22 +00004364// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004365// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004366bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004367 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004368
4369 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004370 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004371 Parser.Lex(); // Eat ':'
4372
4373 if (getLexer().isNot(AsmToken::Identifier)) {
4374 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4375 return true;
4376 }
4377
4378 StringRef IDVal = Parser.getTok().getIdentifier();
4379 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004380 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004381 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004382 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004383 } else {
4384 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4385 return true;
4386 }
4387 Parser.Lex();
4388
4389 if (getLexer().isNot(AsmToken::Colon)) {
4390 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4391 return true;
4392 }
4393 Parser.Lex(); // Eat the last ':'
4394 return false;
4395}
4396
Daniel Dunbar352e1482011-01-11 15:59:50 +00004397/// \brief Given a mnemonic, split out possible predication code and carry
4398/// setting letters to form a canonical mnemonic and flags.
4399//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004400// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004401// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004402StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004403 unsigned &PredicationCode,
4404 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004405 unsigned &ProcessorIMod,
4406 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004407 PredicationCode = ARMCC::AL;
4408 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004409 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004410
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004411 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004412 //
4413 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004414 if ((Mnemonic == "movs" && isThumb()) ||
4415 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4416 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4417 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4418 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4419 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4420 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004421 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4422 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004423 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004424
Jim Grosbach3f00e312011-07-11 17:09:57 +00004425 // First, split out any predication code. Ignore mnemonics we know aren't
4426 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004427 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004428 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004429 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004430 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004431 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4432 .Case("eq", ARMCC::EQ)
4433 .Case("ne", ARMCC::NE)
4434 .Case("hs", ARMCC::HS)
4435 .Case("cs", ARMCC::HS)
4436 .Case("lo", ARMCC::LO)
4437 .Case("cc", ARMCC::LO)
4438 .Case("mi", ARMCC::MI)
4439 .Case("pl", ARMCC::PL)
4440 .Case("vs", ARMCC::VS)
4441 .Case("vc", ARMCC::VC)
4442 .Case("hi", ARMCC::HI)
4443 .Case("ls", ARMCC::LS)
4444 .Case("ge", ARMCC::GE)
4445 .Case("lt", ARMCC::LT)
4446 .Case("gt", ARMCC::GT)
4447 .Case("le", ARMCC::LE)
4448 .Case("al", ARMCC::AL)
4449 .Default(~0U);
4450 if (CC != ~0U) {
4451 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4452 PredicationCode = CC;
4453 }
Bill Wendling52925b62010-10-29 23:50:21 +00004454 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004455
Daniel Dunbar352e1482011-01-11 15:59:50 +00004456 // Next, determine if we have a carry setting bit. We explicitly ignore all
4457 // the instructions we know end in 's'.
4458 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004459 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004460 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4461 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4462 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004463 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004464 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004465 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach1aa149f2011-12-22 19:20:45 +00004466 Mnemonic == "fmuls" || Mnemonic == "fcmps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004467 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004468 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4469 CarrySetting = true;
4470 }
4471
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004472 // The "cps" instruction can have a interrupt mode operand which is glued into
4473 // the mnemonic. Check if this is the case, split it and parse the imod op
4474 if (Mnemonic.startswith("cps")) {
4475 // Split out any imod code.
4476 unsigned IMod =
4477 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4478 .Case("ie", ARM_PROC::IE)
4479 .Case("id", ARM_PROC::ID)
4480 .Default(~0U);
4481 if (IMod != ~0U) {
4482 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4483 ProcessorIMod = IMod;
4484 }
4485 }
4486
Jim Grosbach89df9962011-08-26 21:43:41 +00004487 // The "it" instruction has the condition mask on the end of the mnemonic.
4488 if (Mnemonic.startswith("it")) {
4489 ITMask = Mnemonic.slice(2, Mnemonic.size());
4490 Mnemonic = Mnemonic.slice(0, 2);
4491 }
4492
Daniel Dunbar352e1482011-01-11 15:59:50 +00004493 return Mnemonic;
4494}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004495
4496/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4497/// inclusion of carry set or predication code operands.
4498//
4499// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004500void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004501getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004502 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004503 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4504 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004505 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004506 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004507 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004508 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004509 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004510 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004511 Mnemonic == "mla" || Mnemonic == "smlal" ||
4512 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004513 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004514 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004515 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004516
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004517 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4518 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4519 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4520 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004521 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4522 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004523 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004524 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4525 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4526 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004527 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4528 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004529 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004530 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004531 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004532 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004533
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004534 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004535 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004536 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004537 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004538 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004539}
4540
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004541bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4542 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004543 // FIXME: This is all horribly hacky. We really need a better way to deal
4544 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004545
4546 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4547 // another does not. Specifically, the MOVW instruction does not. So we
4548 // special case it here and remove the defaulted (non-setting) cc_out
4549 // operand if that's the instruction we're trying to match.
4550 //
4551 // We do this as post-processing of the explicit operands rather than just
4552 // conditionally adding the cc_out in the first place because we need
4553 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004554 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004555 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4556 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4557 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4558 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004559
4560 // Register-register 'add' for thumb does not have a cc_out operand
4561 // when there are only two register operands.
4562 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4563 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4564 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4565 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4566 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004567 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004568 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4569 // have to check the immediate range here since Thumb2 has a variant
4570 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004571 if (((isThumb() && Mnemonic == "add") ||
4572 (isThumbTwo() && Mnemonic == "sub")) &&
4573 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004574 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4575 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4576 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004577 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4578 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4579 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004580 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004581 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4582 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004583 // selecting via the generic "add" mnemonic, so to know that we
4584 // should remove the cc_out operand, we have to explicitly check that
4585 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004586 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4587 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004588 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4589 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4590 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4591 // Nest conditions rather than one big 'if' statement for readability.
4592 //
4593 // If either register is a high reg, it's either one of the SP
4594 // variants (handled above) or a 32-bit encoding, so we just
4595 // check against T3.
4596 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4597 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4598 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4599 return false;
4600 // If both registers are low, we're in an IT block, and the immediate is
4601 // in range, we should use encoding T1 instead, which has a cc_out.
4602 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004603 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004604 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4605 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4606 return false;
4607
4608 // Otherwise, we use encoding T4, which does not have a cc_out
4609 // operand.
4610 return true;
4611 }
4612
Jim Grosbach64944f42011-09-14 21:00:40 +00004613 // The thumb2 multiply instruction doesn't have a CCOut register, so
4614 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4615 // use the 16-bit encoding or not.
4616 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4617 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4618 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4619 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4620 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4621 // If the registers aren't low regs, the destination reg isn't the
4622 // same as one of the source regs, or the cc_out operand is zero
4623 // outside of an IT block, we have to use the 32-bit encoding, so
4624 // remove the cc_out operand.
4625 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4626 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004627 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004628 !inITBlock() ||
4629 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4630 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4631 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4632 static_cast<ARMOperand*>(Operands[4])->getReg())))
4633 return true;
4634
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004635 // Also check the 'mul' syntax variant that doesn't specify an explicit
4636 // destination register.
4637 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4638 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4639 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4640 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4641 // If the registers aren't low regs or the cc_out operand is zero
4642 // outside of an IT block, we have to use the 32-bit encoding, so
4643 // remove the cc_out operand.
4644 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4645 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4646 !inITBlock()))
4647 return true;
4648
Jim Grosbach64944f42011-09-14 21:00:40 +00004649
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004650
Jim Grosbachf69c8042011-08-24 21:42:27 +00004651 // Register-register 'add/sub' for thumb does not have a cc_out operand
4652 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4653 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4654 // right, this will result in better diagnostics (which operand is off)
4655 // anyway.
4656 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4657 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004658 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4659 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4660 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4661 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004662
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004663 return false;
4664}
4665
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004666static bool isDataTypeToken(StringRef Tok) {
4667 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4668 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4669 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4670 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4671 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4672 Tok == ".f" || Tok == ".d";
4673}
4674
4675// FIXME: This bit should probably be handled via an explicit match class
4676// in the .td files that matches the suffix instead of having it be
4677// a literal string token the way it is now.
4678static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4679 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4680}
4681
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004682static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004683/// Parse an arm instruction mnemonic followed by its operands.
4684bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4685 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004686 // Apply mnemonic aliases before doing anything else, as the destination
4687 // mnemnonic may include suffices and we want to handle them normally.
4688 // The generic tblgen'erated code does this later, at the start of
4689 // MatchInstructionImpl(), but that's too late for aliases that include
4690 // any sort of suffix.
4691 unsigned AvailableFeatures = getAvailableFeatures();
4692 applyMnemonicAliases(Name, AvailableFeatures);
4693
Jim Grosbacha39cda72011-12-14 02:16:11 +00004694 // First check for the ARM-specific .req directive.
4695 if (Parser.getTok().is(AsmToken::Identifier) &&
4696 Parser.getTok().getIdentifier() == ".req") {
4697 parseDirectiveReq(Name, NameLoc);
4698 // We always return 'error' for this, as we're done with this
4699 // statement and don't need to match the 'instruction."
4700 return true;
4701 }
4702
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004703 // Create the leading tokens for the mnemonic, split by '.' characters.
4704 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004705 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004706
Daniel Dunbar352e1482011-01-11 15:59:50 +00004707 // Split out the predication code and carry setting flag from the mnemonic.
4708 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004709 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004710 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004711 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004712 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004713 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004714
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004715 // In Thumb1, only the branch (B) instruction can be predicated.
4716 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4717 Parser.EatToEndOfStatement();
4718 return Error(NameLoc, "conditional execution not supported in Thumb1");
4719 }
4720
Jim Grosbachffa32252011-07-19 19:13:28 +00004721 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4722
Jim Grosbach89df9962011-08-26 21:43:41 +00004723 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4724 // is the mask as it will be for the IT encoding if the conditional
4725 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4726 // where the conditional bit0 is zero, the instruction post-processing
4727 // will adjust the mask accordingly.
4728 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004729 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4730 if (ITMask.size() > 3) {
4731 Parser.EatToEndOfStatement();
4732 return Error(Loc, "too many conditions on IT instruction");
4733 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004734 unsigned Mask = 8;
4735 for (unsigned i = ITMask.size(); i != 0; --i) {
4736 char pos = ITMask[i - 1];
4737 if (pos != 't' && pos != 'e') {
4738 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004739 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004740 }
4741 Mask >>= 1;
4742 if (ITMask[i - 1] == 't')
4743 Mask |= 8;
4744 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004745 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004746 }
4747
Jim Grosbachffa32252011-07-19 19:13:28 +00004748 // FIXME: This is all a pretty gross hack. We should automatically handle
4749 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004750
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004751 // Next, add the CCOut and ConditionCode operands, if needed.
4752 //
4753 // For mnemonics which can ever incorporate a carry setting bit or predication
4754 // code, our matching model involves us always generating CCOut and
4755 // ConditionCode operands to match the mnemonic "as written" and then we let
4756 // the matcher deal with finding the right instruction or generating an
4757 // appropriate error.
4758 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004759 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004760
Jim Grosbach33c16a22011-07-14 22:04:21 +00004761 // If we had a carry-set on an instruction that can't do that, issue an
4762 // error.
4763 if (!CanAcceptCarrySet && CarrySetting) {
4764 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004765 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004766 "' can not set flags, but 's' suffix specified");
4767 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004768 // If we had a predication code on an instruction that can't do that, issue an
4769 // error.
4770 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4771 Parser.EatToEndOfStatement();
4772 return Error(NameLoc, "instruction '" + Mnemonic +
4773 "' is not predicable, but condition code specified");
4774 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004775
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004776 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004777 if (CanAcceptCarrySet) {
4778 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004779 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004780 Loc));
4781 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004782
4783 // Add the predication code operand, if necessary.
4784 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004785 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4786 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004787 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004788 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004789 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004790
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004791 // Add the processor imod operand, if necessary.
4792 if (ProcessorIMod) {
4793 Operands.push_back(ARMOperand::CreateImm(
4794 MCConstantExpr::Create(ProcessorIMod, getContext()),
4795 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004796 }
4797
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004798 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004799 while (Next != StringRef::npos) {
4800 Start = Next;
4801 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004802 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004803
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004804 // Some NEON instructions have an optional datatype suffix that is
4805 // completely ignored. Check for that.
4806 if (isDataTypeToken(ExtraToken) &&
4807 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4808 continue;
4809
Jim Grosbach81d2e392011-09-07 16:06:04 +00004810 if (ExtraToken != ".n") {
4811 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4812 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4813 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004814 }
4815
4816 // Read the remaining operands.
4817 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004818 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004819 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004820 Parser.EatToEndOfStatement();
4821 return true;
4822 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004823
4824 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004825 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004826
4827 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004828 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004829 Parser.EatToEndOfStatement();
4830 return true;
4831 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004832 }
4833 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004834
Chris Lattnercbf8a982010-09-11 16:18:25 +00004835 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004836 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004837 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004838 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004839 }
Bill Wendling146018f2010-11-06 21:42:12 +00004840
Chris Lattner34e53142010-09-08 05:10:46 +00004841 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004842
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004843 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4844 // do and don't have a cc_out optional-def operand. With some spot-checks
4845 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004846 // parse and adjust accordingly before actually matching. We shouldn't ever
4847 // try to remove a cc_out operand that was explicitly set on the the
4848 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4849 // table driven matcher doesn't fit well with the ARM instruction set.
4850 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004851 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4852 Operands.erase(Operands.begin() + 1);
4853 delete Op;
4854 }
4855
Jim Grosbachcf121c32011-07-28 21:57:55 +00004856 // ARM mode 'blx' need special handling, as the register operand version
4857 // is predicable, but the label operand version is not. So, we can't rely
4858 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004859 // a k_CondCode operand in the list. If we're trying to match the label
4860 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004861 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4862 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4863 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4864 Operands.erase(Operands.begin() + 1);
4865 delete Op;
4866 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004867
4868 // The vector-compare-to-zero instructions have a literal token "#0" at
4869 // the end that comes to here as an immediate operand. Convert it to a
4870 // token to play nicely with the matcher.
4871 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4872 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4873 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4874 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4875 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4876 if (CE && CE->getValue() == 0) {
4877 Operands.erase(Operands.begin() + 5);
4878 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4879 delete Op;
4880 }
4881 }
Jim Grosbach68259142011-10-03 22:30:24 +00004882 // VCMP{E} does the same thing, but with a different operand count.
4883 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4884 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4885 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4886 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4887 if (CE && CE->getValue() == 0) {
4888 Operands.erase(Operands.begin() + 4);
4889 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4890 delete Op;
4891 }
4892 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004893 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004894 // end. Convert it to a token here. Take care not to convert those
4895 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004896 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004897 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4898 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004899 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4900 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4901 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004902 if (CE && CE->getValue() == 0 &&
4903 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004904 // The cc_out operand matches the IT block.
4905 ((inITBlock() != CarrySetting) &&
4906 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004907 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004908 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004909 Operands.erase(Operands.begin() + 5);
4910 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4911 delete Op;
4912 }
4913 }
4914
Chris Lattner98986712010-01-14 22:21:20 +00004915 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004916}
4917
Jim Grosbach189610f2011-07-26 18:25:39 +00004918// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004919
4920// return 'true' if register list contains non-low GPR registers,
4921// 'false' otherwise. If Reg is in the register list or is HiReg, set
4922// 'containsReg' to true.
4923static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4924 unsigned HiReg, bool &containsReg) {
4925 containsReg = false;
4926 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4927 unsigned OpReg = Inst.getOperand(i).getReg();
4928 if (OpReg == Reg)
4929 containsReg = true;
4930 // Anything other than a low register isn't legal here.
4931 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4932 return true;
4933 }
4934 return false;
4935}
4936
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004937// Check if the specified regisgter is in the register list of the inst,
4938// starting at the indicated operand number.
4939static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4940 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4941 unsigned OpReg = Inst.getOperand(i).getReg();
4942 if (OpReg == Reg)
4943 return true;
4944 }
4945 return false;
4946}
4947
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004948// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4949// the ARMInsts array) instead. Getting that here requires awkward
4950// API changes, though. Better way?
4951namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004952extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004953}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004954static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004955 return ARMInsts[Opcode];
4956}
4957
Jim Grosbach189610f2011-07-26 18:25:39 +00004958// FIXME: We would really like to be able to tablegen'erate this.
4959bool ARMAsmParser::
4960validateInstruction(MCInst &Inst,
4961 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004962 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004963 SMLoc Loc = Operands[0]->getStartLoc();
4964 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004965 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4966 // being allowed in IT blocks, but not being predicable. It just always
4967 // executes.
4968 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004969 unsigned bit = 1;
4970 if (ITState.FirstCond)
4971 ITState.FirstCond = false;
4972 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004973 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004974 // The instruction must be predicable.
4975 if (!MCID.isPredicable())
4976 return Error(Loc, "instructions in IT block must be predicable");
4977 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4978 unsigned ITCond = bit ? ITState.Cond :
4979 ARMCC::getOppositeCondition(ITState.Cond);
4980 if (Cond != ITCond) {
4981 // Find the condition code Operand to get its SMLoc information.
4982 SMLoc CondLoc;
4983 for (unsigned i = 1; i < Operands.size(); ++i)
4984 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4985 CondLoc = Operands[i]->getStartLoc();
4986 return Error(CondLoc, "incorrect condition in IT block; got '" +
4987 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4988 "', but expected '" +
4989 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4990 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004991 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004992 } else if (isThumbTwo() && MCID.isPredicable() &&
4993 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004994 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4995 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004996 return Error(Loc, "predicated instructions must be in IT block");
4997
Jim Grosbach189610f2011-07-26 18:25:39 +00004998 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004999 case ARM::LDRD:
5000 case ARM::LDRD_PRE:
5001 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005002 case ARM::LDREXD: {
5003 // Rt2 must be Rt + 1.
5004 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5005 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5006 if (Rt2 != Rt + 1)
5007 return Error(Operands[3]->getStartLoc(),
5008 "destination operands must be sequential");
5009 return false;
5010 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005011 case ARM::STRD: {
5012 // Rt2 must be Rt + 1.
5013 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5014 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5015 if (Rt2 != Rt + 1)
5016 return Error(Operands[3]->getStartLoc(),
5017 "source operands must be sequential");
5018 return false;
5019 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005020 case ARM::STRD_PRE:
5021 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005022 case ARM::STREXD: {
5023 // Rt2 must be Rt + 1.
5024 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5025 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5026 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005027 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005028 "source operands must be sequential");
5029 return false;
5030 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005031 case ARM::SBFX:
5032 case ARM::UBFX: {
5033 // width must be in range [1, 32-lsb]
5034 unsigned lsb = Inst.getOperand(2).getImm();
5035 unsigned widthm1 = Inst.getOperand(3).getImm();
5036 if (widthm1 >= 32 - lsb)
5037 return Error(Operands[5]->getStartLoc(),
5038 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005039 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005040 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005041 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005042 // If we're parsing Thumb2, the .w variant is available and handles
5043 // most cases that are normally illegal for a Thumb1 LDM
5044 // instruction. We'll make the transformation in processInstruction()
5045 // if necessary.
5046 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005047 // Thumb LDM instructions are writeback iff the base register is not
5048 // in the register list.
5049 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005050 bool hasWritebackToken =
5051 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5052 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005053 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005054 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005055 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5056 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005057 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005058 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005059 return Error(Operands[2]->getStartLoc(),
5060 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005061 // If we should not have writeback, there must not be a '!'. This is
5062 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005063 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005064 return Error(Operands[3]->getStartLoc(),
5065 "writeback operator '!' not allowed when base register "
5066 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005067
5068 break;
5069 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005070 case ARM::t2LDMIA_UPD: {
5071 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5072 return Error(Operands[4]->getStartLoc(),
5073 "writeback operator '!' not allowed when base register "
5074 "in register list");
5075 break;
5076 }
Jim Grosbach54026372011-11-10 23:17:11 +00005077 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5078 // so only issue a diagnostic for thumb1. The instructions will be
5079 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005080 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005081 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005082 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5083 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005084 return Error(Operands[2]->getStartLoc(),
5085 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005086 break;
5087 }
5088 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005089 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005090 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5091 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005092 return Error(Operands[2]->getStartLoc(),
5093 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005094 break;
5095 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005096 case ARM::tSTMIA_UPD: {
5097 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005098 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005099 return Error(Operands[4]->getStartLoc(),
5100 "registers must be in range r0-r7");
5101 break;
5102 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005103 }
5104
5105 return false;
5106}
5107
Jim Grosbach5b484312011-12-20 20:46:29 +00005108static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005109 switch(Opc) {
5110 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005111 // VST1LN
5112 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5113 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5114 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005115 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005116 return ARM::VST1LNd8_UPD;
5117 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5118 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5119 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005120 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005121 return ARM::VST1LNd16_UPD;
5122 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5123 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5124 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005125 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005126 return ARM::VST1LNd32_UPD;
5127 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5128 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5129 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005130 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005131 return ARM::VST1LNd8_UPD;
5132 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5133 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5134 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005135 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005136 return ARM::VST1LNd16_UPD;
5137 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5138 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5139 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005140 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005141 return ARM::VST1LNd32_UPD;
5142 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5143 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5144 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005145 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005146 return ARM::VST1LNd8;
5147 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5148 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5149 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005150 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005151 return ARM::VST1LNd16;
5152 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5153 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5154 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005155 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005156 return ARM::VST1LNd32;
5157
5158 // VST2LN
5159 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5160 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5161 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005162 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005163 return ARM::VST2LNd8_UPD;
5164 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5165 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5166 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005167 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005168 return ARM::VST2LNd16_UPD;
5169 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5170 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5171 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005172 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005173 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005174 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5175 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5176 case ARM::VST2LNqWB_fixed_Asm_U16:
5177 Spacing = 2;
5178 return ARM::VST2LNq16_UPD;
5179 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5180 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5181 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5182 Spacing = 2;
5183 return ARM::VST2LNq32_UPD;
5184
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005185 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5186 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5187 case ARM::VST2LNdWB_register_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_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5191 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5192 case ARM::VST2LNdWB_register_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_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5196 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5197 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_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_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5201 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5202 case ARM::VST2LNqWB_register_Asm_U16:
5203 Spacing = 2;
5204 return ARM::VST2LNq16_UPD;
5205 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5206 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5207 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5208 Spacing = 2;
5209 return ARM::VST2LNq32_UPD;
5210
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005211 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5212 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5213 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005214 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005215 return ARM::VST2LNd8;
5216 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5217 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5218 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005219 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005220 return ARM::VST2LNd16;
5221 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5222 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5223 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005224 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005225 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005226 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5227 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5228 case ARM::VST2LNqAsm_U16:
5229 Spacing = 2;
5230 return ARM::VST2LNq16;
5231 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5232 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5233 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5234 Spacing = 2;
5235 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005236 }
5237}
5238
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005239static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005240 switch(Opc) {
5241 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005242 // VLD1LN
5243 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5244 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5245 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005246 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005247 return ARM::VLD1LNd8_UPD;
5248 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5249 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5250 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005251 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005252 return ARM::VLD1LNd16_UPD;
5253 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5254 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5255 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005256 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005257 return ARM::VLD1LNd32_UPD;
5258 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5259 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5260 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005261 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005262 return ARM::VLD1LNd8_UPD;
5263 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5264 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5265 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005266 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005267 return ARM::VLD1LNd16_UPD;
5268 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5269 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5270 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005271 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005272 return ARM::VLD1LNd32_UPD;
5273 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5274 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5275 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005276 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005277 return ARM::VLD1LNd8;
5278 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5279 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5280 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005281 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005282 return ARM::VLD1LNd16;
5283 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5284 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5285 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005286 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005287 return ARM::VLD1LNd32;
5288
5289 // VLD2LN
5290 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5291 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5292 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005293 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005294 return ARM::VLD2LNd8_UPD;
5295 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5296 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5297 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005298 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005299 return ARM::VLD2LNd16_UPD;
5300 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5301 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5302 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005303 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005304 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005305 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5306 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5307 case ARM::VLD2LNqWB_fixed_Asm_U16:
5308 Spacing = 1;
5309 return ARM::VLD2LNq16_UPD;
5310 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5311 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5312 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5313 Spacing = 2;
5314 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005315 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5316 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5317 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005318 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005319 return ARM::VLD2LNd8_UPD;
5320 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5321 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5322 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005323 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005324 return ARM::VLD2LNd16_UPD;
5325 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5326 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5327 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005328 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005329 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005330 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5331 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5332 case ARM::VLD2LNqWB_register_Asm_U16:
5333 Spacing = 2;
5334 return ARM::VLD2LNq16_UPD;
5335 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5336 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5337 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5338 Spacing = 2;
5339 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005340 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5341 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5342 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005343 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005344 return ARM::VLD2LNd8;
5345 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5346 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5347 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005348 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005349 return ARM::VLD2LNd16;
5350 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5351 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5352 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005353 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005354 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005355 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5356 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5357 case ARM::VLD2LNqAsm_U16:
5358 Spacing = 2;
5359 return ARM::VLD2LNq16;
5360 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5361 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5362 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5363 Spacing = 2;
5364 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005365 }
5366}
5367
Jim Grosbach83ec8772011-11-10 23:42:14 +00005368bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005369processInstruction(MCInst &Inst,
5370 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5371 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005372 // Handle NEON VST complex aliases.
5373 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5374 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5375 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5376 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5377 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5378 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5379 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5380 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005381 MCInst TmpInst;
5382 // Shuffle the operands around so the lane index operand is in the
5383 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005384 unsigned Spacing;
5385 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005386 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5387 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5388 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5389 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5390 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5391 TmpInst.addOperand(Inst.getOperand(1)); // lane
5392 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5393 TmpInst.addOperand(Inst.getOperand(6));
5394 Inst = TmpInst;
5395 return true;
5396 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005397
Jim Grosbach5b484312011-12-20 20:46:29 +00005398 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5399 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5400 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005401 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5402 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005403 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005404 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005405 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5406 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5407 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5408 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5409 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5410 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5411 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005412 MCInst TmpInst;
5413 // Shuffle the operands around so the lane index operand is in the
5414 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005415 unsigned Spacing;
5416 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005417 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5418 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5419 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5420 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5421 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005422 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5423 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005424 TmpInst.addOperand(Inst.getOperand(1)); // lane
5425 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5426 TmpInst.addOperand(Inst.getOperand(6));
5427 Inst = TmpInst;
5428 return true;
5429 }
5430 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5431 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5432 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5433 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5434 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5435 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5436 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5437 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +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 Grosbach84defb52011-12-02 22:34:51 +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(MCOperand::CreateReg(0)); // Rm
5447 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5448 TmpInst.addOperand(Inst.getOperand(1)); // lane
5449 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5450 TmpInst.addOperand(Inst.getOperand(5));
5451 Inst = TmpInst;
5452 return true;
5453 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005454
Jim Grosbach5b484312011-12-20 20:46:29 +00005455 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5456 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5457 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005458 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5459 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005460 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005461 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005462 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5463 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5464 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5465 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5466 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5467 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5468 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005469 MCInst TmpInst;
5470 // Shuffle the operands around so the lane index operand is in the
5471 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005472 unsigned Spacing;
5473 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005474 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5475 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5476 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5477 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5478 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005479 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5480 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005481 TmpInst.addOperand(Inst.getOperand(1)); // lane
5482 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5483 TmpInst.addOperand(Inst.getOperand(5));
5484 Inst = TmpInst;
5485 return true;
5486 }
5487 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5488 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5489 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5490 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5491 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005492 case ARM::VST1LNdAsm_U32: {
5493 MCInst TmpInst;
5494 // Shuffle the operands around so the lane index operand is in the
5495 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005496 unsigned Spacing;
5497 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005498 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5499 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5500 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5501 TmpInst.addOperand(Inst.getOperand(1)); // lane
5502 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5503 TmpInst.addOperand(Inst.getOperand(5));
5504 Inst = TmpInst;
5505 return true;
5506 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005507
Jim Grosbach5b484312011-12-20 20:46:29 +00005508 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5509 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005510 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005511 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005512 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005513 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5514 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5515 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5516 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005517 MCInst TmpInst;
5518 // Shuffle the operands around so the lane index operand is in the
5519 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005520 unsigned Spacing;
5521 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005522 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5523 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5524 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005525 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5526 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005527 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 }
5533 // Handle NEON VLD complex aliases.
5534 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5535 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5536 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5537 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5538 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5539 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5540 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5541 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005542 MCInst TmpInst;
5543 // Shuffle the operands around so the lane index operand is in the
5544 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005545 unsigned Spacing;
5546 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005547 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5548 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5549 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5550 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5551 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5552 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5553 TmpInst.addOperand(Inst.getOperand(1)); // lane
5554 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5555 TmpInst.addOperand(Inst.getOperand(6));
5556 Inst = TmpInst;
5557 return true;
5558 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005559
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005560 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5561 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5562 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005563 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5564 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005565 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005566 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005567 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005568 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5569 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5570 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5571 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5572 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5573 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005574 MCInst TmpInst;
5575 // Shuffle the operands around so the lane index operand is in the
5576 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005577 unsigned Spacing;
5578 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005579 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005580 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5581 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005582 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5583 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5584 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5585 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5586 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005587 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5588 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005589 TmpInst.addOperand(Inst.getOperand(1)); // lane
5590 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5591 TmpInst.addOperand(Inst.getOperand(6));
5592 Inst = TmpInst;
5593 return true;
5594 }
5595
5596 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5597 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5598 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5599 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5600 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5601 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5602 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5603 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005604 MCInst TmpInst;
5605 // Shuffle the operands around so the lane index operand is in the
5606 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005607 unsigned Spacing;
5608 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005609 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5610 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5611 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5612 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5613 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5614 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5615 TmpInst.addOperand(Inst.getOperand(1)); // lane
5616 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5617 TmpInst.addOperand(Inst.getOperand(5));
5618 Inst = TmpInst;
5619 return true;
5620 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005621
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005622 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5623 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5624 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005625 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5626 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005627 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005628 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005629 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005630 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5631 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5632 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5633 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5634 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5635 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005636 MCInst TmpInst;
5637 // Shuffle the operands around so the lane index operand is in the
5638 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005639 unsigned Spacing;
5640 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005641 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005642 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5643 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005644 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5645 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5646 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5647 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5648 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005649 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5650 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005651 TmpInst.addOperand(Inst.getOperand(1)); // lane
5652 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5653 TmpInst.addOperand(Inst.getOperand(5));
5654 Inst = TmpInst;
5655 return true;
5656 }
5657
Jim Grosbach5b484312011-12-20 20:46:29 +00005658 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5659 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005660 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005661 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005662 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005663 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005664 MCInst TmpInst;
5665 // Shuffle the operands around so the lane index operand is in the
5666 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005667 unsigned Spacing;
5668 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005669 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5670 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5671 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5672 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5673 TmpInst.addOperand(Inst.getOperand(1)); // lane
5674 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5675 TmpInst.addOperand(Inst.getOperand(5));
5676 Inst = TmpInst;
5677 return true;
5678 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005679
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005680 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5681 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005682 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005683 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005684 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005685 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5686 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5687 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5688 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5689 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +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 Grosbach9b1b3902011-12-14 23:25:46 +00005695 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005696 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5697 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005698 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5699 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5700 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005701 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5702 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005703 TmpInst.addOperand(Inst.getOperand(1)); // lane
5704 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5705 TmpInst.addOperand(Inst.getOperand(5));
5706 Inst = TmpInst;
5707 return true;
5708 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005709 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00005710 case ARM::t2MOVsr:
5711 case ARM::t2MOVSsr: {
5712 // Which instruction to expand to depends on the CCOut operand and
5713 // whether we're in an IT block if the register operands are low
5714 // registers.
5715 bool isNarrow = false;
5716 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5717 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5718 isARMLowRegister(Inst.getOperand(2).getReg()) &&
5719 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
5720 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
5721 isNarrow = true;
5722 MCInst TmpInst;
5723 unsigned newOpc;
5724 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
5725 default: llvm_unreachable("unexpected opcode!");
5726 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
5727 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
5728 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
5729 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
5730 }
5731 TmpInst.setOpcode(newOpc);
5732 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5733 if (isNarrow)
5734 TmpInst.addOperand(MCOperand::CreateReg(
5735 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5736 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5737 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5738 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5739 TmpInst.addOperand(Inst.getOperand(5));
5740 if (!isNarrow)
5741 TmpInst.addOperand(MCOperand::CreateReg(
5742 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
5743 Inst = TmpInst;
5744 return true;
5745 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005746 case ARM::t2MOVsi:
5747 case ARM::t2MOVSsi: {
5748 // Which instruction to expand to depends on the CCOut operand and
5749 // whether we're in an IT block if the register operands are low
5750 // registers.
5751 bool isNarrow = false;
5752 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5753 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5754 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5755 isNarrow = true;
5756 MCInst TmpInst;
5757 unsigned newOpc;
5758 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5759 default: llvm_unreachable("unexpected opcode!");
5760 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5761 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5762 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5763 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00005764 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00005765 }
5766 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5767 if (Ammount == 32) Ammount = 0;
5768 TmpInst.setOpcode(newOpc);
5769 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5770 if (isNarrow)
5771 TmpInst.addOperand(MCOperand::CreateReg(
5772 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5773 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00005774 if (newOpc != ARM::t2RRX)
5775 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00005776 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5777 TmpInst.addOperand(Inst.getOperand(4));
5778 if (!isNarrow)
5779 TmpInst.addOperand(MCOperand::CreateReg(
5780 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5781 Inst = TmpInst;
5782 return true;
5783 }
5784 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005785 case ARM::ASRr:
5786 case ARM::LSRr:
5787 case ARM::LSLr:
5788 case ARM::RORr: {
5789 ARM_AM::ShiftOpc ShiftTy;
5790 switch(Inst.getOpcode()) {
5791 default: llvm_unreachable("unexpected opcode!");
5792 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5793 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5794 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5795 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5796 }
Jim Grosbach23f22072011-11-16 18:31:45 +00005797 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5798 MCInst TmpInst;
5799 TmpInst.setOpcode(ARM::MOVsr);
5800 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5801 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5802 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5803 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5804 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5805 TmpInst.addOperand(Inst.getOperand(4));
5806 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5807 Inst = TmpInst;
5808 return true;
5809 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005810 case ARM::ASRi:
5811 case ARM::LSRi:
5812 case ARM::LSLi:
5813 case ARM::RORi: {
5814 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005815 switch(Inst.getOpcode()) {
5816 default: llvm_unreachable("unexpected opcode!");
5817 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5818 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5819 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5820 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5821 }
5822 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005823 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005824 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5825 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005826 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005827 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005828 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5829 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005830 if (Opc == ARM::MOVsi)
5831 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005832 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5833 TmpInst.addOperand(Inst.getOperand(4));
5834 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5835 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005836 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005837 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005838 case ARM::RRXi: {
5839 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5840 MCInst TmpInst;
5841 TmpInst.setOpcode(ARM::MOVsi);
5842 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5843 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5844 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5845 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5846 TmpInst.addOperand(Inst.getOperand(3));
5847 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5848 Inst = TmpInst;
5849 return true;
5850 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005851 case ARM::t2LDMIA_UPD: {
5852 // If this is a load of a single register, then we should use
5853 // a post-indexed LDR instruction instead, per the ARM ARM.
5854 if (Inst.getNumOperands() != 5)
5855 return false;
5856 MCInst TmpInst;
5857 TmpInst.setOpcode(ARM::t2LDR_POST);
5858 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5859 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5860 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5861 TmpInst.addOperand(MCOperand::CreateImm(4));
5862 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5863 TmpInst.addOperand(Inst.getOperand(3));
5864 Inst = TmpInst;
5865 return true;
5866 }
5867 case ARM::t2STMDB_UPD: {
5868 // If this is a store of a single register, then we should use
5869 // a pre-indexed STR instruction instead, per the ARM ARM.
5870 if (Inst.getNumOperands() != 5)
5871 return false;
5872 MCInst TmpInst;
5873 TmpInst.setOpcode(ARM::t2STR_PRE);
5874 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5875 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5876 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5877 TmpInst.addOperand(MCOperand::CreateImm(-4));
5878 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5879 TmpInst.addOperand(Inst.getOperand(3));
5880 Inst = TmpInst;
5881 return true;
5882 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005883 case ARM::LDMIA_UPD:
5884 // If this is a load of a single register via a 'pop', then we should use
5885 // a post-indexed LDR instruction instead, per the ARM ARM.
5886 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5887 Inst.getNumOperands() == 5) {
5888 MCInst TmpInst;
5889 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5890 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5891 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5892 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5893 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5894 TmpInst.addOperand(MCOperand::CreateImm(4));
5895 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5896 TmpInst.addOperand(Inst.getOperand(3));
5897 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005898 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005899 }
5900 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005901 case ARM::STMDB_UPD:
5902 // If this is a store of a single register via a 'push', then we should use
5903 // a pre-indexed STR instruction instead, per the ARM ARM.
5904 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5905 Inst.getNumOperands() == 5) {
5906 MCInst TmpInst;
5907 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5908 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5909 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5910 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5911 TmpInst.addOperand(MCOperand::CreateImm(-4));
5912 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5913 TmpInst.addOperand(Inst.getOperand(3));
5914 Inst = TmpInst;
5915 }
5916 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005917 case ARM::t2ADDri12:
5918 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5919 // mnemonic was used (not "addw"), encoding T3 is preferred.
5920 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5921 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5922 break;
5923 Inst.setOpcode(ARM::t2ADDri);
5924 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5925 break;
5926 case ARM::t2SUBri12:
5927 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5928 // mnemonic was used (not "subw"), encoding T3 is preferred.
5929 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5930 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5931 break;
5932 Inst.setOpcode(ARM::t2SUBri);
5933 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5934 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005935 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005936 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5937 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5938 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5939 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005940 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005941 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005942 return true;
5943 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005944 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005945 case ARM::tSUBi8:
5946 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5947 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5948 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5949 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005950 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005951 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005952 return true;
5953 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005954 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005955 case ARM::t2ADDrr: {
5956 // If the destination and first source operand are the same, and
5957 // there's no setting of the flags, use encoding T2 instead of T3.
5958 // Note that this is only for ADD, not SUB. This mirrors the system
5959 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5960 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5961 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005962 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5963 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005964 break;
5965 MCInst TmpInst;
5966 TmpInst.setOpcode(ARM::tADDhirr);
5967 TmpInst.addOperand(Inst.getOperand(0));
5968 TmpInst.addOperand(Inst.getOperand(0));
5969 TmpInst.addOperand(Inst.getOperand(2));
5970 TmpInst.addOperand(Inst.getOperand(3));
5971 TmpInst.addOperand(Inst.getOperand(4));
5972 Inst = TmpInst;
5973 return true;
5974 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005975 case ARM::tB:
5976 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005977 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005978 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005979 return true;
5980 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005981 break;
5982 case ARM::t2B:
5983 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005984 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005985 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005986 return true;
5987 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005988 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005989 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005990 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005991 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005992 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005993 return true;
5994 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005995 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005996 case ARM::tBcc:
5997 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005998 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005999 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006000 return true;
6001 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00006002 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006003 case ARM::tLDMIA: {
6004 // If the register list contains any high registers, or if the writeback
6005 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
6006 // instead if we're in Thumb2. Otherwise, this should have generated
6007 // an error in validateInstruction().
6008 unsigned Rn = Inst.getOperand(0).getReg();
6009 bool hasWritebackToken =
6010 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
6011 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
6012 bool listContainsBase;
6013 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
6014 (!listContainsBase && !hasWritebackToken) ||
6015 (listContainsBase && hasWritebackToken)) {
6016 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6017 assert (isThumbTwo());
6018 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
6019 // If we're switching to the updating version, we need to insert
6020 // the writeback tied operand.
6021 if (hasWritebackToken)
6022 Inst.insert(Inst.begin(),
6023 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006024 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006025 }
6026 break;
6027 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006028 case ARM::tSTMIA_UPD: {
6029 // If the register list contains any high registers, we need to use
6030 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6031 // should have generated an error in validateInstruction().
6032 unsigned Rn = Inst.getOperand(0).getReg();
6033 bool listContainsBase;
6034 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6035 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6036 assert (isThumbTwo());
6037 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006038 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006039 }
6040 break;
6041 }
Jim Grosbach54026372011-11-10 23:17:11 +00006042 case ARM::tPOP: {
6043 bool listContainsBase;
6044 // If the register list contains any high registers, we need to use
6045 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6046 // should have generated an error in validateInstruction().
6047 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006048 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006049 assert (isThumbTwo());
6050 Inst.setOpcode(ARM::t2LDMIA_UPD);
6051 // Add the base register and writeback operands.
6052 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6053 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006054 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006055 }
6056 case ARM::tPUSH: {
6057 bool listContainsBase;
6058 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006059 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006060 assert (isThumbTwo());
6061 Inst.setOpcode(ARM::t2STMDB_UPD);
6062 // Add the base register and writeback operands.
6063 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6064 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006065 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006066 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006067 case ARM::t2MOVi: {
6068 // If we can use the 16-bit encoding and the user didn't explicitly
6069 // request the 32-bit variant, transform it here.
6070 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6071 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006072 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6073 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6074 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006075 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6076 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6077 // The operands aren't in the same order for tMOVi8...
6078 MCInst TmpInst;
6079 TmpInst.setOpcode(ARM::tMOVi8);
6080 TmpInst.addOperand(Inst.getOperand(0));
6081 TmpInst.addOperand(Inst.getOperand(4));
6082 TmpInst.addOperand(Inst.getOperand(1));
6083 TmpInst.addOperand(Inst.getOperand(2));
6084 TmpInst.addOperand(Inst.getOperand(3));
6085 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006086 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006087 }
6088 break;
6089 }
6090 case ARM::t2MOVr: {
6091 // If we can use the 16-bit encoding and the user didn't explicitly
6092 // request the 32-bit variant, transform it here.
6093 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6094 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6095 Inst.getOperand(2).getImm() == ARMCC::AL &&
6096 Inst.getOperand(4).getReg() == ARM::CPSR &&
6097 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6098 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6099 // The operands aren't the same for tMOV[S]r... (no cc_out)
6100 MCInst TmpInst;
6101 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6102 TmpInst.addOperand(Inst.getOperand(0));
6103 TmpInst.addOperand(Inst.getOperand(1));
6104 TmpInst.addOperand(Inst.getOperand(2));
6105 TmpInst.addOperand(Inst.getOperand(3));
6106 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006107 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006108 }
6109 break;
6110 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006111 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006112 case ARM::t2SXTB:
6113 case ARM::t2UXTH:
6114 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006115 // If we can use the 16-bit encoding and the user didn't explicitly
6116 // request the 32-bit variant, transform it here.
6117 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6118 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6119 Inst.getOperand(2).getImm() == 0 &&
6120 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6121 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006122 unsigned NewOpc;
6123 switch (Inst.getOpcode()) {
6124 default: llvm_unreachable("Illegal opcode!");
6125 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6126 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6127 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6128 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6129 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006130 // The operands aren't the same for thumb1 (no rotate operand).
6131 MCInst TmpInst;
6132 TmpInst.setOpcode(NewOpc);
6133 TmpInst.addOperand(Inst.getOperand(0));
6134 TmpInst.addOperand(Inst.getOperand(1));
6135 TmpInst.addOperand(Inst.getOperand(3));
6136 TmpInst.addOperand(Inst.getOperand(4));
6137 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006138 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006139 }
6140 break;
6141 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006142 case ARM::MOVsi: {
6143 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6144 if (SOpc == ARM_AM::rrx) return false;
6145 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6146 // Shifting by zero is accepted as a vanilla 'MOVr'
6147 MCInst TmpInst;
6148 TmpInst.setOpcode(ARM::MOVr);
6149 TmpInst.addOperand(Inst.getOperand(0));
6150 TmpInst.addOperand(Inst.getOperand(1));
6151 TmpInst.addOperand(Inst.getOperand(3));
6152 TmpInst.addOperand(Inst.getOperand(4));
6153 TmpInst.addOperand(Inst.getOperand(5));
6154 Inst = TmpInst;
6155 return true;
6156 }
6157 return false;
6158 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00006159 case ARM::ANDrsi:
6160 case ARM::ORRrsi:
6161 case ARM::EORrsi:
6162 case ARM::BICrsi:
6163 case ARM::SUBrsi:
6164 case ARM::ADDrsi: {
6165 unsigned newOpc;
6166 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
6167 if (SOpc == ARM_AM::rrx) return false;
6168 switch (Inst.getOpcode()) {
6169 default: assert("unexpected opcode!");
6170 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
6171 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
6172 case ARM::EORrsi: newOpc = ARM::EORrr; break;
6173 case ARM::BICrsi: newOpc = ARM::BICrr; break;
6174 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
6175 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
6176 }
6177 // If the shift is by zero, use the non-shifted instruction definition.
6178 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
6179 MCInst TmpInst;
6180 TmpInst.setOpcode(newOpc);
6181 TmpInst.addOperand(Inst.getOperand(0));
6182 TmpInst.addOperand(Inst.getOperand(1));
6183 TmpInst.addOperand(Inst.getOperand(2));
6184 TmpInst.addOperand(Inst.getOperand(4));
6185 TmpInst.addOperand(Inst.getOperand(5));
6186 TmpInst.addOperand(Inst.getOperand(6));
6187 Inst = TmpInst;
6188 return true;
6189 }
6190 return false;
6191 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006192 case ARM::t2IT: {
6193 // The mask bits for all but the first condition are represented as
6194 // the low bit of the condition code value implies 't'. We currently
6195 // always have 1 implies 't', so XOR toggle the bits if the low bit
6196 // of the condition code is zero. The encoding also expects the low
6197 // bit of the condition to be encoded as bit 4 of the mask operand,
6198 // so mask that in if needed
6199 MCOperand &MO = Inst.getOperand(1);
6200 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006201 unsigned OrigMask = Mask;
6202 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006203 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006204 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6205 for (unsigned i = 3; i != TZ; --i)
6206 Mask ^= 1 << i;
6207 } else
6208 Mask |= 0x10;
6209 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006210
6211 // Set up the IT block state according to the IT instruction we just
6212 // matched.
6213 assert(!inITBlock() && "nested IT blocks?!");
6214 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6215 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6216 ITState.CurPosition = 0;
6217 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006218 break;
6219 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006220 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006221 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006222}
6223
Jim Grosbach47a0d522011-08-16 20:45:50 +00006224unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6225 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6226 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006227 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006228 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006229 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6230 assert(MCID.hasOptionalDef() &&
6231 "optionally flag setting instruction missing optional def operand");
6232 assert(MCID.NumOperands == Inst.getNumOperands() &&
6233 "operand count mismatch!");
6234 // Find the optional-def operand (cc_out).
6235 unsigned OpNo;
6236 for (OpNo = 0;
6237 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6238 ++OpNo)
6239 ;
6240 // If we're parsing Thumb1, reject it completely.
6241 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6242 return Match_MnemonicFail;
6243 // If we're parsing Thumb2, which form is legal depends on whether we're
6244 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006245 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6246 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006247 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006248 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6249 inITBlock())
6250 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006251 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006252 // Some high-register supporting Thumb1 encodings only allow both registers
6253 // to be from r0-r7 when in Thumb2.
6254 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6255 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6256 isARMLowRegister(Inst.getOperand(2).getReg()))
6257 return Match_RequiresThumb2;
6258 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006259 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006260 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6261 isARMLowRegister(Inst.getOperand(1).getReg()))
6262 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006263 return Match_Success;
6264}
6265
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006266bool ARMAsmParser::
6267MatchAndEmitInstruction(SMLoc IDLoc,
6268 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6269 MCStreamer &Out) {
6270 MCInst Inst;
6271 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006272 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006273 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006274 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006275 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006276 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006277 // Context sensitive operand constraints aren't handled by the matcher,
6278 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006279 if (validateInstruction(Inst, Operands)) {
6280 // Still progress the IT block, otherwise one wrong condition causes
6281 // nasty cascading errors.
6282 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006283 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006284 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006285
Jim Grosbachf8fce712011-08-11 17:35:48 +00006286 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006287 // encoding is selected. Loop on it while changes happen so the
6288 // individual transformations can chain off each other. E.g.,
6289 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6290 while (processInstruction(Inst, Operands))
6291 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006292
Jim Grosbacha1109882011-09-02 23:22:08 +00006293 // Only move forward at the very end so that everything in validate
6294 // and process gets a consistent answer about whether we're in an IT
6295 // block.
6296 forwardITPosition();
6297
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006298 Out.EmitInstruction(Inst);
6299 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006300 case Match_MissingFeature:
6301 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6302 return true;
6303 case Match_InvalidOperand: {
6304 SMLoc ErrorLoc = IDLoc;
6305 if (ErrorInfo != ~0U) {
6306 if (ErrorInfo >= Operands.size())
6307 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006308
Chris Lattnere73d4f82010-10-28 21:41:58 +00006309 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6310 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6311 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006312
Chris Lattnere73d4f82010-10-28 21:41:58 +00006313 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006314 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006315 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006316 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006317 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006318 // The converter function will have already emited a diagnostic.
6319 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006320 case Match_RequiresNotITBlock:
6321 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006322 case Match_RequiresITBlock:
6323 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006324 case Match_RequiresV6:
6325 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6326 case Match_RequiresThumb2:
6327 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006328 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006329
Eric Christopherc223e2b2010-10-29 09:26:59 +00006330 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006331 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006332}
6333
Jim Grosbach1355cf12011-07-26 17:10:22 +00006334/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006335bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6336 StringRef IDVal = DirectiveID.getIdentifier();
6337 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006338 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006339 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006340 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006341 else if (IDVal == ".arm")
6342 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006343 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006344 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006345 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006346 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006347 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006348 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006349 else if (IDVal == ".unreq")
6350 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006351 else if (IDVal == ".arch")
6352 return parseDirectiveArch(DirectiveID.getLoc());
6353 else if (IDVal == ".eabi_attribute")
6354 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006355 return true;
6356}
6357
Jim Grosbach1355cf12011-07-26 17:10:22 +00006358/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006359/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006360bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006361 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6362 for (;;) {
6363 const MCExpr *Value;
6364 if (getParser().ParseExpression(Value))
6365 return true;
6366
Chris Lattneraaec2052010-01-19 19:46:13 +00006367 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006368
6369 if (getLexer().is(AsmToken::EndOfStatement))
6370 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006371
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006372 // FIXME: Improve diagnostic.
6373 if (getLexer().isNot(AsmToken::Comma))
6374 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006375 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006376 }
6377 }
6378
Sean Callananb9a25b72010-01-19 20:27:46 +00006379 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006380 return false;
6381}
6382
Jim Grosbach1355cf12011-07-26 17:10:22 +00006383/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006384/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006385bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006386 if (getLexer().isNot(AsmToken::EndOfStatement))
6387 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006388 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006389
Jim Grosbach9a70df92011-12-07 18:04:19 +00006390 if (!isThumb())
6391 SwitchMode();
6392 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6393 return false;
6394}
6395
6396/// parseDirectiveARM
6397/// ::= .arm
6398bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6399 if (getLexer().isNot(AsmToken::EndOfStatement))
6400 return Error(L, "unexpected token in directive");
6401 Parser.Lex();
6402
6403 if (isThumb())
6404 SwitchMode();
6405 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006406 return false;
6407}
6408
Jim Grosbach1355cf12011-07-26 17:10:22 +00006409/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006410/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006411bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006412 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6413 bool isMachO = MAI.hasSubsectionsViaSymbols();
6414 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00006415 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00006416
Jim Grosbachde4d8392011-12-21 22:30:16 +00006417 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00006418 // ELF doesn't
6419 if (isMachO) {
6420 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00006421 if (Tok.isNot(AsmToken::EndOfStatement)) {
6422 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6423 return Error(L, "unexpected token in .thumb_func directive");
6424 Name = Tok.getIdentifier();
6425 Parser.Lex(); // Consume the identifier token.
6426 needFuncName = false;
6427 }
Rafael Espindola64695402011-05-16 16:17:21 +00006428 }
6429
Jim Grosbachde4d8392011-12-21 22:30:16 +00006430 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006431 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00006432
6433 // Eat the end of statement and any blank lines that follow.
6434 while (getLexer().is(AsmToken::EndOfStatement))
6435 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006436
Rafael Espindola64695402011-05-16 16:17:21 +00006437 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00006438 // We really should be checking the next symbol definition even if there's
6439 // stuff in between.
6440 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006441 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006442 }
6443
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006444 // Mark symbol as a thumb symbol.
6445 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6446 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006447 return false;
6448}
6449
Jim Grosbach1355cf12011-07-26 17:10:22 +00006450/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006451/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006452bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006453 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006454 if (Tok.isNot(AsmToken::Identifier))
6455 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006456 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006457 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006458 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006459 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006460 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006461 else
6462 return Error(L, "unrecognized syntax mode in .syntax directive");
6463
6464 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006465 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006466 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006467
6468 // TODO tell the MC streamer the mode
6469 // getParser().getStreamer().Emit???();
6470 return false;
6471}
6472
Jim Grosbach1355cf12011-07-26 17:10:22 +00006473/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006474/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006475bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006476 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006477 if (Tok.isNot(AsmToken::Integer))
6478 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006479 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006480 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006481 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006482 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006483 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006484 else
6485 return Error(L, "invalid operand to .code directive");
6486
6487 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006488 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006489 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006490
Evan Cheng32869202011-07-08 22:36:29 +00006491 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006492 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006493 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006494 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006495 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006496 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006497 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006498 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006499 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006500
Kevin Enderby515d5092009-10-15 20:48:48 +00006501 return false;
6502}
6503
Jim Grosbacha39cda72011-12-14 02:16:11 +00006504/// parseDirectiveReq
6505/// ::= name .req registername
6506bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6507 Parser.Lex(); // Eat the '.req' token.
6508 unsigned Reg;
6509 SMLoc SRegLoc, ERegLoc;
6510 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6511 Parser.EatToEndOfStatement();
6512 return Error(SRegLoc, "register name expected");
6513 }
6514
6515 // Shouldn't be anything else.
6516 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6517 Parser.EatToEndOfStatement();
6518 return Error(Parser.getTok().getLoc(),
6519 "unexpected input in .req directive.");
6520 }
6521
6522 Parser.Lex(); // Consume the EndOfStatement
6523
6524 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6525 return Error(SRegLoc, "redefinition of '" + Name +
6526 "' does not match original.");
6527
6528 return false;
6529}
6530
6531/// parseDirectiveUneq
6532/// ::= .unreq registername
6533bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6534 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6535 Parser.EatToEndOfStatement();
6536 return Error(L, "unexpected input in .unreq directive.");
6537 }
6538 RegisterReqs.erase(Parser.getTok().getIdentifier());
6539 Parser.Lex(); // Eat the identifier.
6540 return false;
6541}
6542
Jason W Kimd7c9e082011-12-20 17:38:12 +00006543/// parseDirectiveArch
6544/// ::= .arch token
6545bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6546 return true;
6547}
6548
6549/// parseDirectiveEabiAttr
6550/// ::= .eabi_attribute int, int
6551bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6552 return true;
6553}
6554
Sean Callanan90b70972010-04-07 20:29:34 +00006555extern "C" void LLVMInitializeARMAsmLexer();
6556
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006557/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006558extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006559 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6560 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006561 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006562}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006563
Chris Lattner0692ee62010-09-06 19:11:01 +00006564#define GET_REGISTER_MATCHER
6565#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006566#include "ARMGenAsmMatcher.inc"