blob: 93e84040b7bd11b92d11db9831b2582e43b6ec66 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan76264762010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbach862019c2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendling8155e5b2010-11-06 22:19:43 +0000344 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000351
Jim Grosbach9d390362011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000400
Bill Wendling146018f2010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan76264762010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000425 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan76264762010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000479
Sean Callanan76264762010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Daniel Dunbar8462b302010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503 }
504
Bill Wendling5fa22a12010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000509 }
510
Kevin Enderbycfe07242009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000512 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbach9d390362011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbach460a9052011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000550 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
557 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000558 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
565 }
566 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
573 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000574 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 256;
581 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000582 bool isImm0_1() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 2;
589 }
590 bool isImm0_3() const {
591 if (Kind != k_Immediate)
592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 4;
597 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000598 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 16;
613 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000614 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 32;
621 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 bool isImm0_63() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value >= 0 && Value < 64;
629 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000630 bool isImm8() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 8;
637 }
638 bool isImm16() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value == 16;
645 }
646 bool isImm32() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value == 32;
653 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000654 bool isShrImm8() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value <= 8;
661 }
662 bool isShrImm16() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value <= 16;
669 }
670 bool isShrImm32() const {
671 if (Kind != k_Immediate)
672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value <= 32;
677 }
678 bool isShrImm64() const {
679 if (Kind != k_Immediate)
680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value > 0 && Value <= 64;
685 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000686 bool isImm1_7() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 8;
693 }
694 bool isImm1_15() const {
695 if (Kind != k_Immediate)
696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value > 0 && Value < 16;
701 }
702 bool isImm1_31() const {
703 if (Kind != k_Immediate)
704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value < 32;
709 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000710 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000712 return false;
713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 17;
717 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000718 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000720 return false;
721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
722 if (!CE) return false;
723 int64_t Value = CE->getValue();
724 return Value > 0 && Value < 33;
725 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000726 bool isImm0_32() const {
727 if (Kind != k_Immediate)
728 return false;
729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 33;
733 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000734 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 if (!CE) return false;
739 int64_t Value = CE->getValue();
740 return Value >= 0 && Value < 65536;
741 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000742 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000743 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000744 return false;
745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
746 // If it's not a constant expression, it'll generate a fixup and be
747 // handled later.
748 if (!CE) return true;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 65536;
751 }
Jim Grosbached838482011-07-26 16:24:27 +0000752 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return Value >= 0 && Value <= 0xffffff;
759 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000760 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return Value > 0 && Value < 33;
767 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000768 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value >= 0 && Value < 32;
775 }
776 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return Value > 0 && Value <= 32;
783 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000784 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000785 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getSOImmVal(Value) != -1;
791 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000792 bool isARMSOImmNot() const {
793 if (Kind != k_Immediate)
794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return ARM_AM::getSOImmVal(~Value) != -1;
799 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000800 bool isARMSOImmNeg() const {
801 if (Kind != k_Immediate)
802 return false;
803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getSOImmVal(-Value) != -1;
807 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000808 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000809 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000810 return false;
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 int64_t Value = CE->getValue();
814 return ARM_AM::getT2SOImmVal(Value) != -1;
815 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000816 bool isT2SOImmNot() const {
817 if (Kind != k_Immediate)
818 return false;
819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
820 if (!CE) return false;
821 int64_t Value = CE->getValue();
822 return ARM_AM::getT2SOImmVal(~Value) != -1;
823 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000824 bool isT2SOImmNeg() const {
825 if (Kind != k_Immediate)
826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return ARM_AM::getT2SOImmVal(-Value) != -1;
831 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000832 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000833 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000834 return false;
835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
838 return Value == 1 || Value == 0;
839 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000840 bool isReg() const { return Kind == k_Register; }
841 bool isRegList() const { return Kind == k_RegisterList; }
842 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
843 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
844 bool isToken() const { return Kind == k_Token; }
845 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
846 bool isMemory() const { return Kind == k_Memory; }
847 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
848 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
849 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
850 bool isRotImm() const { return Kind == k_RotateImmediate; }
851 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
852 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000853 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000854 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000855 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000857 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000858 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
861 (alignOK || Memory.Alignment == 0);
862 }
863 bool isAlignedMemory() const {
864 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000867 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000869 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000873 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000874 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000875 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000876 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000877 return false;
878 // Immediate offset in range [-4095, 4095].
879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
880 if (!CE) return false;
881 int64_t Val = CE->getValue();
882 return Val > -4096 && Val < 4096;
883 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000884 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000885 // If we have an immediate that's not a constant, treat it as a label
886 // reference needing a fixup. If it is a constant, it's something else
887 // and we reject it.
888 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
889 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000893 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000894 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000895 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000896 if (!Memory.OffsetImm) return true;
897 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000898 return Val > -256 && Val < 256;
899 }
900 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000901 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000902 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000903 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000904 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
905 // Immediate offset in range [-255, 255].
906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000909 // Special case, #-0 is INT32_MIN.
910 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000911 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
917 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000918 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000919 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000920 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000924 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000925 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000926 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000927 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000929 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000930 return false;
931 return true;
932 }
933 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000935 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
936 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000937 return false;
938 return true;
939 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000942 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000943 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000944 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000945 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
947 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000948 return false;
949 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000950 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000951 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000953 return false;
954 return true;
955 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000956 bool isMemThumbRR() const {
957 // Thumb reg+reg addressing is simple. Just two registers, a base and
958 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000959 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000960 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000961 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 return isARMLowRegister(Memory.BaseRegNum) &&
963 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000964 }
965 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000966 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000967 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000968 return false;
969 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000970 if (!Memory.OffsetImm) return true;
971 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000972 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
973 }
Jim Grosbach38466302011-08-19 18:55:51 +0000974 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000976 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000977 return false;
978 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000979 if (!Memory.OffsetImm) return true;
980 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000981 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
982 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000983 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000985 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000986 return false;
987 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000988 if (!Memory.OffsetImm) return true;
989 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000990 return Val >= 0 && Val <= 31;
991 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000992 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000993 if (!isMemory() || Memory.OffsetRegNum != 0 ||
994 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000995 return false;
996 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000999 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001000 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001001 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001002 // If we have an immediate that's not a constant, treat it as a label
1003 // reference needing a fixup. If it is a constant, it's something else
1004 // and we reject it.
1005 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
1006 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001007 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001008 return false;
1009 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001010 if (!Memory.OffsetImm) return true;
1011 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001012 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1013 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001014 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001015 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001016 return false;
1017 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001018 if (!Memory.OffsetImm) return true;
1019 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001020 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1021 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001022 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001023 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001024 return false;
1025 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001026 if (!Memory.OffsetImm) return true;
1027 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001028 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001029 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001030 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001032 return false;
1033 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001036 return Val >= 0 && Val < 256;
1037 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001038 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001040 return false;
1041 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001042 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001044 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001045 }
1046 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001048 return false;
1049 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001050 if (!Memory.OffsetImm) return true;
1051 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001052 return (Val >= 0 && Val < 4096);
1053 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001054 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001055 // If we have an immediate that's not a constant, treat it as a label
1056 // reference needing a fixup. If it is a constant, it's something else
1057 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001058 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001059 return true;
1060
Jim Grosbach57dcb852011-10-11 17:29:55 +00001061 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001062 return false;
1063 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001064 if (!Memory.OffsetImm) return true;
1065 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001066 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001067 }
1068 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001070 return false;
1071 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1072 if (!CE) return false;
1073 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001074 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001075 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001076 bool isPostIdxImm8s4() const {
1077 if (Kind != k_Immediate)
1078 return false;
1079 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1080 if (!CE) return false;
1081 int64_t Val = CE->getValue();
1082 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1083 (Val == INT32_MIN);
1084 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001085
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001086 bool isMSRMask() const { return Kind == k_MSRMask; }
1087 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001088
Jim Grosbach0e387b22011-10-17 22:26:03 +00001089 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 bool isSingleSpacedVectorList() const {
1091 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1092 }
1093 bool isDoubleSpacedVectorList() const {
1094 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1095 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001096 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001098 return VectorList.Count == 1;
1099 }
1100
Jim Grosbach280dfad2011-10-21 18:54:25 +00001101 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001103 return VectorList.Count == 2;
1104 }
1105
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001106 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001107 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001108 return VectorList.Count == 3;
1109 }
1110
Jim Grosbachb6310312011-10-21 20:35:01 +00001111 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001112 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001113 return VectorList.Count == 4;
1114 }
1115
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001116 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001117 if (!isDoubleSpacedVectorList()) return false;
1118 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001119 }
1120
Jim Grosbach98b05a52011-11-30 01:09:44 +00001121 bool isVecListOneDAllLanes() const {
1122 if (Kind != k_VectorListAllLanes) return false;
1123 return VectorList.Count == 1;
1124 }
1125
Jim Grosbach13af2222011-11-30 18:21:25 +00001126 bool isVecListTwoDAllLanes() const {
1127 if (Kind != k_VectorListAllLanes) return false;
1128 return VectorList.Count == 2;
1129 }
1130
Jim Grosbach7636bf62011-12-02 00:35:16 +00001131 bool isVecListOneDByteIndexed() const {
1132 if (Kind != k_VectorListIndexed) return false;
1133 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1134 }
1135
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001136 bool isVecListOneDHWordIndexed() const {
1137 if (Kind != k_VectorListIndexed) return false;
1138 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1139 }
1140
1141 bool isVecListOneDWordIndexed() const {
1142 if (Kind != k_VectorListIndexed) return false;
1143 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1144 }
1145
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001146 bool isVecListTwoDByteIndexed() const {
1147 if (Kind != k_VectorListIndexed) return false;
1148 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1149 }
1150
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001151 bool isVecListTwoDHWordIndexed() const {
1152 if (Kind != k_VectorListIndexed) return false;
1153 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1154 }
1155
1156 bool isVecListTwoDWordIndexed() const {
1157 if (Kind != k_VectorListIndexed) return false;
1158 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1159 }
1160
Jim Grosbach460a9052011-10-07 23:56:00 +00001161 bool isVectorIndex8() const {
1162 if (Kind != k_VectorIndex) return false;
1163 return VectorIndex.Val < 8;
1164 }
1165 bool isVectorIndex16() const {
1166 if (Kind != k_VectorIndex) return false;
1167 return VectorIndex.Val < 4;
1168 }
1169 bool isVectorIndex32() const {
1170 if (Kind != k_VectorIndex) return false;
1171 return VectorIndex.Val < 2;
1172 }
1173
Jim Grosbach0e387b22011-10-17 22:26:03 +00001174 bool isNEONi8splat() const {
1175 if (Kind != k_Immediate)
1176 return false;
1177 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1178 // Must be a constant.
1179 if (!CE) return false;
1180 int64_t Value = CE->getValue();
1181 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1182 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001183 return Value >= 0 && Value < 256;
1184 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001185
Jim Grosbachea461102011-10-17 23:09:09 +00001186 bool isNEONi16splat() const {
1187 if (Kind != k_Immediate)
1188 return false;
1189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1190 // Must be a constant.
1191 if (!CE) return false;
1192 int64_t Value = CE->getValue();
1193 // i16 value in the range [0,255] or [0x0100, 0xff00]
1194 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1195 }
1196
Jim Grosbach6248a542011-10-18 00:22:00 +00001197 bool isNEONi32splat() const {
1198 if (Kind != k_Immediate)
1199 return false;
1200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1201 // Must be a constant.
1202 if (!CE) return false;
1203 int64_t Value = CE->getValue();
1204 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1205 return (Value >= 0 && Value < 256) ||
1206 (Value >= 0x0100 && Value <= 0xff00) ||
1207 (Value >= 0x010000 && Value <= 0xff0000) ||
1208 (Value >= 0x01000000 && Value <= 0xff000000);
1209 }
1210
1211 bool isNEONi32vmov() const {
1212 if (Kind != k_Immediate)
1213 return false;
1214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 // Must be a constant.
1216 if (!CE) return false;
1217 int64_t Value = CE->getValue();
1218 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1219 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1220 return (Value >= 0 && Value < 256) ||
1221 (Value >= 0x0100 && Value <= 0xff00) ||
1222 (Value >= 0x010000 && Value <= 0xff0000) ||
1223 (Value >= 0x01000000 && Value <= 0xff000000) ||
1224 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1225 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1226 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001227 bool isNEONi32vmovNeg() const {
1228 if (Kind != k_Immediate)
1229 return false;
1230 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1231 // Must be a constant.
1232 if (!CE) return false;
1233 int64_t Value = ~CE->getValue();
1234 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1235 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1236 return (Value >= 0 && Value < 256) ||
1237 (Value >= 0x0100 && Value <= 0xff00) ||
1238 (Value >= 0x010000 && Value <= 0xff0000) ||
1239 (Value >= 0x01000000 && Value <= 0xff000000) ||
1240 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1241 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1242 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001243
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001244 bool isNEONi64splat() const {
1245 if (Kind != k_Immediate)
1246 return false;
1247 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1248 // Must be a constant.
1249 if (!CE) return false;
1250 uint64_t Value = CE->getValue();
1251 // i64 value with each byte being either 0 or 0xff.
1252 for (unsigned i = 0; i < 8; ++i)
1253 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1254 return true;
1255 }
1256
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001257 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001258 // Add as immediates when possible. Null MCExpr = 0.
1259 if (Expr == 0)
1260 Inst.addOperand(MCOperand::CreateImm(0));
1261 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001262 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1263 else
1264 Inst.addOperand(MCOperand::CreateExpr(Expr));
1265 }
1266
Daniel Dunbar8462b302010-08-11 06:36:53 +00001267 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001268 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001269 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001270 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1271 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001272 }
1273
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001274 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1275 assert(N == 1 && "Invalid number of operands!");
1276 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1277 }
1278
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001279 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
1281 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1282 }
1283
1284 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
1286 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1287 }
1288
Jim Grosbach89df9962011-08-26 21:43:41 +00001289 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
1291 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1292 }
1293
1294 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1295 assert(N == 1 && "Invalid number of operands!");
1296 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1297 }
1298
Jim Grosbachd67641b2010-12-06 18:21:12 +00001299 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1300 assert(N == 1 && "Invalid number of operands!");
1301 Inst.addOperand(MCOperand::CreateReg(getReg()));
1302 }
1303
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001304 void addRegOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
1306 Inst.addOperand(MCOperand::CreateReg(getReg()));
1307 }
1308
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001309 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001310 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001311 assert(isRegShiftedReg() &&
1312 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001313 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1314 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001315 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001316 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001317 }
1318
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001319 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001320 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001321 assert(isRegShiftedImm() &&
1322 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001323 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001324 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001325 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001326 }
1327
Jim Grosbach580f4a92011-07-25 22:20:28 +00001328 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001329 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001330 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1331 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001332 }
1333
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001334 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001335 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001336 const SmallVectorImpl<unsigned> &RegList = getRegList();
1337 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001338 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1339 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001340 }
1341
Bill Wendling0f630752010-11-17 04:32:08 +00001342 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1343 addRegListOperands(Inst, N);
1344 }
1345
1346 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1347 addRegListOperands(Inst, N);
1348 }
1349
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001350 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1351 assert(N == 1 && "Invalid number of operands!");
1352 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1353 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1354 }
1355
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001356 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1357 assert(N == 1 && "Invalid number of operands!");
1358 // Munge the lsb/width into a bitfield mask.
1359 unsigned lsb = Bitfield.LSB;
1360 unsigned width = Bitfield.Width;
1361 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1362 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1363 (32 - (lsb + width)));
1364 Inst.addOperand(MCOperand::CreateImm(Mask));
1365 }
1366
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001367 void addImmOperands(MCInst &Inst, unsigned N) const {
1368 assert(N == 1 && "Invalid number of operands!");
1369 addExpr(Inst, getImm());
1370 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001371
Jim Grosbach9d390362011-10-03 23:38:36 +00001372 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1375 }
1376
Jim Grosbacha77295d2011-09-08 22:07:06 +00001377 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 // FIXME: We really want to scale the value here, but the LDRD/STRD
1380 // instruction don't encode operands that way yet.
1381 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1382 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1383 }
1384
Jim Grosbach72f39f82011-08-24 21:22:15 +00001385 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 // The immediate is scaled by four in the encoding and is stored
1388 // in the MCInst as such. Lop off the low two bits here.
1389 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1390 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1391 }
1392
1393 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 // The immediate is scaled by four in the encoding and is stored
1396 // in the MCInst as such. Lop off the low two bits here.
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1399 }
1400
Jim Grosbachf4943352011-07-25 23:09:14 +00001401 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 // The constant encodes as the immediate-1, and we store in the instruction
1404 // the bits as encoded, so subtract off one here.
1405 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1406 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1407 }
1408
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001409 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 // The constant encodes as the immediate-1, and we store in the instruction
1412 // the bits as encoded, so subtract off one here.
1413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1414 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1415 }
1416
Jim Grosbach70939ee2011-08-17 21:51:27 +00001417 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 // The constant encodes as the immediate, except for 32, which encodes as
1420 // zero.
1421 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1422 unsigned Imm = CE->getValue();
1423 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1424 }
1425
Jim Grosbachf6c05252011-07-21 17:23:04 +00001426 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
1428 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1429 // the instruction as well.
1430 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1431 int Val = CE->getValue();
1432 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1433 }
1434
Jim Grosbach89a63372011-10-28 22:36:30 +00001435 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
1437 // The operand is actually a t2_so_imm, but we have its bitwise
1438 // negation in the assembly source, so twiddle it here.
1439 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1440 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1441 }
1442
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001443 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1444 assert(N == 1 && "Invalid number of operands!");
1445 // The operand is actually a t2_so_imm, but we have its
1446 // negation in the assembly source, so twiddle it here.
1447 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1448 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1449 }
1450
Jim Grosbache70ec842011-10-28 22:50:54 +00001451 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 // The operand is actually a so_imm, but we have its bitwise
1454 // negation in the assembly source, so twiddle it here.
1455 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1456 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1457 }
1458
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001459 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
1461 // The operand is actually a so_imm, but we have its
1462 // negation in the assembly source, so twiddle it here.
1463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1464 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1465 }
1466
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001467 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1470 }
1471
Jim Grosbach7ce05792011-08-03 23:50:40 +00001472 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001474 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001475 }
1476
Jim Grosbach57dcb852011-10-11 17:29:55 +00001477 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 2 && "Invalid number of operands!");
1479 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1480 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1481 }
1482
Jim Grosbach7ce05792011-08-03 23:50:40 +00001483 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1484 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001485 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1486 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001487 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1488 // Special case for #-0
1489 if (Val == INT32_MIN) Val = 0;
1490 if (Val < 0) Val = -Val;
1491 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1492 } else {
1493 // For register offset, we encode the shift type and negation flag
1494 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001495 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1496 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001497 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001498 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1499 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001500 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001501 }
1502
Jim Grosbach039c2e12011-08-04 23:01:30 +00001503 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1506 assert(CE && "non-constant AM2OffsetImm operand!");
1507 int32_t Val = CE->getValue();
1508 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1509 // Special case for #-0
1510 if (Val == INT32_MIN) Val = 0;
1511 if (Val < 0) Val = -Val;
1512 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1513 Inst.addOperand(MCOperand::CreateReg(0));
1514 Inst.addOperand(MCOperand::CreateImm(Val));
1515 }
1516
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001517 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1518 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001519 // If we have an immediate that's not a constant, treat it as a label
1520 // reference needing a fixup. If it is a constant, it's something else
1521 // and we reject it.
1522 if (isImm()) {
1523 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1524 Inst.addOperand(MCOperand::CreateReg(0));
1525 Inst.addOperand(MCOperand::CreateImm(0));
1526 return;
1527 }
1528
Jim Grosbache53c87b2011-10-11 15:59:20 +00001529 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1530 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001531 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1532 // Special case for #-0
1533 if (Val == INT32_MIN) Val = 0;
1534 if (Val < 0) Val = -Val;
1535 Val = ARM_AM::getAM3Opc(AddSub, Val);
1536 } else {
1537 // For register offset, we encode the shift type and negation flag
1538 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001539 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001540 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001541 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1542 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001543 Inst.addOperand(MCOperand::CreateImm(Val));
1544 }
1545
1546 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1547 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001548 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001549 int32_t Val =
1550 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1551 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1552 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001553 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001554 }
1555
1556 // Constant offset.
1557 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1558 int32_t Val = CE->getValue();
1559 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1560 // Special case for #-0
1561 if (Val == INT32_MIN) Val = 0;
1562 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001563 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001564 Inst.addOperand(MCOperand::CreateReg(0));
1565 Inst.addOperand(MCOperand::CreateImm(Val));
1566 }
1567
Jim Grosbach7ce05792011-08-03 23:50:40 +00001568 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001570 // If we have an immediate that's not a constant, treat it as a label
1571 // reference needing a fixup. If it is a constant, it's something else
1572 // and we reject it.
1573 if (isImm()) {
1574 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1575 Inst.addOperand(MCOperand::CreateImm(0));
1576 return;
1577 }
1578
Jim Grosbach7ce05792011-08-03 23:50:40 +00001579 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001580 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001581 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1582 // Special case for #-0
1583 if (Val == INT32_MIN) Val = 0;
1584 if (Val < 0) Val = -Val;
1585 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001586 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001587 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001588 }
1589
Jim Grosbacha77295d2011-09-08 22:07:06 +00001590 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1591 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001592 // If we have an immediate that's not a constant, treat it as a label
1593 // reference needing a fixup. If it is a constant, it's something else
1594 // and we reject it.
1595 if (isImm()) {
1596 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1597 Inst.addOperand(MCOperand::CreateImm(0));
1598 return;
1599 }
1600
Jim Grosbache53c87b2011-10-11 15:59:20 +00001601 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1602 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001603 Inst.addOperand(MCOperand::CreateImm(Val));
1604 }
1605
Jim Grosbachb6aed502011-09-09 18:37:27 +00001606 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 2 && "Invalid number of operands!");
1608 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001609 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1610 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001611 Inst.addOperand(MCOperand::CreateImm(Val));
1612 }
1613
Jim Grosbach7ce05792011-08-03 23:50:40 +00001614 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1615 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001616 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1617 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001618 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001619 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001620
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001621 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1622 addMemImm8OffsetOperands(Inst, N);
1623 }
1624
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001625 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001626 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001627 }
1628
1629 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 2 && "Invalid number of operands!");
1631 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001632 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001633 addExpr(Inst, getImm());
1634 Inst.addOperand(MCOperand::CreateImm(0));
1635 return;
1636 }
1637
1638 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001639 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1640 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001641 Inst.addOperand(MCOperand::CreateImm(Val));
1642 }
1643
Jim Grosbach7ce05792011-08-03 23:50:40 +00001644 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1645 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001646 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001647 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001648 addExpr(Inst, getImm());
1649 Inst.addOperand(MCOperand::CreateImm(0));
1650 return;
1651 }
1652
1653 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001654 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1655 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001656 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001657 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001658
Jim Grosbach7f739be2011-09-19 22:21:13 +00001659 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1660 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001661 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1662 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001663 }
1664
1665 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1666 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001667 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1668 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001669 }
1670
Jim Grosbach7ce05792011-08-03 23:50:40 +00001671 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1672 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001673 unsigned Val =
1674 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1675 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001676 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1677 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001678 Inst.addOperand(MCOperand::CreateImm(Val));
1679 }
1680
Jim Grosbachab899c12011-09-07 23:10:15 +00001681 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1682 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001683 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1684 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1685 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001686 }
1687
Jim Grosbach7ce05792011-08-03 23:50:40 +00001688 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1689 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001690 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1691 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001692 }
1693
Jim Grosbach60f91a32011-08-19 17:55:24 +00001694 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1695 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001696 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1697 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001698 Inst.addOperand(MCOperand::CreateImm(Val));
1699 }
1700
Jim Grosbach38466302011-08-19 18:55:51 +00001701 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1702 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001703 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1704 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001705 Inst.addOperand(MCOperand::CreateImm(Val));
1706 }
1707
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001708 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1709 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001710 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1711 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001712 Inst.addOperand(MCOperand::CreateImm(Val));
1713 }
1714
Jim Grosbachecd85892011-08-19 18:13:48 +00001715 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001717 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1718 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001719 Inst.addOperand(MCOperand::CreateImm(Val));
1720 }
1721
Jim Grosbach7ce05792011-08-03 23:50:40 +00001722 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1723 assert(N == 1 && "Invalid number of operands!");
1724 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1725 assert(CE && "non-constant post-idx-imm8 operand!");
1726 int Imm = CE->getValue();
1727 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001728 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001729 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1730 Inst.addOperand(MCOperand::CreateImm(Imm));
1731 }
1732
Jim Grosbach2bd01182011-10-11 21:55:36 +00001733 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1734 assert(N == 1 && "Invalid number of operands!");
1735 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1736 assert(CE && "non-constant post-idx-imm8s4 operand!");
1737 int Imm = CE->getValue();
1738 bool isAdd = Imm >= 0;
1739 if (Imm == INT32_MIN) Imm = 0;
1740 // Immediate is scaled by 4.
1741 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1742 Inst.addOperand(MCOperand::CreateImm(Imm));
1743 }
1744
Jim Grosbach7ce05792011-08-03 23:50:40 +00001745 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1746 assert(N == 2 && "Invalid number of operands!");
1747 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001748 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1749 }
1750
1751 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1752 assert(N == 2 && "Invalid number of operands!");
1753 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1754 // The sign, shift type, and shift amount are encoded in a single operand
1755 // using the AM2 encoding helpers.
1756 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1757 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1758 PostIdxReg.ShiftTy);
1759 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001760 }
1761
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001762 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1763 assert(N == 1 && "Invalid number of operands!");
1764 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1765 }
1766
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001767 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1768 assert(N == 1 && "Invalid number of operands!");
1769 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1770 }
1771
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001772 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001773 assert(N == 1 && "Invalid number of operands!");
1774 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1775 }
1776
Jim Grosbach7636bf62011-12-02 00:35:16 +00001777 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1778 assert(N == 2 && "Invalid number of operands!");
1779 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1780 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1781 }
1782
Jim Grosbach460a9052011-10-07 23:56:00 +00001783 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1784 assert(N == 1 && "Invalid number of operands!");
1785 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1786 }
1787
1788 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1789 assert(N == 1 && "Invalid number of operands!");
1790 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1791 }
1792
1793 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1794 assert(N == 1 && "Invalid number of operands!");
1795 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1796 }
1797
Jim Grosbach0e387b22011-10-17 22:26:03 +00001798 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1799 assert(N == 1 && "Invalid number of operands!");
1800 // The immediate encodes the type of constant as well as the value.
1801 // Mask in that this is an i8 splat.
1802 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1803 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1804 }
1805
Jim Grosbachea461102011-10-17 23:09:09 +00001806 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1807 assert(N == 1 && "Invalid number of operands!");
1808 // The immediate encodes the type of constant as well as the value.
1809 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1810 unsigned Value = CE->getValue();
1811 if (Value >= 256)
1812 Value = (Value >> 8) | 0xa00;
1813 else
1814 Value |= 0x800;
1815 Inst.addOperand(MCOperand::CreateImm(Value));
1816 }
1817
Jim Grosbach6248a542011-10-18 00:22:00 +00001818 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1819 assert(N == 1 && "Invalid number of operands!");
1820 // The immediate encodes the type of constant as well as the value.
1821 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1822 unsigned Value = CE->getValue();
1823 if (Value >= 256 && Value <= 0xff00)
1824 Value = (Value >> 8) | 0x200;
1825 else if (Value > 0xffff && Value <= 0xff0000)
1826 Value = (Value >> 16) | 0x400;
1827 else if (Value > 0xffffff)
1828 Value = (Value >> 24) | 0x600;
1829 Inst.addOperand(MCOperand::CreateImm(Value));
1830 }
1831
1832 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1833 assert(N == 1 && "Invalid number of operands!");
1834 // The immediate encodes the type of constant as well as the value.
1835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1836 unsigned Value = CE->getValue();
1837 if (Value >= 256 && Value <= 0xffff)
1838 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1839 else if (Value > 0xffff && Value <= 0xffffff)
1840 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1841 else if (Value > 0xffffff)
1842 Value = (Value >> 24) | 0x600;
1843 Inst.addOperand(MCOperand::CreateImm(Value));
1844 }
1845
Jim Grosbach9b087852011-12-19 23:51:07 +00001846 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1847 assert(N == 1 && "Invalid number of operands!");
1848 // The immediate encodes the type of constant as well as the value.
1849 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1850 unsigned Value = ~CE->getValue();
1851 if (Value >= 256 && Value <= 0xffff)
1852 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1853 else if (Value > 0xffff && Value <= 0xffffff)
1854 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1855 else if (Value > 0xffffff)
1856 Value = (Value >> 24) | 0x600;
1857 Inst.addOperand(MCOperand::CreateImm(Value));
1858 }
1859
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001860 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1861 assert(N == 1 && "Invalid number of operands!");
1862 // The immediate encodes the type of constant as well as the value.
1863 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1864 uint64_t Value = CE->getValue();
1865 unsigned Imm = 0;
1866 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1867 Imm |= (Value & 1) << i;
1868 }
1869 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1870 }
1871
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001872 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001873
Jim Grosbach89df9962011-08-26 21:43:41 +00001874 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001875 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001876 Op->ITMask.Mask = Mask;
1877 Op->StartLoc = S;
1878 Op->EndLoc = S;
1879 return Op;
1880 }
1881
Chris Lattner3a697562010-10-28 17:20:03 +00001882 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001883 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001884 Op->CC.Val = CC;
1885 Op->StartLoc = S;
1886 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001887 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001888 }
1889
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001890 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001892 Op->Cop.Val = CopVal;
1893 Op->StartLoc = S;
1894 Op->EndLoc = S;
1895 return Op;
1896 }
1897
1898 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001899 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001900 Op->Cop.Val = CopVal;
1901 Op->StartLoc = S;
1902 Op->EndLoc = S;
1903 return Op;
1904 }
1905
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001906 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1907 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1908 Op->Cop.Val = Val;
1909 Op->StartLoc = S;
1910 Op->EndLoc = E;
1911 return Op;
1912 }
1913
Jim Grosbachd67641b2010-12-06 18:21:12 +00001914 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001916 Op->Reg.RegNum = RegNum;
1917 Op->StartLoc = S;
1918 Op->EndLoc = S;
1919 return Op;
1920 }
1921
Chris Lattner3a697562010-10-28 17:20:03 +00001922 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001924 Op->Tok.Data = Str.data();
1925 Op->Tok.Length = Str.size();
1926 Op->StartLoc = S;
1927 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001928 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001929 }
1930
Bill Wendling50d0f582010-11-18 23:43:05 +00001931 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001932 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001933 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001934 Op->StartLoc = S;
1935 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001936 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001937 }
1938
Jim Grosbache8606dc2011-07-13 17:50:29 +00001939 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1940 unsigned SrcReg,
1941 unsigned ShiftReg,
1942 unsigned ShiftImm,
1943 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001945 Op->RegShiftedReg.ShiftTy = ShTy;
1946 Op->RegShiftedReg.SrcReg = SrcReg;
1947 Op->RegShiftedReg.ShiftReg = ShiftReg;
1948 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001949 Op->StartLoc = S;
1950 Op->EndLoc = E;
1951 return Op;
1952 }
1953
Owen Anderson92a20222011-07-21 18:54:16 +00001954 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1955 unsigned SrcReg,
1956 unsigned ShiftImm,
1957 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001958 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001959 Op->RegShiftedImm.ShiftTy = ShTy;
1960 Op->RegShiftedImm.SrcReg = SrcReg;
1961 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001962 Op->StartLoc = S;
1963 Op->EndLoc = E;
1964 return Op;
1965 }
1966
Jim Grosbach580f4a92011-07-25 22:20:28 +00001967 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001968 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001970 Op->ShifterImm.isASR = isASR;
1971 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001972 Op->StartLoc = S;
1973 Op->EndLoc = E;
1974 return Op;
1975 }
1976
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001977 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001978 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001979 Op->RotImm.Imm = Imm;
1980 Op->StartLoc = S;
1981 Op->EndLoc = E;
1982 return Op;
1983 }
1984
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001985 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1986 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001987 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001988 Op->Bitfield.LSB = LSB;
1989 Op->Bitfield.Width = Width;
1990 Op->StartLoc = S;
1991 Op->EndLoc = E;
1992 return Op;
1993 }
1994
Bill Wendling7729e062010-11-09 22:44:22 +00001995 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001996 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001997 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001998 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001999
Jim Grosbachd300b942011-09-13 22:56:44 +00002000 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002001 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002002 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002003 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002004 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002005
2006 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002007 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002008 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002009 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002010 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002011 Op->StartLoc = StartLoc;
2012 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002013 return Op;
2014 }
2015
Jim Grosbach862019c2011-10-18 23:02:30 +00002016 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002017 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002018 ARMOperand *Op = new ARMOperand(k_VectorList);
2019 Op->VectorList.RegNum = RegNum;
2020 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002021 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002022 Op->StartLoc = S;
2023 Op->EndLoc = E;
2024 return Op;
2025 }
2026
Jim Grosbach98b05a52011-11-30 01:09:44 +00002027 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
2028 SMLoc S, SMLoc E) {
2029 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2030 Op->VectorList.RegNum = RegNum;
2031 Op->VectorList.Count = Count;
2032 Op->StartLoc = S;
2033 Op->EndLoc = E;
2034 return Op;
2035 }
2036
Jim Grosbach7636bf62011-12-02 00:35:16 +00002037 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
2038 unsigned Index, SMLoc S, SMLoc E) {
2039 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2040 Op->VectorList.RegNum = RegNum;
2041 Op->VectorList.Count = Count;
2042 Op->VectorList.LaneIndex = Index;
2043 Op->StartLoc = S;
2044 Op->EndLoc = E;
2045 return Op;
2046 }
2047
Jim Grosbach460a9052011-10-07 23:56:00 +00002048 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2049 MCContext &Ctx) {
2050 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2051 Op->VectorIndex.Val = Idx;
2052 Op->StartLoc = S;
2053 Op->EndLoc = E;
2054 return Op;
2055 }
2056
Chris Lattner3a697562010-10-28 17:20:03 +00002057 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002058 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002059 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002060 Op->StartLoc = S;
2061 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002062 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002063 }
2064
Jim Grosbach9d390362011-10-03 23:38:36 +00002065 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002066 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002067 Op->FPImm.Val = Val;
2068 Op->StartLoc = S;
2069 Op->EndLoc = S;
2070 return Op;
2071 }
2072
Jim Grosbach7ce05792011-08-03 23:50:40 +00002073 static ARMOperand *CreateMem(unsigned BaseRegNum,
2074 const MCConstantExpr *OffsetImm,
2075 unsigned OffsetRegNum,
2076 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002077 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002078 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002079 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002080 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002081 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002082 Op->Memory.BaseRegNum = BaseRegNum;
2083 Op->Memory.OffsetImm = OffsetImm;
2084 Op->Memory.OffsetRegNum = OffsetRegNum;
2085 Op->Memory.ShiftType = ShiftType;
2086 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002087 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002088 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002089 Op->StartLoc = S;
2090 Op->EndLoc = E;
2091 return Op;
2092 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002093
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002094 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2095 ARM_AM::ShiftOpc ShiftTy,
2096 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002097 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002098 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002099 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002100 Op->PostIdxReg.isAdd = isAdd;
2101 Op->PostIdxReg.ShiftTy = ShiftTy;
2102 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002103 Op->StartLoc = S;
2104 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002105 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002106 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002107
2108 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002109 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002110 Op->MBOpt.Val = Opt;
2111 Op->StartLoc = S;
2112 Op->EndLoc = S;
2113 return Op;
2114 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002115
2116 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002117 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002118 Op->IFlags.Val = IFlags;
2119 Op->StartLoc = S;
2120 Op->EndLoc = S;
2121 return Op;
2122 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002123
2124 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002125 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002126 Op->MMask.Val = MMask;
2127 Op->StartLoc = S;
2128 Op->EndLoc = S;
2129 return Op;
2130 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002131};
2132
2133} // end anonymous namespace.
2134
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002135void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002136 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002137 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002138 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2139 << ") >";
2140 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002141 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002142 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002143 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002144 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002145 OS << "<ccout " << getReg() << ">";
2146 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002147 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002148 static const char *MaskStr[] = {
2149 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2150 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2151 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002152 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2153 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2154 break;
2155 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002156 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002157 OS << "<coprocessor number: " << getCoproc() << ">";
2158 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002159 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002160 OS << "<coprocessor register: " << getCoproc() << ">";
2161 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002162 case k_CoprocOption:
2163 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2164 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002165 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002166 OS << "<mask: " << getMSRMask() << ">";
2167 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002168 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002169 getImm()->print(OS);
2170 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002171 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002172 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2173 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002174 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002175 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002176 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002177 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002178 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002179 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002180 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2181 << PostIdxReg.RegNum;
2182 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2183 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2184 << PostIdxReg.ShiftImm;
2185 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002186 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002187 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002188 OS << "<ARM_PROC::";
2189 unsigned IFlags = getProcIFlags();
2190 for (int i=2; i >= 0; --i)
2191 if (IFlags & (1 << i))
2192 OS << ARM_PROC::IFlagsToString(1 << i);
2193 OS << ">";
2194 break;
2195 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002196 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002197 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002198 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002199 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002200 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2201 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002202 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002203 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002204 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002205 << RegShiftedReg.SrcReg << " "
2206 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2207 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002208 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002209 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002210 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002211 << RegShiftedImm.SrcReg << " "
2212 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2213 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002214 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002215 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002216 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2217 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002218 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002219 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2220 << ", width: " << Bitfield.Width << ">";
2221 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002222 case k_RegisterList:
2223 case k_DPRRegisterList:
2224 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002225 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002226
Bill Wendling5fa22a12010-11-09 23:28:44 +00002227 const SmallVectorImpl<unsigned> &RegList = getRegList();
2228 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002229 I = RegList.begin(), E = RegList.end(); I != E; ) {
2230 OS << *I;
2231 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002232 }
2233
2234 OS << ">";
2235 break;
2236 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002237 case k_VectorList:
2238 OS << "<vector_list " << VectorList.Count << " * "
2239 << VectorList.RegNum << ">";
2240 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002241 case k_VectorListAllLanes:
2242 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2243 << VectorList.RegNum << ">";
2244 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002245 case k_VectorListIndexed:
2246 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2247 << VectorList.Count << " * " << VectorList.RegNum << ">";
2248 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002249 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002250 OS << "'" << getToken() << "'";
2251 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002252 case k_VectorIndex:
2253 OS << "<vectorindex " << getVectorIndex() << ">";
2254 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002255 }
2256}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002257
2258/// @name Auto-generated Match Functions
2259/// {
2260
2261static unsigned MatchRegisterName(StringRef Name);
2262
2263/// }
2264
Bob Wilson69df7232011-02-03 21:46:10 +00002265bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2266 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002267 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002268 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002269 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002270
2271 return (RegNo == (unsigned)-1);
2272}
2273
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002274/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002275/// and if it is a register name the token is eaten and the register number is
2276/// returned. Otherwise return -1.
2277///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002278int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002279 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002280 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002281
Benjamin Kramer59085362011-11-06 20:37:06 +00002282 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002283 unsigned RegNum = MatchRegisterName(lowerCase);
2284 if (!RegNum) {
2285 RegNum = StringSwitch<unsigned>(lowerCase)
2286 .Case("r13", ARM::SP)
2287 .Case("r14", ARM::LR)
2288 .Case("r15", ARM::PC)
2289 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002290 // Additional register name aliases for 'gas' compatibility.
2291 .Case("a1", ARM::R0)
2292 .Case("a2", ARM::R1)
2293 .Case("a3", ARM::R2)
2294 .Case("a4", ARM::R3)
2295 .Case("v1", ARM::R4)
2296 .Case("v2", ARM::R5)
2297 .Case("v3", ARM::R6)
2298 .Case("v4", ARM::R7)
2299 .Case("v5", ARM::R8)
2300 .Case("v6", ARM::R9)
2301 .Case("v7", ARM::R10)
2302 .Case("v8", ARM::R11)
2303 .Case("sb", ARM::R9)
2304 .Case("sl", ARM::R10)
2305 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002306 .Default(0);
2307 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002308 if (!RegNum) {
2309 // Check for aliases registered via .req.
2310 StringMap<unsigned>::const_iterator Entry =
2311 RegisterReqs.find(Tok.getIdentifier());
2312 // If no match, return failure.
2313 if (Entry == RegisterReqs.end())
2314 return -1;
2315 Parser.Lex(); // Eat identifier token.
2316 return Entry->getValue();
2317 }
Bob Wilson69df7232011-02-03 21:46:10 +00002318
Chris Lattnere5658fa2010-10-30 04:09:10 +00002319 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002320
Chris Lattnere5658fa2010-10-30 04:09:10 +00002321 return RegNum;
2322}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002323
Jim Grosbach19906722011-07-13 18:49:30 +00002324// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2325// If a recoverable error occurs, return 1. If an irrecoverable error
2326// occurs, return -1. An irrecoverable error is one where tokens have been
2327// consumed in the process of trying to parse the shifter (i.e., when it is
2328// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002329int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002330 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2331 SMLoc S = Parser.getTok().getLoc();
2332 const AsmToken &Tok = Parser.getTok();
2333 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2334
Benjamin Kramer59085362011-11-06 20:37:06 +00002335 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002336 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002337 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002338 .Case("lsl", ARM_AM::lsl)
2339 .Case("lsr", ARM_AM::lsr)
2340 .Case("asr", ARM_AM::asr)
2341 .Case("ror", ARM_AM::ror)
2342 .Case("rrx", ARM_AM::rrx)
2343 .Default(ARM_AM::no_shift);
2344
2345 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002346 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002347
Jim Grosbache8606dc2011-07-13 17:50:29 +00002348 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002349
Jim Grosbache8606dc2011-07-13 17:50:29 +00002350 // The source register for the shift has already been added to the
2351 // operand list, so we need to pop it off and combine it into the shifted
2352 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002353 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002354 if (!PrevOp->isReg())
2355 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2356 int SrcReg = PrevOp->getReg();
2357 int64_t Imm = 0;
2358 int ShiftReg = 0;
2359 if (ShiftTy == ARM_AM::rrx) {
2360 // RRX Doesn't have an explicit shift amount. The encoder expects
2361 // the shift register to be the same as the source register. Seems odd,
2362 // but OK.
2363 ShiftReg = SrcReg;
2364 } else {
2365 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002366 if (Parser.getTok().is(AsmToken::Hash) ||
2367 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002368 Parser.Lex(); // Eat hash.
2369 SMLoc ImmLoc = Parser.getTok().getLoc();
2370 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002371 if (getParser().ParseExpression(ShiftExpr)) {
2372 Error(ImmLoc, "invalid immediate shift value");
2373 return -1;
2374 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002375 // The expression must be evaluatable as an immediate.
2376 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002377 if (!CE) {
2378 Error(ImmLoc, "invalid immediate shift value");
2379 return -1;
2380 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002381 // Range check the immediate.
2382 // lsl, ror: 0 <= imm <= 31
2383 // lsr, asr: 0 <= imm <= 32
2384 Imm = CE->getValue();
2385 if (Imm < 0 ||
2386 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2387 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002388 Error(ImmLoc, "immediate shift value out of range");
2389 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002390 }
2391 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002392 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002393 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002394 if (ShiftReg == -1) {
2395 Error (L, "expected immediate or register in shift operand");
2396 return -1;
2397 }
2398 } else {
2399 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002400 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002401 return -1;
2402 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002403 }
2404
Owen Anderson92a20222011-07-21 18:54:16 +00002405 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2406 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002407 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002408 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002409 else
2410 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2411 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002412
Jim Grosbach19906722011-07-13 18:49:30 +00002413 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002414}
2415
2416
Bill Wendling50d0f582010-11-18 23:43:05 +00002417/// Try to parse a register name. The token must be an Identifier when called.
2418/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2419/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002420///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002421/// TODO this is likely to change to allow different register types and or to
2422/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002423bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002424tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002425 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002426 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002427 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002428 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002429
Bill Wendling50d0f582010-11-18 23:43:05 +00002430 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002431
Chris Lattnere5658fa2010-10-30 04:09:10 +00002432 const AsmToken &ExclaimTok = Parser.getTok();
2433 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002434 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2435 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002436 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002437 return false;
2438 }
2439
2440 // Also check for an index operand. This is only legal for vector registers,
2441 // but that'll get caught OK in operand matching, so we don't need to
2442 // explicitly filter everything else out here.
2443 if (Parser.getTok().is(AsmToken::LBrac)) {
2444 SMLoc SIdx = Parser.getTok().getLoc();
2445 Parser.Lex(); // Eat left bracket token.
2446
2447 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002448 if (getParser().ParseExpression(ImmVal))
2449 return MatchOperand_ParseFail;
2450 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2451 if (!MCE) {
2452 TokError("immediate value expected for vector index");
2453 return MatchOperand_ParseFail;
2454 }
2455
2456 SMLoc E = Parser.getTok().getLoc();
2457 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2458 Error(E, "']' expected");
2459 return MatchOperand_ParseFail;
2460 }
2461
2462 Parser.Lex(); // Eat right bracket token.
2463
2464 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2465 SIdx, E,
2466 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002467 }
2468
Bill Wendling50d0f582010-11-18 23:43:05 +00002469 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002470}
2471
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002472/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2473/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2474/// "c5", ...
2475static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002476 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2477 // but efficient.
2478 switch (Name.size()) {
2479 default: break;
2480 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002481 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002482 return -1;
2483 switch (Name[1]) {
2484 default: return -1;
2485 case '0': return 0;
2486 case '1': return 1;
2487 case '2': return 2;
2488 case '3': return 3;
2489 case '4': return 4;
2490 case '5': return 5;
2491 case '6': return 6;
2492 case '7': return 7;
2493 case '8': return 8;
2494 case '9': return 9;
2495 }
2496 break;
2497 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002498 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002499 return -1;
2500 switch (Name[2]) {
2501 default: return -1;
2502 case '0': return 10;
2503 case '1': return 11;
2504 case '2': return 12;
2505 case '3': return 13;
2506 case '4': return 14;
2507 case '5': return 15;
2508 }
2509 break;
2510 }
2511
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002512 return -1;
2513}
2514
Jim Grosbach89df9962011-08-26 21:43:41 +00002515/// parseITCondCode - Try to parse a condition code for an IT instruction.
2516ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2517parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2518 SMLoc S = Parser.getTok().getLoc();
2519 const AsmToken &Tok = Parser.getTok();
2520 if (!Tok.is(AsmToken::Identifier))
2521 return MatchOperand_NoMatch;
2522 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2523 .Case("eq", ARMCC::EQ)
2524 .Case("ne", ARMCC::NE)
2525 .Case("hs", ARMCC::HS)
2526 .Case("cs", ARMCC::HS)
2527 .Case("lo", ARMCC::LO)
2528 .Case("cc", ARMCC::LO)
2529 .Case("mi", ARMCC::MI)
2530 .Case("pl", ARMCC::PL)
2531 .Case("vs", ARMCC::VS)
2532 .Case("vc", ARMCC::VC)
2533 .Case("hi", ARMCC::HI)
2534 .Case("ls", ARMCC::LS)
2535 .Case("ge", ARMCC::GE)
2536 .Case("lt", ARMCC::LT)
2537 .Case("gt", ARMCC::GT)
2538 .Case("le", ARMCC::LE)
2539 .Case("al", ARMCC::AL)
2540 .Default(~0U);
2541 if (CC == ~0U)
2542 return MatchOperand_NoMatch;
2543 Parser.Lex(); // Eat the token.
2544
2545 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2546
2547 return MatchOperand_Success;
2548}
2549
Jim Grosbach43904292011-07-25 20:14:50 +00002550/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002551/// token must be an Identifier when called, and if it is a coprocessor
2552/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002553ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002554parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002555 SMLoc S = Parser.getTok().getLoc();
2556 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002557 if (Tok.isNot(AsmToken::Identifier))
2558 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002559
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002560 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002561 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002562 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002563
2564 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002565 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002566 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002567}
2568
Jim Grosbach43904292011-07-25 20:14:50 +00002569/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002570/// token must be an Identifier when called, and if it is a coprocessor
2571/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002572ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002573parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002574 SMLoc S = Parser.getTok().getLoc();
2575 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002576 if (Tok.isNot(AsmToken::Identifier))
2577 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002578
2579 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2580 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002581 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002582
2583 Parser.Lex(); // Eat identifier token.
2584 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002585 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002586}
2587
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002588/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2589/// coproc_option : '{' imm0_255 '}'
2590ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2591parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2592 SMLoc S = Parser.getTok().getLoc();
2593
2594 // If this isn't a '{', this isn't a coprocessor immediate operand.
2595 if (Parser.getTok().isNot(AsmToken::LCurly))
2596 return MatchOperand_NoMatch;
2597 Parser.Lex(); // Eat the '{'
2598
2599 const MCExpr *Expr;
2600 SMLoc Loc = Parser.getTok().getLoc();
2601 if (getParser().ParseExpression(Expr)) {
2602 Error(Loc, "illegal expression");
2603 return MatchOperand_ParseFail;
2604 }
2605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2606 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2607 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2608 return MatchOperand_ParseFail;
2609 }
2610 int Val = CE->getValue();
2611
2612 // Check for and consume the closing '}'
2613 if (Parser.getTok().isNot(AsmToken::RCurly))
2614 return MatchOperand_ParseFail;
2615 SMLoc E = Parser.getTok().getLoc();
2616 Parser.Lex(); // Eat the '}'
2617
2618 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2619 return MatchOperand_Success;
2620}
2621
Jim Grosbachd0588e22011-09-14 18:08:35 +00002622// For register list parsing, we need to map from raw GPR register numbering
2623// to the enumeration values. The enumeration values aren't sorted by
2624// register number due to our using "sp", "lr" and "pc" as canonical names.
2625static unsigned getNextRegister(unsigned Reg) {
2626 // If this is a GPR, we need to do it manually, otherwise we can rely
2627 // on the sort ordering of the enumeration since the other reg-classes
2628 // are sane.
2629 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2630 return Reg + 1;
2631 switch(Reg) {
2632 default: assert(0 && "Invalid GPR number!");
2633 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2634 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2635 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2636 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2637 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2638 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2639 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2640 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2641 }
2642}
2643
Jim Grosbachce485e72011-11-11 21:27:40 +00002644// Return the low-subreg of a given Q register.
2645static unsigned getDRegFromQReg(unsigned QReg) {
2646 switch (QReg) {
2647 default: llvm_unreachable("expected a Q register!");
2648 case ARM::Q0: return ARM::D0;
2649 case ARM::Q1: return ARM::D2;
2650 case ARM::Q2: return ARM::D4;
2651 case ARM::Q3: return ARM::D6;
2652 case ARM::Q4: return ARM::D8;
2653 case ARM::Q5: return ARM::D10;
2654 case ARM::Q6: return ARM::D12;
2655 case ARM::Q7: return ARM::D14;
2656 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002657 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002658 case ARM::Q10: return ARM::D20;
2659 case ARM::Q11: return ARM::D22;
2660 case ARM::Q12: return ARM::D24;
2661 case ARM::Q13: return ARM::D26;
2662 case ARM::Q14: return ARM::D28;
2663 case ARM::Q15: return ARM::D30;
2664 }
2665}
2666
Jim Grosbachd0588e22011-09-14 18:08:35 +00002667/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002668bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002669parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002670 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002671 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002672 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002673 Parser.Lex(); // Eat '{' token.
2674 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002675
Jim Grosbachd0588e22011-09-14 18:08:35 +00002676 // Check the first register in the list to see what register class
2677 // this is a list of.
2678 int Reg = tryParseRegister();
2679 if (Reg == -1)
2680 return Error(RegLoc, "register expected");
2681
Jim Grosbachce485e72011-11-11 21:27:40 +00002682 // The reglist instructions have at most 16 registers, so reserve
2683 // space for that many.
2684 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2685
2686 // Allow Q regs and just interpret them as the two D sub-registers.
2687 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2688 Reg = getDRegFromQReg(Reg);
2689 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2690 ++Reg;
2691 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002692 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002693 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2694 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2695 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2696 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2697 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2698 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2699 else
2700 return Error(RegLoc, "invalid register in register list");
2701
Jim Grosbachce485e72011-11-11 21:27:40 +00002702 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002703 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002704
Jim Grosbachd0588e22011-09-14 18:08:35 +00002705 // This starts immediately after the first register token in the list,
2706 // so we can see either a comma or a minus (range separator) as a legal
2707 // next token.
2708 while (Parser.getTok().is(AsmToken::Comma) ||
2709 Parser.getTok().is(AsmToken::Minus)) {
2710 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002711 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002712 SMLoc EndLoc = Parser.getTok().getLoc();
2713 int EndReg = tryParseRegister();
2714 if (EndReg == -1)
2715 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002716 // Allow Q regs and just interpret them as the two D sub-registers.
2717 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2718 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002719 // If the register is the same as the start reg, there's nothing
2720 // more to do.
2721 if (Reg == EndReg)
2722 continue;
2723 // The register must be in the same register class as the first.
2724 if (!RC->contains(EndReg))
2725 return Error(EndLoc, "invalid register in register list");
2726 // Ranges must go from low to high.
2727 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2728 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002729
Jim Grosbachd0588e22011-09-14 18:08:35 +00002730 // Add all the registers in the range to the register list.
2731 while (Reg != EndReg) {
2732 Reg = getNextRegister(Reg);
2733 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2734 }
2735 continue;
2736 }
2737 Parser.Lex(); // Eat the comma.
2738 RegLoc = Parser.getTok().getLoc();
2739 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002740 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002741 Reg = tryParseRegister();
2742 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002743 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002744 // Allow Q regs and just interpret them as the two D sub-registers.
2745 bool isQReg = false;
2746 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2747 Reg = getDRegFromQReg(Reg);
2748 isQReg = true;
2749 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002750 // The register must be in the same register class as the first.
2751 if (!RC->contains(Reg))
2752 return Error(RegLoc, "invalid register in register list");
2753 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002754 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002755 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002756 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2757 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2758 ") in register list");
2759 continue;
2760 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002761 // VFP register lists must also be contiguous.
2762 // It's OK to use the enumeration values directly here rather, as the
2763 // VFP register classes have the enum sorted properly.
2764 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2765 Reg != OldReg + 1)
2766 return Error(RegLoc, "non-contiguous register range");
2767 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002768 if (isQReg)
2769 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002770 }
2771
Jim Grosbachd0588e22011-09-14 18:08:35 +00002772 SMLoc E = Parser.getTok().getLoc();
2773 if (Parser.getTok().isNot(AsmToken::RCurly))
2774 return Error(E, "'}' expected");
2775 Parser.Lex(); // Eat '}' token.
2776
Jim Grosbach27debd62011-12-13 21:48:29 +00002777 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002778 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002779
2780 // The ARM system instruction variants for LDM/STM have a '^' token here.
2781 if (Parser.getTok().is(AsmToken::Caret)) {
2782 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2783 Parser.Lex(); // Eat '^' token.
2784 }
2785
Bill Wendling50d0f582010-11-18 23:43:05 +00002786 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002787}
2788
Jim Grosbach98b05a52011-11-30 01:09:44 +00002789// Helper function to parse the lane index for vector lists.
2790ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002791parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2792 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002793 if (Parser.getTok().is(AsmToken::LBrac)) {
2794 Parser.Lex(); // Eat the '['.
2795 if (Parser.getTok().is(AsmToken::RBrac)) {
2796 // "Dn[]" is the 'all lanes' syntax.
2797 LaneKind = AllLanes;
2798 Parser.Lex(); // Eat the ']'.
2799 return MatchOperand_Success;
2800 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002801 if (Parser.getTok().is(AsmToken::Integer)) {
2802 int64_t Val = Parser.getTok().getIntVal();
2803 // Make this range check context sensitive for .8, .16, .32.
2804 if (Val < 0 && Val > 7)
2805 Error(Parser.getTok().getLoc(), "lane index out of range");
2806 Index = Val;
2807 LaneKind = IndexedLane;
2808 Parser.Lex(); // Eat the token;
2809 if (Parser.getTok().isNot(AsmToken::RBrac))
2810 Error(Parser.getTok().getLoc(), "']' expected");
2811 Parser.Lex(); // Eat the ']'.
2812 return MatchOperand_Success;
2813 }
2814 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002815 return MatchOperand_ParseFail;
2816 }
2817 LaneKind = NoLanes;
2818 return MatchOperand_Success;
2819}
2820
Jim Grosbach862019c2011-10-18 23:02:30 +00002821// parse a vector register list
2822ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2823parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002824 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002825 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002826 SMLoc S = Parser.getTok().getLoc();
2827 // As an extension (to match gas), support a plain D register or Q register
2828 // (without encosing curly braces) as a single or double entry list,
2829 // respectively.
2830 if (Parser.getTok().is(AsmToken::Identifier)) {
2831 int Reg = tryParseRegister();
2832 if (Reg == -1)
2833 return MatchOperand_NoMatch;
2834 SMLoc E = Parser.getTok().getLoc();
2835 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002836 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002837 if (Res != MatchOperand_Success)
2838 return Res;
2839 switch (LaneKind) {
2840 default:
2841 assert(0 && "unexpected lane kind!");
2842 case NoLanes:
2843 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002844 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002845 break;
2846 case AllLanes:
2847 E = Parser.getTok().getLoc();
2848 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2849 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002850 case IndexedLane:
2851 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2852 LaneIndex, S,E));
2853 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002854 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002855 return MatchOperand_Success;
2856 }
2857 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2858 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002859 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002860 if (Res != MatchOperand_Success)
2861 return Res;
2862 switch (LaneKind) {
2863 default:
2864 assert(0 && "unexpected lane kind!");
2865 case NoLanes:
2866 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002867 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002868 break;
2869 case AllLanes:
2870 E = Parser.getTok().getLoc();
2871 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2872 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002873 case IndexedLane:
2874 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2875 LaneIndex, S,E));
2876 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002877 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002878 return MatchOperand_Success;
2879 }
2880 Error(S, "vector register expected");
2881 return MatchOperand_ParseFail;
2882 }
2883
2884 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002885 return MatchOperand_NoMatch;
2886
Jim Grosbach862019c2011-10-18 23:02:30 +00002887 Parser.Lex(); // Eat '{' token.
2888 SMLoc RegLoc = Parser.getTok().getLoc();
2889
2890 int Reg = tryParseRegister();
2891 if (Reg == -1) {
2892 Error(RegLoc, "register expected");
2893 return MatchOperand_ParseFail;
2894 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002895 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002896 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002897 unsigned FirstReg = Reg;
2898 // The list is of D registers, but we also allow Q regs and just interpret
2899 // them as the two D sub-registers.
2900 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2901 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002902 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2903 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002904 ++Reg;
2905 ++Count;
2906 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002907 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002908 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002909
Jim Grosbache43862b2011-11-15 23:19:15 +00002910 while (Parser.getTok().is(AsmToken::Comma) ||
2911 Parser.getTok().is(AsmToken::Minus)) {
2912 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002913 if (!Spacing)
2914 Spacing = 1; // Register range implies a single spaced list.
2915 else if (Spacing == 2) {
2916 Error(Parser.getTok().getLoc(),
2917 "sequential registers in double spaced list");
2918 return MatchOperand_ParseFail;
2919 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002920 Parser.Lex(); // Eat the minus.
2921 SMLoc EndLoc = Parser.getTok().getLoc();
2922 int EndReg = tryParseRegister();
2923 if (EndReg == -1) {
2924 Error(EndLoc, "register expected");
2925 return MatchOperand_ParseFail;
2926 }
2927 // Allow Q regs and just interpret them as the two D sub-registers.
2928 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2929 EndReg = getDRegFromQReg(EndReg) + 1;
2930 // If the register is the same as the start reg, there's nothing
2931 // more to do.
2932 if (Reg == EndReg)
2933 continue;
2934 // The register must be in the same register class as the first.
2935 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2936 Error(EndLoc, "invalid register in register list");
2937 return MatchOperand_ParseFail;
2938 }
2939 // Ranges must go from low to high.
2940 if (Reg > EndReg) {
2941 Error(EndLoc, "bad range in register list");
2942 return MatchOperand_ParseFail;
2943 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002944 // Parse the lane specifier if present.
2945 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002946 unsigned NextLaneIndex;
2947 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002948 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002949 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002950 Error(EndLoc, "mismatched lane index in register list");
2951 return MatchOperand_ParseFail;
2952 }
2953 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002954
2955 // Add all the registers in the range to the register list.
2956 Count += EndReg - Reg;
2957 Reg = EndReg;
2958 continue;
2959 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002960 Parser.Lex(); // Eat the comma.
2961 RegLoc = Parser.getTok().getLoc();
2962 int OldReg = Reg;
2963 Reg = tryParseRegister();
2964 if (Reg == -1) {
2965 Error(RegLoc, "register expected");
2966 return MatchOperand_ParseFail;
2967 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002968 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002969 // It's OK to use the enumeration values directly here rather, as the
2970 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002971 //
2972 // The list is of D registers, but we also allow Q regs and just interpret
2973 // them as the two D sub-registers.
2974 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002975 if (!Spacing)
2976 Spacing = 1; // Register range implies a single spaced list.
2977 else if (Spacing == 2) {
2978 Error(RegLoc,
2979 "invalid register in double-spaced list (must be 'D' register')");
2980 return MatchOperand_ParseFail;
2981 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002982 Reg = getDRegFromQReg(Reg);
2983 if (Reg != OldReg + 1) {
2984 Error(RegLoc, "non-contiguous register range");
2985 return MatchOperand_ParseFail;
2986 }
2987 ++Reg;
2988 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002989 // Parse the lane specifier if present.
2990 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002991 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002992 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002993 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002994 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002995 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002996 Error(EndLoc, "mismatched lane index in register list");
2997 return MatchOperand_ParseFail;
2998 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002999 continue;
3000 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003001 // Normal D register.
3002 // Figure out the register spacing (single or double) of the list if
3003 // we don't know it already.
3004 if (!Spacing)
3005 Spacing = 1 + (Reg == OldReg + 2);
3006
3007 // Just check that it's contiguous and keep going.
3008 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003009 Error(RegLoc, "non-contiguous register range");
3010 return MatchOperand_ParseFail;
3011 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003012 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003013 // Parse the lane specifier if present.
3014 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003015 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003016 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003017 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003018 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003019 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003020 Error(EndLoc, "mismatched lane index in register list");
3021 return MatchOperand_ParseFail;
3022 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003023 if (Spacing == 2 && LaneKind != NoLanes) {
3024 Error(EndLoc,
3025 "lane index specfier invalid in double spaced register list");
3026 return MatchOperand_ParseFail;
3027 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003028 }
3029
3030 SMLoc E = Parser.getTok().getLoc();
3031 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3032 Error(E, "'}' expected");
3033 return MatchOperand_ParseFail;
3034 }
3035 Parser.Lex(); // Eat '}' token.
3036
Jim Grosbach98b05a52011-11-30 01:09:44 +00003037 switch (LaneKind) {
3038 default:
3039 assert(0 && "unexpected lane kind in register list.");
3040 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003041 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3042 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003043 break;
3044 case AllLanes:
3045 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
3046 S, E));
3047 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003048 case IndexedLane:
3049 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
3050 LaneIndex, S, E));
3051 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003052 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003053 return MatchOperand_Success;
3054}
3055
Jim Grosbach43904292011-07-25 20:14:50 +00003056/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003057ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003058parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003059 SMLoc S = Parser.getTok().getLoc();
3060 const AsmToken &Tok = Parser.getTok();
3061 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3062 StringRef OptStr = Tok.getString();
3063
3064 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3065 .Case("sy", ARM_MB::SY)
3066 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003067 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003068 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003069 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003070 .Case("ishst", ARM_MB::ISHST)
3071 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003072 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003073 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003074 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003075 .Case("osh", ARM_MB::OSH)
3076 .Case("oshst", ARM_MB::OSHST)
3077 .Default(~0U);
3078
3079 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003080 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003081
3082 Parser.Lex(); // Eat identifier token.
3083 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003084 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003085}
3086
Jim Grosbach43904292011-07-25 20:14:50 +00003087/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003088ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003089parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003090 SMLoc S = Parser.getTok().getLoc();
3091 const AsmToken &Tok = Parser.getTok();
3092 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3093 StringRef IFlagsStr = Tok.getString();
3094
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003095 // An iflags string of "none" is interpreted to mean that none of the AIF
3096 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003097 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003098 if (IFlagsStr != "none") {
3099 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3100 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3101 .Case("a", ARM_PROC::A)
3102 .Case("i", ARM_PROC::I)
3103 .Case("f", ARM_PROC::F)
3104 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003105
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003106 // If some specific iflag is already set, it means that some letter is
3107 // present more than once, this is not acceptable.
3108 if (Flag == ~0U || (IFlags & Flag))
3109 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003110
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003111 IFlags |= Flag;
3112 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003113 }
3114
3115 Parser.Lex(); // Eat identifier token.
3116 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3117 return MatchOperand_Success;
3118}
3119
Jim Grosbach43904292011-07-25 20:14:50 +00003120/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003121ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003122parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003123 SMLoc S = Parser.getTok().getLoc();
3124 const AsmToken &Tok = Parser.getTok();
3125 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3126 StringRef Mask = Tok.getString();
3127
James Molloyacad68d2011-09-28 14:21:38 +00003128 if (isMClass()) {
3129 // See ARMv6-M 10.1.1
3130 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3131 .Case("apsr", 0)
3132 .Case("iapsr", 1)
3133 .Case("eapsr", 2)
3134 .Case("xpsr", 3)
3135 .Case("ipsr", 5)
3136 .Case("epsr", 6)
3137 .Case("iepsr", 7)
3138 .Case("msp", 8)
3139 .Case("psp", 9)
3140 .Case("primask", 16)
3141 .Case("basepri", 17)
3142 .Case("basepri_max", 18)
3143 .Case("faultmask", 19)
3144 .Case("control", 20)
3145 .Default(~0U);
3146
3147 if (FlagsVal == ~0U)
3148 return MatchOperand_NoMatch;
3149
3150 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3151 // basepri, basepri_max and faultmask only valid for V7m.
3152 return MatchOperand_NoMatch;
3153
3154 Parser.Lex(); // Eat identifier token.
3155 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3156 return MatchOperand_Success;
3157 }
3158
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003159 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3160 size_t Start = 0, Next = Mask.find('_');
3161 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003162 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003163 if (Next != StringRef::npos)
3164 Flags = Mask.slice(Next+1, Mask.size());
3165
3166 // FlagsVal contains the complete mask:
3167 // 3-0: Mask
3168 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3169 unsigned FlagsVal = 0;
3170
3171 if (SpecReg == "apsr") {
3172 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003173 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003174 .Case("g", 0x4) // same as CPSR_s
3175 .Case("nzcvqg", 0xc) // same as CPSR_fs
3176 .Default(~0U);
3177
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003178 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003179 if (!Flags.empty())
3180 return MatchOperand_NoMatch;
3181 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003182 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003183 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003184 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003185 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3186 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003187 for (int i = 0, e = Flags.size(); i != e; ++i) {
3188 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3189 .Case("c", 1)
3190 .Case("x", 2)
3191 .Case("s", 4)
3192 .Case("f", 8)
3193 .Default(~0U);
3194
3195 // If some specific flag is already set, it means that some letter is
3196 // present more than once, this is not acceptable.
3197 if (FlagsVal == ~0U || (FlagsVal & Flag))
3198 return MatchOperand_NoMatch;
3199 FlagsVal |= Flag;
3200 }
3201 } else // No match for special register.
3202 return MatchOperand_NoMatch;
3203
Owen Anderson7784f1d2011-10-21 18:43:28 +00003204 // Special register without flags is NOT equivalent to "fc" flags.
3205 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3206 // two lines would enable gas compatibility at the expense of breaking
3207 // round-tripping.
3208 //
3209 // if (!FlagsVal)
3210 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003211
3212 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3213 if (SpecReg == "spsr")
3214 FlagsVal |= 16;
3215
3216 Parser.Lex(); // Eat identifier token.
3217 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3218 return MatchOperand_Success;
3219}
3220
Jim Grosbachf6c05252011-07-21 17:23:04 +00003221ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3222parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3223 int Low, int High) {
3224 const AsmToken &Tok = Parser.getTok();
3225 if (Tok.isNot(AsmToken::Identifier)) {
3226 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3227 return MatchOperand_ParseFail;
3228 }
3229 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003230 std::string LowerOp = Op.lower();
3231 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003232 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3233 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3234 return MatchOperand_ParseFail;
3235 }
3236 Parser.Lex(); // Eat shift type token.
3237
3238 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003239 if (Parser.getTok().isNot(AsmToken::Hash) &&
3240 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003241 Error(Parser.getTok().getLoc(), "'#' expected");
3242 return MatchOperand_ParseFail;
3243 }
3244 Parser.Lex(); // Eat hash token.
3245
3246 const MCExpr *ShiftAmount;
3247 SMLoc Loc = Parser.getTok().getLoc();
3248 if (getParser().ParseExpression(ShiftAmount)) {
3249 Error(Loc, "illegal expression");
3250 return MatchOperand_ParseFail;
3251 }
3252 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3253 if (!CE) {
3254 Error(Loc, "constant expression expected");
3255 return MatchOperand_ParseFail;
3256 }
3257 int Val = CE->getValue();
3258 if (Val < Low || Val > High) {
3259 Error(Loc, "immediate value out of range");
3260 return MatchOperand_ParseFail;
3261 }
3262
3263 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3264
3265 return MatchOperand_Success;
3266}
3267
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003268ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3269parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3270 const AsmToken &Tok = Parser.getTok();
3271 SMLoc S = Tok.getLoc();
3272 if (Tok.isNot(AsmToken::Identifier)) {
3273 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3274 return MatchOperand_ParseFail;
3275 }
3276 int Val = StringSwitch<int>(Tok.getString())
3277 .Case("be", 1)
3278 .Case("le", 0)
3279 .Default(-1);
3280 Parser.Lex(); // Eat the token.
3281
3282 if (Val == -1) {
3283 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3284 return MatchOperand_ParseFail;
3285 }
3286 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3287 getContext()),
3288 S, Parser.getTok().getLoc()));
3289 return MatchOperand_Success;
3290}
3291
Jim Grosbach580f4a92011-07-25 22:20:28 +00003292/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3293/// instructions. Legal values are:
3294/// lsl #n 'n' in [0,31]
3295/// asr #n 'n' in [1,32]
3296/// n == 32 encoded as n == 0.
3297ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3298parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3299 const AsmToken &Tok = Parser.getTok();
3300 SMLoc S = Tok.getLoc();
3301 if (Tok.isNot(AsmToken::Identifier)) {
3302 Error(S, "shift operator 'asr' or 'lsl' expected");
3303 return MatchOperand_ParseFail;
3304 }
3305 StringRef ShiftName = Tok.getString();
3306 bool isASR;
3307 if (ShiftName == "lsl" || ShiftName == "LSL")
3308 isASR = false;
3309 else if (ShiftName == "asr" || ShiftName == "ASR")
3310 isASR = true;
3311 else {
3312 Error(S, "shift operator 'asr' or 'lsl' expected");
3313 return MatchOperand_ParseFail;
3314 }
3315 Parser.Lex(); // Eat the operator.
3316
3317 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003318 if (Parser.getTok().isNot(AsmToken::Hash) &&
3319 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003320 Error(Parser.getTok().getLoc(), "'#' expected");
3321 return MatchOperand_ParseFail;
3322 }
3323 Parser.Lex(); // Eat hash token.
3324
3325 const MCExpr *ShiftAmount;
3326 SMLoc E = Parser.getTok().getLoc();
3327 if (getParser().ParseExpression(ShiftAmount)) {
3328 Error(E, "malformed shift expression");
3329 return MatchOperand_ParseFail;
3330 }
3331 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3332 if (!CE) {
3333 Error(E, "shift amount must be an immediate");
3334 return MatchOperand_ParseFail;
3335 }
3336
3337 int64_t Val = CE->getValue();
3338 if (isASR) {
3339 // Shift amount must be in [1,32]
3340 if (Val < 1 || Val > 32) {
3341 Error(E, "'asr' shift amount must be in range [1,32]");
3342 return MatchOperand_ParseFail;
3343 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003344 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3345 if (isThumb() && Val == 32) {
3346 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3347 return MatchOperand_ParseFail;
3348 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003349 if (Val == 32) Val = 0;
3350 } else {
3351 // Shift amount must be in [1,32]
3352 if (Val < 0 || Val > 31) {
3353 Error(E, "'lsr' shift amount must be in range [0,31]");
3354 return MatchOperand_ParseFail;
3355 }
3356 }
3357
3358 E = Parser.getTok().getLoc();
3359 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3360
3361 return MatchOperand_Success;
3362}
3363
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003364/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3365/// of instructions. Legal values are:
3366/// ror #n 'n' in {0, 8, 16, 24}
3367ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3368parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3369 const AsmToken &Tok = Parser.getTok();
3370 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003371 if (Tok.isNot(AsmToken::Identifier))
3372 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003373 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003374 if (ShiftName != "ror" && ShiftName != "ROR")
3375 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003376 Parser.Lex(); // Eat the operator.
3377
3378 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003379 if (Parser.getTok().isNot(AsmToken::Hash) &&
3380 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003381 Error(Parser.getTok().getLoc(), "'#' expected");
3382 return MatchOperand_ParseFail;
3383 }
3384 Parser.Lex(); // Eat hash token.
3385
3386 const MCExpr *ShiftAmount;
3387 SMLoc E = Parser.getTok().getLoc();
3388 if (getParser().ParseExpression(ShiftAmount)) {
3389 Error(E, "malformed rotate expression");
3390 return MatchOperand_ParseFail;
3391 }
3392 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3393 if (!CE) {
3394 Error(E, "rotate amount must be an immediate");
3395 return MatchOperand_ParseFail;
3396 }
3397
3398 int64_t Val = CE->getValue();
3399 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3400 // normally, zero is represented in asm by omitting the rotate operand
3401 // entirely.
3402 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3403 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3404 return MatchOperand_ParseFail;
3405 }
3406
3407 E = Parser.getTok().getLoc();
3408 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3409
3410 return MatchOperand_Success;
3411}
3412
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003413ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3414parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3415 SMLoc S = Parser.getTok().getLoc();
3416 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003417 if (Parser.getTok().isNot(AsmToken::Hash) &&
3418 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003419 Error(Parser.getTok().getLoc(), "'#' expected");
3420 return MatchOperand_ParseFail;
3421 }
3422 Parser.Lex(); // Eat hash token.
3423
3424 const MCExpr *LSBExpr;
3425 SMLoc E = Parser.getTok().getLoc();
3426 if (getParser().ParseExpression(LSBExpr)) {
3427 Error(E, "malformed immediate expression");
3428 return MatchOperand_ParseFail;
3429 }
3430 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3431 if (!CE) {
3432 Error(E, "'lsb' operand must be an immediate");
3433 return MatchOperand_ParseFail;
3434 }
3435
3436 int64_t LSB = CE->getValue();
3437 // The LSB must be in the range [0,31]
3438 if (LSB < 0 || LSB > 31) {
3439 Error(E, "'lsb' operand must be in the range [0,31]");
3440 return MatchOperand_ParseFail;
3441 }
3442 E = Parser.getTok().getLoc();
3443
3444 // Expect another immediate operand.
3445 if (Parser.getTok().isNot(AsmToken::Comma)) {
3446 Error(Parser.getTok().getLoc(), "too few operands");
3447 return MatchOperand_ParseFail;
3448 }
3449 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003450 if (Parser.getTok().isNot(AsmToken::Hash) &&
3451 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003452 Error(Parser.getTok().getLoc(), "'#' expected");
3453 return MatchOperand_ParseFail;
3454 }
3455 Parser.Lex(); // Eat hash token.
3456
3457 const MCExpr *WidthExpr;
3458 if (getParser().ParseExpression(WidthExpr)) {
3459 Error(E, "malformed immediate expression");
3460 return MatchOperand_ParseFail;
3461 }
3462 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3463 if (!CE) {
3464 Error(E, "'width' operand must be an immediate");
3465 return MatchOperand_ParseFail;
3466 }
3467
3468 int64_t Width = CE->getValue();
3469 // The LSB must be in the range [1,32-lsb]
3470 if (Width < 1 || Width > 32 - LSB) {
3471 Error(E, "'width' operand must be in the range [1,32-lsb]");
3472 return MatchOperand_ParseFail;
3473 }
3474 E = Parser.getTok().getLoc();
3475
3476 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3477
3478 return MatchOperand_Success;
3479}
3480
Jim Grosbach7ce05792011-08-03 23:50:40 +00003481ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3482parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3483 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003484 // postidx_reg := '+' register {, shift}
3485 // | '-' register {, shift}
3486 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003487
3488 // This method must return MatchOperand_NoMatch without consuming any tokens
3489 // in the case where there is no match, as other alternatives take other
3490 // parse methods.
3491 AsmToken Tok = Parser.getTok();
3492 SMLoc S = Tok.getLoc();
3493 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003494 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003495 int Reg = -1;
3496 if (Tok.is(AsmToken::Plus)) {
3497 Parser.Lex(); // Eat the '+' token.
3498 haveEaten = true;
3499 } else if (Tok.is(AsmToken::Minus)) {
3500 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003501 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003502 haveEaten = true;
3503 }
3504 if (Parser.getTok().is(AsmToken::Identifier))
3505 Reg = tryParseRegister();
3506 if (Reg == -1) {
3507 if (!haveEaten)
3508 return MatchOperand_NoMatch;
3509 Error(Parser.getTok().getLoc(), "register expected");
3510 return MatchOperand_ParseFail;
3511 }
3512 SMLoc E = Parser.getTok().getLoc();
3513
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003514 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3515 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003516 if (Parser.getTok().is(AsmToken::Comma)) {
3517 Parser.Lex(); // Eat the ','.
3518 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3519 return MatchOperand_ParseFail;
3520 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003521
3522 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3523 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003524
3525 return MatchOperand_Success;
3526}
3527
Jim Grosbach251bf252011-08-10 21:56:18 +00003528ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3529parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3530 // Check for a post-index addressing register operand. Specifically:
3531 // am3offset := '+' register
3532 // | '-' register
3533 // | register
3534 // | # imm
3535 // | # + imm
3536 // | # - imm
3537
3538 // This method must return MatchOperand_NoMatch without consuming any tokens
3539 // in the case where there is no match, as other alternatives take other
3540 // parse methods.
3541 AsmToken Tok = Parser.getTok();
3542 SMLoc S = Tok.getLoc();
3543
3544 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003545 if (Parser.getTok().is(AsmToken::Hash) ||
3546 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003547 Parser.Lex(); // Eat the '#'.
3548 // Explicitly look for a '-', as we need to encode negative zero
3549 // differently.
3550 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3551 const MCExpr *Offset;
3552 if (getParser().ParseExpression(Offset))
3553 return MatchOperand_ParseFail;
3554 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3555 if (!CE) {
3556 Error(S, "constant expression expected");
3557 return MatchOperand_ParseFail;
3558 }
3559 SMLoc E = Tok.getLoc();
3560 // Negative zero is encoded as the flag value INT32_MIN.
3561 int32_t Val = CE->getValue();
3562 if (isNegative && Val == 0)
3563 Val = INT32_MIN;
3564
3565 Operands.push_back(
3566 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3567
3568 return MatchOperand_Success;
3569 }
3570
3571
3572 bool haveEaten = false;
3573 bool isAdd = true;
3574 int Reg = -1;
3575 if (Tok.is(AsmToken::Plus)) {
3576 Parser.Lex(); // Eat the '+' token.
3577 haveEaten = true;
3578 } else if (Tok.is(AsmToken::Minus)) {
3579 Parser.Lex(); // Eat the '-' token.
3580 isAdd = false;
3581 haveEaten = true;
3582 }
3583 if (Parser.getTok().is(AsmToken::Identifier))
3584 Reg = tryParseRegister();
3585 if (Reg == -1) {
3586 if (!haveEaten)
3587 return MatchOperand_NoMatch;
3588 Error(Parser.getTok().getLoc(), "register expected");
3589 return MatchOperand_ParseFail;
3590 }
3591 SMLoc E = Parser.getTok().getLoc();
3592
3593 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3594 0, S, E));
3595
3596 return MatchOperand_Success;
3597}
3598
Jim Grosbacha77295d2011-09-08 22:07:06 +00003599/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3600/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3601/// when they refer multiple MIOperands inside a single one.
3602bool ARMAsmParser::
3603cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3604 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3605 // Rt, Rt2
3606 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3607 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3608 // Create a writeback register dummy placeholder.
3609 Inst.addOperand(MCOperand::CreateReg(0));
3610 // addr
3611 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3612 // pred
3613 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3614 return true;
3615}
3616
3617/// cvtT2StrdPre - Convert parsed operands to MCInst.
3618/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3619/// when they refer multiple MIOperands inside a single one.
3620bool ARMAsmParser::
3621cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3622 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3623 // Create a writeback register dummy placeholder.
3624 Inst.addOperand(MCOperand::CreateReg(0));
3625 // Rt, Rt2
3626 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3627 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3628 // addr
3629 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3630 // pred
3631 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3632 return true;
3633}
3634
Jim Grosbacheeec0252011-09-08 00:39:19 +00003635/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3636/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3637/// when they refer multiple MIOperands inside a single one.
3638bool ARMAsmParser::
3639cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3640 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3641 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3642
3643 // Create a writeback register dummy placeholder.
3644 Inst.addOperand(MCOperand::CreateImm(0));
3645
3646 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3647 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3648 return true;
3649}
3650
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003651/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3652/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3653/// when they refer multiple MIOperands inside a single one.
3654bool ARMAsmParser::
3655cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3656 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3657 // Create a writeback register dummy placeholder.
3658 Inst.addOperand(MCOperand::CreateImm(0));
3659 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3660 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3661 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3662 return true;
3663}
3664
Jim Grosbach1355cf12011-07-26 17:10:22 +00003665/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003666/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3667/// when they refer multiple MIOperands inside a single one.
3668bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003669cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003670 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3671 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3672
3673 // Create a writeback register dummy placeholder.
3674 Inst.addOperand(MCOperand::CreateImm(0));
3675
Jim Grosbach7ce05792011-08-03 23:50:40 +00003676 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003677 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3678 return true;
3679}
3680
Owen Anderson9ab0f252011-08-26 20:43:14 +00003681/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3682/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3683/// when they refer multiple MIOperands inside a single one.
3684bool ARMAsmParser::
3685cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3686 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3687 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3688
3689 // Create a writeback register dummy placeholder.
3690 Inst.addOperand(MCOperand::CreateImm(0));
3691
3692 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3693 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3694 return true;
3695}
3696
3697
Jim Grosbach548340c2011-08-11 19:22:40 +00003698/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3699/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3700/// when they refer multiple MIOperands inside a single one.
3701bool ARMAsmParser::
3702cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3703 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3704 // Create a writeback register dummy placeholder.
3705 Inst.addOperand(MCOperand::CreateImm(0));
3706 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3707 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3708 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3709 return true;
3710}
3711
Jim Grosbach1355cf12011-07-26 17:10:22 +00003712/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003713/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3714/// when they refer multiple MIOperands inside a single one.
3715bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003716cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003717 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3718 // Create a writeback register dummy placeholder.
3719 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003720 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3721 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3722 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003723 return true;
3724}
3725
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003726/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3727/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3728/// when they refer multiple MIOperands inside a single one.
3729bool ARMAsmParser::
3730cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3731 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3732 // Create a writeback register dummy placeholder.
3733 Inst.addOperand(MCOperand::CreateImm(0));
3734 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3735 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3736 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3737 return true;
3738}
3739
Jim Grosbach7ce05792011-08-03 23:50:40 +00003740/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3741/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3742/// when they refer multiple MIOperands inside a single one.
3743bool ARMAsmParser::
3744cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3745 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3746 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003747 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003748 // Create a writeback register dummy placeholder.
3749 Inst.addOperand(MCOperand::CreateImm(0));
3750 // addr
3751 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3752 // offset
3753 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3754 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003755 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3756 return true;
3757}
3758
Jim Grosbach7ce05792011-08-03 23:50:40 +00003759/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003760/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3761/// when they refer multiple MIOperands inside a single one.
3762bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003763cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3764 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3765 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003766 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003767 // Create a writeback register dummy placeholder.
3768 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003769 // addr
3770 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3771 // offset
3772 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3773 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003774 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3775 return true;
3776}
3777
Jim Grosbach7ce05792011-08-03 23:50:40 +00003778/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003779/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3780/// when they refer multiple MIOperands inside a single one.
3781bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003782cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3783 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003784 // Create a writeback register dummy placeholder.
3785 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003786 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003787 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003788 // addr
3789 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3790 // offset
3791 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3792 // pred
3793 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3794 return true;
3795}
3796
3797/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3798/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3799/// when they refer multiple MIOperands inside a single one.
3800bool ARMAsmParser::
3801cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3803 // Create a writeback register dummy placeholder.
3804 Inst.addOperand(MCOperand::CreateImm(0));
3805 // Rt
3806 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3807 // addr
3808 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3809 // offset
3810 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3811 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003812 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3813 return true;
3814}
3815
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003816/// cvtLdrdPre - Convert parsed operands to MCInst.
3817/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3818/// when they refer multiple MIOperands inside a single one.
3819bool ARMAsmParser::
3820cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3821 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3822 // Rt, Rt2
3823 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3824 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3825 // Create a writeback register dummy placeholder.
3826 Inst.addOperand(MCOperand::CreateImm(0));
3827 // addr
3828 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3829 // pred
3830 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3831 return true;
3832}
3833
Jim Grosbach14605d12011-08-11 20:28:23 +00003834/// cvtStrdPre - Convert parsed operands to MCInst.
3835/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3836/// when they refer multiple MIOperands inside a single one.
3837bool ARMAsmParser::
3838cvtStrdPre(MCInst &Inst, unsigned Opcode,
3839 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3840 // Create a writeback register dummy placeholder.
3841 Inst.addOperand(MCOperand::CreateImm(0));
3842 // Rt, Rt2
3843 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3844 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3845 // addr
3846 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3847 // pred
3848 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3849 return true;
3850}
3851
Jim Grosbach623a4542011-08-10 22:42:16 +00003852/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3853/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3854/// when they refer multiple MIOperands inside a single one.
3855bool ARMAsmParser::
3856cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3857 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3858 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3859 // Create a writeback register dummy placeholder.
3860 Inst.addOperand(MCOperand::CreateImm(0));
3861 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3862 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3863 return true;
3864}
3865
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003866/// cvtThumbMultiple- Convert parsed operands to MCInst.
3867/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3868/// when they refer multiple MIOperands inside a single one.
3869bool ARMAsmParser::
3870cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3871 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3872 // The second source operand must be the same register as the destination
3873 // operand.
3874 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003875 (((ARMOperand*)Operands[3])->getReg() !=
3876 ((ARMOperand*)Operands[5])->getReg()) &&
3877 (((ARMOperand*)Operands[3])->getReg() !=
3878 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003879 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003880 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003881 return false;
3882 }
3883 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3884 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003885 // If we have a three-operand form, make sure to set Rn to be the operand
3886 // that isn't the same as Rd.
3887 unsigned RegOp = 4;
3888 if (Operands.size() == 6 &&
3889 ((ARMOperand*)Operands[4])->getReg() ==
3890 ((ARMOperand*)Operands[3])->getReg())
3891 RegOp = 5;
3892 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3893 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003894 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3895
3896 return true;
3897}
Jim Grosbach623a4542011-08-10 22:42:16 +00003898
Jim Grosbach12431322011-10-24 22:16:58 +00003899bool ARMAsmParser::
3900cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3901 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3902 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003903 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003904 // Create a writeback register dummy placeholder.
3905 Inst.addOperand(MCOperand::CreateImm(0));
3906 // Vn
3907 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3908 // pred
3909 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3910 return true;
3911}
3912
3913bool ARMAsmParser::
3914cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3915 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3916 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003917 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003918 // Create a writeback register dummy placeholder.
3919 Inst.addOperand(MCOperand::CreateImm(0));
3920 // Vn
3921 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3922 // Vm
3923 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3924 // pred
3925 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3926 return true;
3927}
3928
Jim Grosbach4334e032011-10-31 21:50:31 +00003929bool ARMAsmParser::
3930cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3931 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3932 // Create a writeback register dummy placeholder.
3933 Inst.addOperand(MCOperand::CreateImm(0));
3934 // Vn
3935 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3936 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003937 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003938 // pred
3939 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3940 return true;
3941}
3942
3943bool ARMAsmParser::
3944cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3945 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3946 // Create a writeback register dummy placeholder.
3947 Inst.addOperand(MCOperand::CreateImm(0));
3948 // Vn
3949 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3950 // Vm
3951 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3952 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003953 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003954 // pred
3955 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3956 return true;
3957}
3958
Bill Wendlinge7176102010-11-06 22:36:58 +00003959/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003960/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003961bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003962parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003963 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003964 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003965 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003966 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003967 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003968
Sean Callanan18b83232010-01-19 21:44:56 +00003969 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003970 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003971 if (BaseRegNum == -1)
3972 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003973
Daniel Dunbar05710932011-01-18 05:34:17 +00003974 // The next token must either be a comma or a closing bracket.
3975 const AsmToken &Tok = Parser.getTok();
3976 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003977 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003978
Jim Grosbach7ce05792011-08-03 23:50:40 +00003979 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003980 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003981 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003982
Jim Grosbach7ce05792011-08-03 23:50:40 +00003983 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003984 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003985
Jim Grosbachfb12f352011-09-19 18:42:21 +00003986 // If there's a pre-indexing writeback marker, '!', just add it as a token
3987 // operand. It's rather odd, but syntactically valid.
3988 if (Parser.getTok().is(AsmToken::Exclaim)) {
3989 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3990 Parser.Lex(); // Eat the '!'.
3991 }
3992
Jim Grosbach7ce05792011-08-03 23:50:40 +00003993 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003994 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003995
Jim Grosbach7ce05792011-08-03 23:50:40 +00003996 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3997 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003998
Jim Grosbach57dcb852011-10-11 17:29:55 +00003999 // If we have a ':', it's an alignment specifier.
4000 if (Parser.getTok().is(AsmToken::Colon)) {
4001 Parser.Lex(); // Eat the ':'.
4002 E = Parser.getTok().getLoc();
4003
4004 const MCExpr *Expr;
4005 if (getParser().ParseExpression(Expr))
4006 return true;
4007
4008 // The expression has to be a constant. Memory references with relocations
4009 // don't come through here, as they use the <label> forms of the relevant
4010 // instructions.
4011 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4012 if (!CE)
4013 return Error (E, "constant expression expected");
4014
4015 unsigned Align = 0;
4016 switch (CE->getValue()) {
4017 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004018 return Error(E,
4019 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4020 case 16: Align = 2; break;
4021 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004022 case 64: Align = 8; break;
4023 case 128: Align = 16; break;
4024 case 256: Align = 32; break;
4025 }
4026
4027 // Now we should have the closing ']'
4028 E = Parser.getTok().getLoc();
4029 if (Parser.getTok().isNot(AsmToken::RBrac))
4030 return Error(E, "']' expected");
4031 Parser.Lex(); // Eat right bracket token.
4032
4033 // Don't worry about range checking the value here. That's handled by
4034 // the is*() predicates.
4035 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4036 ARM_AM::no_shift, 0, Align,
4037 false, S, E));
4038
4039 // If there's a pre-indexing writeback marker, '!', just add it as a token
4040 // operand.
4041 if (Parser.getTok().is(AsmToken::Exclaim)) {
4042 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4043 Parser.Lex(); // Eat the '!'.
4044 }
4045
4046 return false;
4047 }
4048
4049 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004050 // offset. Be friendly and also accept a plain integer (without a leading
4051 // hash) for gas compatibility.
4052 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004053 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004054 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004055 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004056 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004057 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004058
Owen Anderson0da10cf2011-08-29 19:36:44 +00004059 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004060 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004061 if (getParser().ParseExpression(Offset))
4062 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004063
4064 // The expression has to be a constant. Memory references with relocations
4065 // don't come through here, as they use the <label> forms of the relevant
4066 // instructions.
4067 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4068 if (!CE)
4069 return Error (E, "constant expression expected");
4070
Owen Anderson0da10cf2011-08-29 19:36:44 +00004071 // If the constant was #-0, represent it as INT32_MIN.
4072 int32_t Val = CE->getValue();
4073 if (isNegative && Val == 0)
4074 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4075
Jim Grosbach7ce05792011-08-03 23:50:40 +00004076 // Now we should have the closing ']'
4077 E = Parser.getTok().getLoc();
4078 if (Parser.getTok().isNot(AsmToken::RBrac))
4079 return Error(E, "']' expected");
4080 Parser.Lex(); // Eat right bracket token.
4081
4082 // Don't worry about range checking the value here. That's handled by
4083 // the is*() predicates.
4084 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004085 ARM_AM::no_shift, 0, 0,
4086 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004087
4088 // If there's a pre-indexing writeback marker, '!', just add it as a token
4089 // operand.
4090 if (Parser.getTok().is(AsmToken::Exclaim)) {
4091 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4092 Parser.Lex(); // Eat the '!'.
4093 }
4094
4095 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004096 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004097
4098 // The register offset is optionally preceded by a '+' or '-'
4099 bool isNegative = false;
4100 if (Parser.getTok().is(AsmToken::Minus)) {
4101 isNegative = true;
4102 Parser.Lex(); // Eat the '-'.
4103 } else if (Parser.getTok().is(AsmToken::Plus)) {
4104 // Nothing to do.
4105 Parser.Lex(); // Eat the '+'.
4106 }
4107
4108 E = Parser.getTok().getLoc();
4109 int OffsetRegNum = tryParseRegister();
4110 if (OffsetRegNum == -1)
4111 return Error(E, "register expected");
4112
4113 // If there's a shift operator, handle it.
4114 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004115 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004116 if (Parser.getTok().is(AsmToken::Comma)) {
4117 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004118 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004119 return true;
4120 }
4121
4122 // Now we should have the closing ']'
4123 E = Parser.getTok().getLoc();
4124 if (Parser.getTok().isNot(AsmToken::RBrac))
4125 return Error(E, "']' expected");
4126 Parser.Lex(); // Eat right bracket token.
4127
4128 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004129 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004130 S, E));
4131
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004132 // If there's a pre-indexing writeback marker, '!', just add it as a token
4133 // operand.
4134 if (Parser.getTok().is(AsmToken::Exclaim)) {
4135 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4136 Parser.Lex(); // Eat the '!'.
4137 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004138
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004139 return false;
4140}
4141
Jim Grosbach7ce05792011-08-03 23:50:40 +00004142/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004143/// ( lsl | lsr | asr | ror ) , # shift_amount
4144/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004145/// return true if it parses a shift otherwise it returns false.
4146bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4147 unsigned &Amount) {
4148 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004149 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004150 if (Tok.isNot(AsmToken::Identifier))
4151 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004152 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004153 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4154 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004155 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004156 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004157 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004158 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004159 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004160 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004161 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004162 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004163 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004164 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004165 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004166 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004167
Jim Grosbach7ce05792011-08-03 23:50:40 +00004168 // rrx stands alone.
4169 Amount = 0;
4170 if (St != ARM_AM::rrx) {
4171 Loc = Parser.getTok().getLoc();
4172 // A '#' and a shift amount.
4173 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004174 if (HashTok.isNot(AsmToken::Hash) &&
4175 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004176 return Error(HashTok.getLoc(), "'#' expected");
4177 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004178
Jim Grosbach7ce05792011-08-03 23:50:40 +00004179 const MCExpr *Expr;
4180 if (getParser().ParseExpression(Expr))
4181 return true;
4182 // Range check the immediate.
4183 // lsl, ror: 0 <= imm <= 31
4184 // lsr, asr: 0 <= imm <= 32
4185 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4186 if (!CE)
4187 return Error(Loc, "shift amount must be an immediate");
4188 int64_t Imm = CE->getValue();
4189 if (Imm < 0 ||
4190 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4191 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4192 return Error(Loc, "immediate shift value out of range");
4193 Amount = Imm;
4194 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004195
4196 return false;
4197}
4198
Jim Grosbach9d390362011-10-03 23:38:36 +00004199/// parseFPImm - A floating point immediate expression operand.
4200ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4201parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4202 SMLoc S = Parser.getTok().getLoc();
4203
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004204 if (Parser.getTok().isNot(AsmToken::Hash) &&
4205 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004206 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004207
4208 // Disambiguate the VMOV forms that can accept an FP immediate.
4209 // vmov.f32 <sreg>, #imm
4210 // vmov.f64 <dreg>, #imm
4211 // vmov.f32 <dreg>, #imm @ vector f32x2
4212 // vmov.f32 <qreg>, #imm @ vector f32x4
4213 //
4214 // There are also the NEON VMOV instructions which expect an
4215 // integer constant. Make sure we don't try to parse an FPImm
4216 // for these:
4217 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4218 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4219 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4220 TyOp->getToken() != ".f64"))
4221 return MatchOperand_NoMatch;
4222
Jim Grosbach9d390362011-10-03 23:38:36 +00004223 Parser.Lex(); // Eat the '#'.
4224
4225 // Handle negation, as that still comes through as a separate token.
4226 bool isNegative = false;
4227 if (Parser.getTok().is(AsmToken::Minus)) {
4228 isNegative = true;
4229 Parser.Lex();
4230 }
4231 const AsmToken &Tok = Parser.getTok();
4232 if (Tok.is(AsmToken::Real)) {
4233 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4234 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4235 // If we had a '-' in front, toggle the sign bit.
4236 IntVal ^= (uint64_t)isNegative << 63;
4237 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4238 Parser.Lex(); // Eat the token.
4239 if (Val == -1) {
4240 TokError("floating point value out of range");
4241 return MatchOperand_ParseFail;
4242 }
4243 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4244 return MatchOperand_Success;
4245 }
4246 if (Tok.is(AsmToken::Integer)) {
4247 int64_t Val = Tok.getIntVal();
4248 Parser.Lex(); // Eat the token.
4249 if (Val > 255 || Val < 0) {
4250 TokError("encoded floating point value out of range");
4251 return MatchOperand_ParseFail;
4252 }
4253 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4254 return MatchOperand_Success;
4255 }
4256
4257 TokError("invalid floating point immediate");
4258 return MatchOperand_ParseFail;
4259}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004260/// Parse a arm instruction operand. For now this parses the operand regardless
4261/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004262bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004263 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004264 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004265
4266 // Check if the current operand has a custom associated parser, if so, try to
4267 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004268 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4269 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004270 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004271 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4272 // there was a match, but an error occurred, in which case, just return that
4273 // the operand parsing failed.
4274 if (ResTy == MatchOperand_ParseFail)
4275 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004276
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004277 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004278 default:
4279 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004280 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004281 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004282 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004283 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004284 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004285 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004286 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004287 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004288 else if (Res == -1) // irrecoverable error
4289 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004290 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4291 S = Parser.getTok().getLoc();
4292 Parser.Lex();
4293 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4294 return false;
4295 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004296
4297 // Fall though for the Identifier case that is not a register or a
4298 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004299 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004300 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004301 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004302 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004303 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004304 // This was not a register so parse other operands that start with an
4305 // identifier (like labels) as expressions and create them as immediates.
4306 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004307 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004308 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004309 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004310 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004311 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4312 return false;
4313 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004314 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004315 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004316 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004317 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004318 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004319 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004320 // #42 -> immediate.
4321 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004322 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004323 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004324 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004325 const MCExpr *ImmVal;
4326 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004327 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004328 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004329 if (CE) {
4330 int32_t Val = CE->getValue();
4331 if (isNegative && Val == 0)
4332 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004333 }
Sean Callanan76264762010-04-02 22:27:05 +00004334 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004335 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4336 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004337 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004338 case AsmToken::Colon: {
4339 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004340 // FIXME: Check it's an expression prefix,
4341 // e.g. (FOO - :lower16:BAR) isn't legal.
4342 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004343 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004344 return true;
4345
Evan Cheng75972122011-01-13 07:58:56 +00004346 const MCExpr *SubExprVal;
4347 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004348 return true;
4349
Evan Cheng75972122011-01-13 07:58:56 +00004350 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4351 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004352 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004353 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004354 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004355 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004356 }
4357}
4358
Jim Grosbach1355cf12011-07-26 17:10:22 +00004359// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004360// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004361bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004362 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004363
4364 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004365 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004366 Parser.Lex(); // Eat ':'
4367
4368 if (getLexer().isNot(AsmToken::Identifier)) {
4369 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4370 return true;
4371 }
4372
4373 StringRef IDVal = Parser.getTok().getIdentifier();
4374 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004375 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004376 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004377 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004378 } else {
4379 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4380 return true;
4381 }
4382 Parser.Lex();
4383
4384 if (getLexer().isNot(AsmToken::Colon)) {
4385 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4386 return true;
4387 }
4388 Parser.Lex(); // Eat the last ':'
4389 return false;
4390}
4391
Daniel Dunbar352e1482011-01-11 15:59:50 +00004392/// \brief Given a mnemonic, split out possible predication code and carry
4393/// setting letters to form a canonical mnemonic and flags.
4394//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004395// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004396// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004397StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004398 unsigned &PredicationCode,
4399 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004400 unsigned &ProcessorIMod,
4401 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004402 PredicationCode = ARMCC::AL;
4403 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004404 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004405
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004406 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004407 //
4408 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004409 if ((Mnemonic == "movs" && isThumb()) ||
4410 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4411 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4412 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4413 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4414 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4415 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004416 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4417 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004418 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004419
Jim Grosbach3f00e312011-07-11 17:09:57 +00004420 // First, split out any predication code. Ignore mnemonics we know aren't
4421 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004422 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004423 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004424 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004425 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004426 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4427 .Case("eq", ARMCC::EQ)
4428 .Case("ne", ARMCC::NE)
4429 .Case("hs", ARMCC::HS)
4430 .Case("cs", ARMCC::HS)
4431 .Case("lo", ARMCC::LO)
4432 .Case("cc", ARMCC::LO)
4433 .Case("mi", ARMCC::MI)
4434 .Case("pl", ARMCC::PL)
4435 .Case("vs", ARMCC::VS)
4436 .Case("vc", ARMCC::VC)
4437 .Case("hi", ARMCC::HI)
4438 .Case("ls", ARMCC::LS)
4439 .Case("ge", ARMCC::GE)
4440 .Case("lt", ARMCC::LT)
4441 .Case("gt", ARMCC::GT)
4442 .Case("le", ARMCC::LE)
4443 .Case("al", ARMCC::AL)
4444 .Default(~0U);
4445 if (CC != ~0U) {
4446 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4447 PredicationCode = CC;
4448 }
Bill Wendling52925b62010-10-29 23:50:21 +00004449 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004450
Daniel Dunbar352e1482011-01-11 15:59:50 +00004451 // Next, determine if we have a carry setting bit. We explicitly ignore all
4452 // the instructions we know end in 's'.
4453 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004454 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004455 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4456 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4457 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004458 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004459 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004460 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004461 Mnemonic == "fmuls" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004462 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004463 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4464 CarrySetting = true;
4465 }
4466
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004467 // The "cps" instruction can have a interrupt mode operand which is glued into
4468 // the mnemonic. Check if this is the case, split it and parse the imod op
4469 if (Mnemonic.startswith("cps")) {
4470 // Split out any imod code.
4471 unsigned IMod =
4472 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4473 .Case("ie", ARM_PROC::IE)
4474 .Case("id", ARM_PROC::ID)
4475 .Default(~0U);
4476 if (IMod != ~0U) {
4477 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4478 ProcessorIMod = IMod;
4479 }
4480 }
4481
Jim Grosbach89df9962011-08-26 21:43:41 +00004482 // The "it" instruction has the condition mask on the end of the mnemonic.
4483 if (Mnemonic.startswith("it")) {
4484 ITMask = Mnemonic.slice(2, Mnemonic.size());
4485 Mnemonic = Mnemonic.slice(0, 2);
4486 }
4487
Daniel Dunbar352e1482011-01-11 15:59:50 +00004488 return Mnemonic;
4489}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004490
4491/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4492/// inclusion of carry set or predication code operands.
4493//
4494// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004495void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004496getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004497 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004498 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4499 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004500 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004501 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004502 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004503 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004504 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004505 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004506 Mnemonic == "mla" || Mnemonic == "smlal" ||
4507 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004508 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004509 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004510 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004511
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004512 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4513 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4514 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4515 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004516 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4517 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004518 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004519 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4520 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4521 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004522 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4523 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004524 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004525 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004526 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004527 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004528
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004529 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004530 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004531 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004532 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004533 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004534}
4535
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004536bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4537 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004538 // FIXME: This is all horribly hacky. We really need a better way to deal
4539 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004540
4541 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4542 // another does not. Specifically, the MOVW instruction does not. So we
4543 // special case it here and remove the defaulted (non-setting) cc_out
4544 // operand if that's the instruction we're trying to match.
4545 //
4546 // We do this as post-processing of the explicit operands rather than just
4547 // conditionally adding the cc_out in the first place because we need
4548 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004549 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004550 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4551 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4552 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4553 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004554
4555 // Register-register 'add' for thumb does not have a cc_out operand
4556 // when there are only two register operands.
4557 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4558 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4559 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4560 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4561 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004562 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004563 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4564 // have to check the immediate range here since Thumb2 has a variant
4565 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004566 if (((isThumb() && Mnemonic == "add") ||
4567 (isThumbTwo() && Mnemonic == "sub")) &&
4568 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004569 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4570 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4571 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004572 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4573 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4574 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004575 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004576 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4577 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004578 // selecting via the generic "add" mnemonic, so to know that we
4579 // should remove the cc_out operand, we have to explicitly check that
4580 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004581 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4582 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004583 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4584 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4585 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4586 // Nest conditions rather than one big 'if' statement for readability.
4587 //
4588 // If either register is a high reg, it's either one of the SP
4589 // variants (handled above) or a 32-bit encoding, so we just
4590 // check against T3.
4591 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4592 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4593 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4594 return false;
4595 // If both registers are low, we're in an IT block, and the immediate is
4596 // in range, we should use encoding T1 instead, which has a cc_out.
4597 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004598 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004599 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4600 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4601 return false;
4602
4603 // Otherwise, we use encoding T4, which does not have a cc_out
4604 // operand.
4605 return true;
4606 }
4607
Jim Grosbach64944f42011-09-14 21:00:40 +00004608 // The thumb2 multiply instruction doesn't have a CCOut register, so
4609 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4610 // use the 16-bit encoding or not.
4611 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4612 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4613 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4614 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4615 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4616 // If the registers aren't low regs, the destination reg isn't the
4617 // same as one of the source regs, or the cc_out operand is zero
4618 // outside of an IT block, we have to use the 32-bit encoding, so
4619 // remove the cc_out operand.
4620 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4621 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004622 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004623 !inITBlock() ||
4624 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4625 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4626 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4627 static_cast<ARMOperand*>(Operands[4])->getReg())))
4628 return true;
4629
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004630 // Also check the 'mul' syntax variant that doesn't specify an explicit
4631 // destination register.
4632 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4633 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4634 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4635 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4636 // If the registers aren't low regs or the cc_out operand is zero
4637 // outside of an IT block, we have to use the 32-bit encoding, so
4638 // remove the cc_out operand.
4639 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4640 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4641 !inITBlock()))
4642 return true;
4643
Jim Grosbach64944f42011-09-14 21:00:40 +00004644
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004645
Jim Grosbachf69c8042011-08-24 21:42:27 +00004646 // Register-register 'add/sub' for thumb does not have a cc_out operand
4647 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4648 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4649 // right, this will result in better diagnostics (which operand is off)
4650 // anyway.
4651 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4652 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004653 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4654 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4655 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4656 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004657
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004658 return false;
4659}
4660
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004661static bool isDataTypeToken(StringRef Tok) {
4662 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4663 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4664 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4665 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4666 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4667 Tok == ".f" || Tok == ".d";
4668}
4669
4670// FIXME: This bit should probably be handled via an explicit match class
4671// in the .td files that matches the suffix instead of having it be
4672// a literal string token the way it is now.
4673static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4674 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4675}
4676
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004677static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004678/// Parse an arm instruction mnemonic followed by its operands.
4679bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4680 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004681 // Apply mnemonic aliases before doing anything else, as the destination
4682 // mnemnonic may include suffices and we want to handle them normally.
4683 // The generic tblgen'erated code does this later, at the start of
4684 // MatchInstructionImpl(), but that's too late for aliases that include
4685 // any sort of suffix.
4686 unsigned AvailableFeatures = getAvailableFeatures();
4687 applyMnemonicAliases(Name, AvailableFeatures);
4688
Jim Grosbacha39cda72011-12-14 02:16:11 +00004689 // First check for the ARM-specific .req directive.
4690 if (Parser.getTok().is(AsmToken::Identifier) &&
4691 Parser.getTok().getIdentifier() == ".req") {
4692 parseDirectiveReq(Name, NameLoc);
4693 // We always return 'error' for this, as we're done with this
4694 // statement and don't need to match the 'instruction."
4695 return true;
4696 }
4697
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004698 // Create the leading tokens for the mnemonic, split by '.' characters.
4699 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004700 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004701
Daniel Dunbar352e1482011-01-11 15:59:50 +00004702 // Split out the predication code and carry setting flag from the mnemonic.
4703 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004704 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004705 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004706 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004707 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004708 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004709
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004710 // In Thumb1, only the branch (B) instruction can be predicated.
4711 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4712 Parser.EatToEndOfStatement();
4713 return Error(NameLoc, "conditional execution not supported in Thumb1");
4714 }
4715
Jim Grosbachffa32252011-07-19 19:13:28 +00004716 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4717
Jim Grosbach89df9962011-08-26 21:43:41 +00004718 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4719 // is the mask as it will be for the IT encoding if the conditional
4720 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4721 // where the conditional bit0 is zero, the instruction post-processing
4722 // will adjust the mask accordingly.
4723 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004724 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4725 if (ITMask.size() > 3) {
4726 Parser.EatToEndOfStatement();
4727 return Error(Loc, "too many conditions on IT instruction");
4728 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004729 unsigned Mask = 8;
4730 for (unsigned i = ITMask.size(); i != 0; --i) {
4731 char pos = ITMask[i - 1];
4732 if (pos != 't' && pos != 'e') {
4733 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004734 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004735 }
4736 Mask >>= 1;
4737 if (ITMask[i - 1] == 't')
4738 Mask |= 8;
4739 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004740 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004741 }
4742
Jim Grosbachffa32252011-07-19 19:13:28 +00004743 // FIXME: This is all a pretty gross hack. We should automatically handle
4744 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004745
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004746 // Next, add the CCOut and ConditionCode operands, if needed.
4747 //
4748 // For mnemonics which can ever incorporate a carry setting bit or predication
4749 // code, our matching model involves us always generating CCOut and
4750 // ConditionCode operands to match the mnemonic "as written" and then we let
4751 // the matcher deal with finding the right instruction or generating an
4752 // appropriate error.
4753 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004754 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004755
Jim Grosbach33c16a22011-07-14 22:04:21 +00004756 // If we had a carry-set on an instruction that can't do that, issue an
4757 // error.
4758 if (!CanAcceptCarrySet && CarrySetting) {
4759 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004760 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004761 "' can not set flags, but 's' suffix specified");
4762 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004763 // If we had a predication code on an instruction that can't do that, issue an
4764 // error.
4765 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4766 Parser.EatToEndOfStatement();
4767 return Error(NameLoc, "instruction '" + Mnemonic +
4768 "' is not predicable, but condition code specified");
4769 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004770
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004771 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004772 if (CanAcceptCarrySet) {
4773 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004774 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004775 Loc));
4776 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004777
4778 // Add the predication code operand, if necessary.
4779 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004780 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4781 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004782 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004783 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004784 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004785
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004786 // Add the processor imod operand, if necessary.
4787 if (ProcessorIMod) {
4788 Operands.push_back(ARMOperand::CreateImm(
4789 MCConstantExpr::Create(ProcessorIMod, getContext()),
4790 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004791 }
4792
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004793 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004794 while (Next != StringRef::npos) {
4795 Start = Next;
4796 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004797 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004798
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004799 // Some NEON instructions have an optional datatype suffix that is
4800 // completely ignored. Check for that.
4801 if (isDataTypeToken(ExtraToken) &&
4802 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4803 continue;
4804
Jim Grosbach81d2e392011-09-07 16:06:04 +00004805 if (ExtraToken != ".n") {
4806 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4807 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4808 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004809 }
4810
4811 // Read the remaining operands.
4812 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004813 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004814 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004815 Parser.EatToEndOfStatement();
4816 return true;
4817 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004818
4819 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004820 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004821
4822 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004823 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004824 Parser.EatToEndOfStatement();
4825 return true;
4826 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004827 }
4828 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004829
Chris Lattnercbf8a982010-09-11 16:18:25 +00004830 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004831 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004832 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004833 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004834 }
Bill Wendling146018f2010-11-06 21:42:12 +00004835
Chris Lattner34e53142010-09-08 05:10:46 +00004836 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004837
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004838 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4839 // do and don't have a cc_out optional-def operand. With some spot-checks
4840 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004841 // parse and adjust accordingly before actually matching. We shouldn't ever
4842 // try to remove a cc_out operand that was explicitly set on the the
4843 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4844 // table driven matcher doesn't fit well with the ARM instruction set.
4845 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004846 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4847 Operands.erase(Operands.begin() + 1);
4848 delete Op;
4849 }
4850
Jim Grosbachcf121c32011-07-28 21:57:55 +00004851 // ARM mode 'blx' need special handling, as the register operand version
4852 // is predicable, but the label operand version is not. So, we can't rely
4853 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004854 // a k_CondCode operand in the list. If we're trying to match the label
4855 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004856 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4857 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4858 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4859 Operands.erase(Operands.begin() + 1);
4860 delete Op;
4861 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004862
4863 // The vector-compare-to-zero instructions have a literal token "#0" at
4864 // the end that comes to here as an immediate operand. Convert it to a
4865 // token to play nicely with the matcher.
4866 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4867 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4868 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4869 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4870 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4871 if (CE && CE->getValue() == 0) {
4872 Operands.erase(Operands.begin() + 5);
4873 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4874 delete Op;
4875 }
4876 }
Jim Grosbach68259142011-10-03 22:30:24 +00004877 // VCMP{E} does the same thing, but with a different operand count.
4878 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4879 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4880 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4881 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4882 if (CE && CE->getValue() == 0) {
4883 Operands.erase(Operands.begin() + 4);
4884 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4885 delete Op;
4886 }
4887 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004888 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004889 // end. Convert it to a token here. Take care not to convert those
4890 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004891 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004892 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4893 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004894 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4895 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4896 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004897 if (CE && CE->getValue() == 0 &&
4898 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004899 // The cc_out operand matches the IT block.
4900 ((inITBlock() != CarrySetting) &&
4901 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004902 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004903 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004904 Operands.erase(Operands.begin() + 5);
4905 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4906 delete Op;
4907 }
4908 }
4909
Chris Lattner98986712010-01-14 22:21:20 +00004910 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004911}
4912
Jim Grosbach189610f2011-07-26 18:25:39 +00004913// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004914
4915// return 'true' if register list contains non-low GPR registers,
4916// 'false' otherwise. If Reg is in the register list or is HiReg, set
4917// 'containsReg' to true.
4918static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4919 unsigned HiReg, bool &containsReg) {
4920 containsReg = false;
4921 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4922 unsigned OpReg = Inst.getOperand(i).getReg();
4923 if (OpReg == Reg)
4924 containsReg = true;
4925 // Anything other than a low register isn't legal here.
4926 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4927 return true;
4928 }
4929 return false;
4930}
4931
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004932// Check if the specified regisgter is in the register list of the inst,
4933// starting at the indicated operand number.
4934static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4935 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4936 unsigned OpReg = Inst.getOperand(i).getReg();
4937 if (OpReg == Reg)
4938 return true;
4939 }
4940 return false;
4941}
4942
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004943// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4944// the ARMInsts array) instead. Getting that here requires awkward
4945// API changes, though. Better way?
4946namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004947extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004948}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004949static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004950 return ARMInsts[Opcode];
4951}
4952
Jim Grosbach189610f2011-07-26 18:25:39 +00004953// FIXME: We would really like to be able to tablegen'erate this.
4954bool ARMAsmParser::
4955validateInstruction(MCInst &Inst,
4956 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004957 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004958 SMLoc Loc = Operands[0]->getStartLoc();
4959 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004960 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4961 // being allowed in IT blocks, but not being predicable. It just always
4962 // executes.
4963 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004964 unsigned bit = 1;
4965 if (ITState.FirstCond)
4966 ITState.FirstCond = false;
4967 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004968 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004969 // The instruction must be predicable.
4970 if (!MCID.isPredicable())
4971 return Error(Loc, "instructions in IT block must be predicable");
4972 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4973 unsigned ITCond = bit ? ITState.Cond :
4974 ARMCC::getOppositeCondition(ITState.Cond);
4975 if (Cond != ITCond) {
4976 // Find the condition code Operand to get its SMLoc information.
4977 SMLoc CondLoc;
4978 for (unsigned i = 1; i < Operands.size(); ++i)
4979 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4980 CondLoc = Operands[i]->getStartLoc();
4981 return Error(CondLoc, "incorrect condition in IT block; got '" +
4982 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4983 "', but expected '" +
4984 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4985 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004986 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004987 } else if (isThumbTwo() && MCID.isPredicable() &&
4988 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004989 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4990 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004991 return Error(Loc, "predicated instructions must be in IT block");
4992
Jim Grosbach189610f2011-07-26 18:25:39 +00004993 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004994 case ARM::LDRD:
4995 case ARM::LDRD_PRE:
4996 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004997 case ARM::LDREXD: {
4998 // Rt2 must be Rt + 1.
4999 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5000 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5001 if (Rt2 != Rt + 1)
5002 return Error(Operands[3]->getStartLoc(),
5003 "destination operands must be sequential");
5004 return false;
5005 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005006 case ARM::STRD: {
5007 // Rt2 must be Rt + 1.
5008 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5009 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5010 if (Rt2 != Rt + 1)
5011 return Error(Operands[3]->getStartLoc(),
5012 "source operands must be sequential");
5013 return false;
5014 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005015 case ARM::STRD_PRE:
5016 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005017 case ARM::STREXD: {
5018 // Rt2 must be Rt + 1.
5019 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5020 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5021 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005022 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005023 "source operands must be sequential");
5024 return false;
5025 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005026 case ARM::SBFX:
5027 case ARM::UBFX: {
5028 // width must be in range [1, 32-lsb]
5029 unsigned lsb = Inst.getOperand(2).getImm();
5030 unsigned widthm1 = Inst.getOperand(3).getImm();
5031 if (widthm1 >= 32 - lsb)
5032 return Error(Operands[5]->getStartLoc(),
5033 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005034 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005035 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005036 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005037 // If we're parsing Thumb2, the .w variant is available and handles
5038 // most cases that are normally illegal for a Thumb1 LDM
5039 // instruction. We'll make the transformation in processInstruction()
5040 // if necessary.
5041 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005042 // Thumb LDM instructions are writeback iff the base register is not
5043 // in the register list.
5044 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005045 bool hasWritebackToken =
5046 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5047 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005048 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005049 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005050 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5051 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005052 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005053 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005054 return Error(Operands[2]->getStartLoc(),
5055 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005056 // If we should not have writeback, there must not be a '!'. This is
5057 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005058 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005059 return Error(Operands[3]->getStartLoc(),
5060 "writeback operator '!' not allowed when base register "
5061 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005062
5063 break;
5064 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005065 case ARM::t2LDMIA_UPD: {
5066 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5067 return Error(Operands[4]->getStartLoc(),
5068 "writeback operator '!' not allowed when base register "
5069 "in register list");
5070 break;
5071 }
Jim Grosbach54026372011-11-10 23:17:11 +00005072 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5073 // so only issue a diagnostic for thumb1. The instructions will be
5074 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005075 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005076 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005077 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5078 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005079 return Error(Operands[2]->getStartLoc(),
5080 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005081 break;
5082 }
5083 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005084 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005085 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5086 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005087 return Error(Operands[2]->getStartLoc(),
5088 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005089 break;
5090 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005091 case ARM::tSTMIA_UPD: {
5092 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005093 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005094 return Error(Operands[4]->getStartLoc(),
5095 "registers must be in range r0-r7");
5096 break;
5097 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005098 }
5099
5100 return false;
5101}
5102
Jim Grosbach84defb52011-12-02 22:34:51 +00005103static unsigned getRealVSTLNOpcode(unsigned Opc) {
5104 switch(Opc) {
5105 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005106 // VST1LN
5107 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5108 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5109 case ARM::VST1LNdWB_fixed_Asm_U8:
5110 return ARM::VST1LNd8_UPD;
5111 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5112 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5113 case ARM::VST1LNdWB_fixed_Asm_U16:
5114 return ARM::VST1LNd16_UPD;
5115 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5116 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5117 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
5118 return ARM::VST1LNd32_UPD;
5119 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5120 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5121 case ARM::VST1LNdWB_register_Asm_U8:
5122 return ARM::VST1LNd8_UPD;
5123 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5124 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5125 case ARM::VST1LNdWB_register_Asm_U16:
5126 return ARM::VST1LNd16_UPD;
5127 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5128 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5129 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
5130 return ARM::VST1LNd32_UPD;
5131 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5132 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5133 case ARM::VST1LNdAsm_U8:
5134 return ARM::VST1LNd8;
5135 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5136 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5137 case ARM::VST1LNdAsm_U16:
5138 return ARM::VST1LNd16;
5139 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5140 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5141 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
5142 return ARM::VST1LNd32;
5143
5144 // VST2LN
5145 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5146 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5147 case ARM::VST2LNdWB_fixed_Asm_U8:
5148 return ARM::VST2LNd8_UPD;
5149 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5150 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5151 case ARM::VST2LNdWB_fixed_Asm_U16:
5152 return ARM::VST2LNd16_UPD;
5153 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5154 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5155 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5156 return ARM::VST2LNd32_UPD;
5157 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5158 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5159 case ARM::VST2LNdWB_register_Asm_U8:
5160 return ARM::VST2LNd8_UPD;
5161 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5162 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5163 case ARM::VST2LNdWB_register_Asm_U16:
5164 return ARM::VST2LNd16_UPD;
5165 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5166 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5167 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5168 return ARM::VST2LNd32_UPD;
5169 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5170 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5171 case ARM::VST2LNdAsm_U8:
5172 return ARM::VST2LNd8;
5173 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5174 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5175 case ARM::VST2LNdAsm_U16:
5176 return ARM::VST2LNd16;
5177 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5178 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5179 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
5180 return ARM::VST2LNd32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005181 }
5182}
5183
5184static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005185 switch(Opc) {
5186 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005187 // VLD1LN
5188 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5189 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5190 case ARM::VLD1LNdWB_fixed_Asm_U8:
5191 return ARM::VLD1LNd8_UPD;
5192 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5193 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5194 case ARM::VLD1LNdWB_fixed_Asm_U16:
5195 return ARM::VLD1LNd16_UPD;
5196 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5197 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5198 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
5199 return ARM::VLD1LNd32_UPD;
5200 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5201 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5202 case ARM::VLD1LNdWB_register_Asm_U8:
5203 return ARM::VLD1LNd8_UPD;
5204 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5205 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5206 case ARM::VLD1LNdWB_register_Asm_U16:
5207 return ARM::VLD1LNd16_UPD;
5208 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5209 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5210 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
5211 return ARM::VLD1LNd32_UPD;
5212 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5213 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5214 case ARM::VLD1LNdAsm_U8:
5215 return ARM::VLD1LNd8;
5216 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5217 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5218 case ARM::VLD1LNdAsm_U16:
5219 return ARM::VLD1LNd16;
5220 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5221 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5222 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
5223 return ARM::VLD1LNd32;
5224
5225 // VLD2LN
5226 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5227 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5228 case ARM::VLD2LNdWB_fixed_Asm_U8:
5229 return ARM::VLD2LNd8_UPD;
5230 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5231 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5232 case ARM::VLD2LNdWB_fixed_Asm_U16:
5233 return ARM::VLD2LNd16_UPD;
5234 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5235 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5236 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
5237 return ARM::VLD2LNd32_UPD;
5238 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5239 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5240 case ARM::VLD2LNdWB_register_Asm_U8:
5241 return ARM::VLD2LNd8_UPD;
5242 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5243 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5244 case ARM::VLD2LNdWB_register_Asm_U16:
5245 return ARM::VLD2LNd16_UPD;
5246 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5247 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5248 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
5249 return ARM::VLD2LNd32_UPD;
5250 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5251 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5252 case ARM::VLD2LNdAsm_U8:
5253 return ARM::VLD2LNd8;
5254 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5255 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5256 case ARM::VLD2LNdAsm_U16:
5257 return ARM::VLD2LNd16;
5258 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5259 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5260 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
5261 return ARM::VLD2LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005262 }
5263}
5264
Jim Grosbach83ec8772011-11-10 23:42:14 +00005265bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005266processInstruction(MCInst &Inst,
5267 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5268 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005269 // Handle NEON VST complex aliases.
5270 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5271 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5272 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5273 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5274 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5275 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5276 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5277 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005278 MCInst TmpInst;
5279 // Shuffle the operands around so the lane index operand is in the
5280 // right place.
5281 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5282 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5283 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5284 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5285 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5286 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5287 TmpInst.addOperand(Inst.getOperand(1)); // lane
5288 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5289 TmpInst.addOperand(Inst.getOperand(6));
5290 Inst = TmpInst;
5291 return true;
5292 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005293
5294 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5295 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5296 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
5297 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5298 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
5299 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5300 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5301 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32: {
5302 MCInst TmpInst;
5303 // Shuffle the operands around so the lane index operand is in the
5304 // right place.
5305 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5306 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5307 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5308 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5309 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5310 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5311 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5312 TmpInst.addOperand(Inst.getOperand(1)); // lane
5313 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5314 TmpInst.addOperand(Inst.getOperand(6));
5315 Inst = TmpInst;
5316 return true;
5317 }
5318 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5319 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5320 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5321 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5322 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5323 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5324 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5325 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005326 MCInst TmpInst;
5327 // Shuffle the operands around so the lane index operand is in the
5328 // right place.
5329 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5330 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5331 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5332 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5333 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5334 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5335 TmpInst.addOperand(Inst.getOperand(1)); // lane
5336 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5337 TmpInst.addOperand(Inst.getOperand(5));
5338 Inst = TmpInst;
5339 return true;
5340 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005341
5342 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5343 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5344 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
5345 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5346 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
5347 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5348 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5349 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32: {
5350 MCInst TmpInst;
5351 // Shuffle the operands around so the lane index operand is in the
5352 // right place.
5353 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5354 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5355 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5356 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5357 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5358 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5359 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5360 TmpInst.addOperand(Inst.getOperand(1)); // lane
5361 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5362 TmpInst.addOperand(Inst.getOperand(5));
5363 Inst = TmpInst;
5364 return true;
5365 }
5366 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5367 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5368 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5369 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5370 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005371 case ARM::VST1LNdAsm_U32: {
5372 MCInst TmpInst;
5373 // Shuffle the operands around so the lane index operand is in the
5374 // right place.
5375 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5376 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5377 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5378 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5379 TmpInst.addOperand(Inst.getOperand(1)); // lane
5380 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5381 TmpInst.addOperand(Inst.getOperand(5));
5382 Inst = TmpInst;
5383 return true;
5384 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005385
5386 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5387 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
5388 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5389 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5390 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
5391 case ARM::VST2LNdAsm_U32: {
5392 MCInst TmpInst;
5393 // Shuffle the operands around so the lane index operand is in the
5394 // right place.
5395 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5396 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5397 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5398 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5399 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5400 TmpInst.addOperand(Inst.getOperand(1)); // lane
5401 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5402 TmpInst.addOperand(Inst.getOperand(5));
5403 Inst = TmpInst;
5404 return true;
5405 }
5406 // Handle NEON VLD complex aliases.
5407 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5408 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5409 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5410 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5411 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5412 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5413 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5414 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005415 MCInst TmpInst;
5416 // Shuffle the operands around so the lane index operand is in the
5417 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005418 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005419 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5420 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5421 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5422 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5423 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5424 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5425 TmpInst.addOperand(Inst.getOperand(1)); // lane
5426 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5427 TmpInst.addOperand(Inst.getOperand(6));
5428 Inst = TmpInst;
5429 return true;
5430 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005431
5432 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5433 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5434 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
5435 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5436 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
5437 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5438 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5439 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32: {
5440 MCInst TmpInst;
5441 // Shuffle the operands around so the lane index operand is in the
5442 // right place.
5443 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5444 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5445 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5446 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5447 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5448 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5449 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5450 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5451 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5452 TmpInst.addOperand(Inst.getOperand(1)); // lane
5453 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5454 TmpInst.addOperand(Inst.getOperand(6));
5455 Inst = TmpInst;
5456 return true;
5457 }
5458
5459 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5460 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5461 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5462 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5463 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5464 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5465 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5466 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005467 MCInst TmpInst;
5468 // Shuffle the operands around so the lane index operand is in the
5469 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005470 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005471 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5472 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5473 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5474 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5475 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5476 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5477 TmpInst.addOperand(Inst.getOperand(1)); // lane
5478 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5479 TmpInst.addOperand(Inst.getOperand(5));
5480 Inst = TmpInst;
5481 return true;
5482 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005483
5484 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5485 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5486 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
5487 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5488 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
5489 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5490 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5491 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32: {
5492 MCInst TmpInst;
5493 // Shuffle the operands around so the lane index operand is in the
5494 // right place.
5495 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5496 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5497 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5498 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5499 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5500 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5501 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5502 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5503 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5504 TmpInst.addOperand(Inst.getOperand(1)); // lane
5505 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5506 TmpInst.addOperand(Inst.getOperand(5));
5507 Inst = TmpInst;
5508 return true;
5509 }
5510
5511 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5512 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
5513 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5514 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5515 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005516 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005517 MCInst TmpInst;
5518 // Shuffle the operands around so the lane index operand is in the
5519 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005520 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005521 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5522 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5523 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5524 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5525 TmpInst.addOperand(Inst.getOperand(1)); // lane
5526 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5527 TmpInst.addOperand(Inst.getOperand(5));
5528 Inst = TmpInst;
5529 return true;
5530 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005531
5532 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5533 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
5534 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5535 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5536 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
5537 case ARM::VLD2LNdAsm_U32: {
5538 MCInst TmpInst;
5539 // Shuffle the operands around so the lane index operand is in the
5540 // right place.
5541 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5542 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5543 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5544 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5545 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5546 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5547 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5548 TmpInst.addOperand(Inst.getOperand(1)); // lane
5549 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5550 TmpInst.addOperand(Inst.getOperand(5));
5551 Inst = TmpInst;
5552 return true;
5553 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005554 // Handle the Thumb2 mode MOV complex aliases.
5555 case ARM::t2MOVsi:
5556 case ARM::t2MOVSsi: {
5557 // Which instruction to expand to depends on the CCOut operand and
5558 // whether we're in an IT block if the register operands are low
5559 // registers.
5560 bool isNarrow = false;
5561 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5562 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5563 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5564 isNarrow = true;
5565 MCInst TmpInst;
5566 unsigned newOpc;
5567 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5568 default: llvm_unreachable("unexpected opcode!");
5569 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5570 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5571 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5572 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5573 }
5574 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5575 if (Ammount == 32) Ammount = 0;
5576 TmpInst.setOpcode(newOpc);
5577 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5578 if (isNarrow)
5579 TmpInst.addOperand(MCOperand::CreateReg(
5580 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5581 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5582 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5583 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5584 TmpInst.addOperand(Inst.getOperand(4));
5585 if (!isNarrow)
5586 TmpInst.addOperand(MCOperand::CreateReg(
5587 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5588 Inst = TmpInst;
5589 return true;
5590 }
5591 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005592 case ARM::ASRr:
5593 case ARM::LSRr:
5594 case ARM::LSLr:
5595 case ARM::RORr: {
5596 ARM_AM::ShiftOpc ShiftTy;
5597 switch(Inst.getOpcode()) {
5598 default: llvm_unreachable("unexpected opcode!");
5599 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5600 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5601 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5602 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5603 }
5604 // A shift by zero is a plain MOVr, not a MOVsi.
5605 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5606 MCInst TmpInst;
5607 TmpInst.setOpcode(ARM::MOVsr);
5608 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5609 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5610 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5611 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5612 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5613 TmpInst.addOperand(Inst.getOperand(4));
5614 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5615 Inst = TmpInst;
5616 return true;
5617 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005618 case ARM::ASRi:
5619 case ARM::LSRi:
5620 case ARM::LSLi:
5621 case ARM::RORi: {
5622 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005623 switch(Inst.getOpcode()) {
5624 default: llvm_unreachable("unexpected opcode!");
5625 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5626 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5627 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5628 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5629 }
5630 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005631 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005632 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5633 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005634 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005635 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005636 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5637 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005638 if (Opc == ARM::MOVsi)
5639 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005640 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5641 TmpInst.addOperand(Inst.getOperand(4));
5642 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5643 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005644 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005645 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005646 case ARM::RRXi: {
5647 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5648 MCInst TmpInst;
5649 TmpInst.setOpcode(ARM::MOVsi);
5650 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5651 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5652 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5653 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5654 TmpInst.addOperand(Inst.getOperand(3));
5655 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5656 Inst = TmpInst;
5657 return true;
5658 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005659 case ARM::t2LDMIA_UPD: {
5660 // If this is a load of a single register, then we should use
5661 // a post-indexed LDR instruction instead, per the ARM ARM.
5662 if (Inst.getNumOperands() != 5)
5663 return false;
5664 MCInst TmpInst;
5665 TmpInst.setOpcode(ARM::t2LDR_POST);
5666 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5667 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5668 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5669 TmpInst.addOperand(MCOperand::CreateImm(4));
5670 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5671 TmpInst.addOperand(Inst.getOperand(3));
5672 Inst = TmpInst;
5673 return true;
5674 }
5675 case ARM::t2STMDB_UPD: {
5676 // If this is a store of a single register, then we should use
5677 // a pre-indexed STR instruction instead, per the ARM ARM.
5678 if (Inst.getNumOperands() != 5)
5679 return false;
5680 MCInst TmpInst;
5681 TmpInst.setOpcode(ARM::t2STR_PRE);
5682 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5683 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5684 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5685 TmpInst.addOperand(MCOperand::CreateImm(-4));
5686 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5687 TmpInst.addOperand(Inst.getOperand(3));
5688 Inst = TmpInst;
5689 return true;
5690 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005691 case ARM::LDMIA_UPD:
5692 // If this is a load of a single register via a 'pop', then we should use
5693 // a post-indexed LDR instruction instead, per the ARM ARM.
5694 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5695 Inst.getNumOperands() == 5) {
5696 MCInst TmpInst;
5697 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5698 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5699 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5700 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5701 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5702 TmpInst.addOperand(MCOperand::CreateImm(4));
5703 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5704 TmpInst.addOperand(Inst.getOperand(3));
5705 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005706 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005707 }
5708 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005709 case ARM::STMDB_UPD:
5710 // If this is a store of a single register via a 'push', then we should use
5711 // a pre-indexed STR instruction instead, per the ARM ARM.
5712 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5713 Inst.getNumOperands() == 5) {
5714 MCInst TmpInst;
5715 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5716 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5717 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5718 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5719 TmpInst.addOperand(MCOperand::CreateImm(-4));
5720 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5721 TmpInst.addOperand(Inst.getOperand(3));
5722 Inst = TmpInst;
5723 }
5724 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005725 case ARM::t2ADDri12:
5726 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5727 // mnemonic was used (not "addw"), encoding T3 is preferred.
5728 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5729 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5730 break;
5731 Inst.setOpcode(ARM::t2ADDri);
5732 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5733 break;
5734 case ARM::t2SUBri12:
5735 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5736 // mnemonic was used (not "subw"), encoding T3 is preferred.
5737 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5738 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5739 break;
5740 Inst.setOpcode(ARM::t2SUBri);
5741 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5742 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005743 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005744 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5745 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5746 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5747 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005748 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005749 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005750 return true;
5751 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005752 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005753 case ARM::tSUBi8:
5754 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5755 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5756 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5757 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005758 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005759 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005760 return true;
5761 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005762 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005763 case ARM::t2ADDrr: {
5764 // If the destination and first source operand are the same, and
5765 // there's no setting of the flags, use encoding T2 instead of T3.
5766 // Note that this is only for ADD, not SUB. This mirrors the system
5767 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5768 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5769 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005770 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5771 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005772 break;
5773 MCInst TmpInst;
5774 TmpInst.setOpcode(ARM::tADDhirr);
5775 TmpInst.addOperand(Inst.getOperand(0));
5776 TmpInst.addOperand(Inst.getOperand(0));
5777 TmpInst.addOperand(Inst.getOperand(2));
5778 TmpInst.addOperand(Inst.getOperand(3));
5779 TmpInst.addOperand(Inst.getOperand(4));
5780 Inst = TmpInst;
5781 return true;
5782 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005783 case ARM::tB:
5784 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005785 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005786 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005787 return true;
5788 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005789 break;
5790 case ARM::t2B:
5791 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005792 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005793 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005794 return true;
5795 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005796 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005797 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005798 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005799 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005800 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005801 return true;
5802 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005803 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005804 case ARM::tBcc:
5805 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005806 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005807 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005808 return true;
5809 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005810 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005811 case ARM::tLDMIA: {
5812 // If the register list contains any high registers, or if the writeback
5813 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5814 // instead if we're in Thumb2. Otherwise, this should have generated
5815 // an error in validateInstruction().
5816 unsigned Rn = Inst.getOperand(0).getReg();
5817 bool hasWritebackToken =
5818 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5819 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5820 bool listContainsBase;
5821 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5822 (!listContainsBase && !hasWritebackToken) ||
5823 (listContainsBase && hasWritebackToken)) {
5824 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5825 assert (isThumbTwo());
5826 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5827 // If we're switching to the updating version, we need to insert
5828 // the writeback tied operand.
5829 if (hasWritebackToken)
5830 Inst.insert(Inst.begin(),
5831 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005832 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005833 }
5834 break;
5835 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005836 case ARM::tSTMIA_UPD: {
5837 // If the register list contains any high registers, we need to use
5838 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5839 // should have generated an error in validateInstruction().
5840 unsigned Rn = Inst.getOperand(0).getReg();
5841 bool listContainsBase;
5842 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5843 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5844 assert (isThumbTwo());
5845 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005846 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005847 }
5848 break;
5849 }
Jim Grosbach54026372011-11-10 23:17:11 +00005850 case ARM::tPOP: {
5851 bool listContainsBase;
5852 // If the register list contains any high registers, we need to use
5853 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5854 // should have generated an error in validateInstruction().
5855 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005856 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005857 assert (isThumbTwo());
5858 Inst.setOpcode(ARM::t2LDMIA_UPD);
5859 // Add the base register and writeback operands.
5860 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5861 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005862 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005863 }
5864 case ARM::tPUSH: {
5865 bool listContainsBase;
5866 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005867 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005868 assert (isThumbTwo());
5869 Inst.setOpcode(ARM::t2STMDB_UPD);
5870 // Add the base register and writeback operands.
5871 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5872 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005873 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005874 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005875 case ARM::t2MOVi: {
5876 // If we can use the 16-bit encoding and the user didn't explicitly
5877 // request the 32-bit variant, transform it here.
5878 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5879 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005880 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5881 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5882 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005883 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5884 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5885 // The operands aren't in the same order for tMOVi8...
5886 MCInst TmpInst;
5887 TmpInst.setOpcode(ARM::tMOVi8);
5888 TmpInst.addOperand(Inst.getOperand(0));
5889 TmpInst.addOperand(Inst.getOperand(4));
5890 TmpInst.addOperand(Inst.getOperand(1));
5891 TmpInst.addOperand(Inst.getOperand(2));
5892 TmpInst.addOperand(Inst.getOperand(3));
5893 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005894 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005895 }
5896 break;
5897 }
5898 case ARM::t2MOVr: {
5899 // If we can use the 16-bit encoding and the user didn't explicitly
5900 // request the 32-bit variant, transform it here.
5901 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5902 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5903 Inst.getOperand(2).getImm() == ARMCC::AL &&
5904 Inst.getOperand(4).getReg() == ARM::CPSR &&
5905 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5906 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5907 // The operands aren't the same for tMOV[S]r... (no cc_out)
5908 MCInst TmpInst;
5909 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5910 TmpInst.addOperand(Inst.getOperand(0));
5911 TmpInst.addOperand(Inst.getOperand(1));
5912 TmpInst.addOperand(Inst.getOperand(2));
5913 TmpInst.addOperand(Inst.getOperand(3));
5914 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005915 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005916 }
5917 break;
5918 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005919 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005920 case ARM::t2SXTB:
5921 case ARM::t2UXTH:
5922 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005923 // If we can use the 16-bit encoding and the user didn't explicitly
5924 // request the 32-bit variant, transform it here.
5925 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5926 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5927 Inst.getOperand(2).getImm() == 0 &&
5928 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5929 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005930 unsigned NewOpc;
5931 switch (Inst.getOpcode()) {
5932 default: llvm_unreachable("Illegal opcode!");
5933 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5934 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5935 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5936 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5937 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005938 // The operands aren't the same for thumb1 (no rotate operand).
5939 MCInst TmpInst;
5940 TmpInst.setOpcode(NewOpc);
5941 TmpInst.addOperand(Inst.getOperand(0));
5942 TmpInst.addOperand(Inst.getOperand(1));
5943 TmpInst.addOperand(Inst.getOperand(3));
5944 TmpInst.addOperand(Inst.getOperand(4));
5945 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005946 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005947 }
5948 break;
5949 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00005950 case ARM::MOVsi: {
5951 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
5952 if (SOpc == ARM_AM::rrx) return false;
5953 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
5954 // Shifting by zero is accepted as a vanilla 'MOVr'
5955 MCInst TmpInst;
5956 TmpInst.setOpcode(ARM::MOVr);
5957 TmpInst.addOperand(Inst.getOperand(0));
5958 TmpInst.addOperand(Inst.getOperand(1));
5959 TmpInst.addOperand(Inst.getOperand(3));
5960 TmpInst.addOperand(Inst.getOperand(4));
5961 TmpInst.addOperand(Inst.getOperand(5));
5962 Inst = TmpInst;
5963 return true;
5964 }
5965 return false;
5966 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005967 case ARM::t2IT: {
5968 // The mask bits for all but the first condition are represented as
5969 // the low bit of the condition code value implies 't'. We currently
5970 // always have 1 implies 't', so XOR toggle the bits if the low bit
5971 // of the condition code is zero. The encoding also expects the low
5972 // bit of the condition to be encoded as bit 4 of the mask operand,
5973 // so mask that in if needed
5974 MCOperand &MO = Inst.getOperand(1);
5975 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005976 unsigned OrigMask = Mask;
5977 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005978 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005979 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5980 for (unsigned i = 3; i != TZ; --i)
5981 Mask ^= 1 << i;
5982 } else
5983 Mask |= 0x10;
5984 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005985
5986 // Set up the IT block state according to the IT instruction we just
5987 // matched.
5988 assert(!inITBlock() && "nested IT blocks?!");
5989 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5990 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5991 ITState.CurPosition = 0;
5992 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005993 break;
5994 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005995 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005996 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005997}
5998
Jim Grosbach47a0d522011-08-16 20:45:50 +00005999unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6000 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6001 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006002 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006003 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006004 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6005 assert(MCID.hasOptionalDef() &&
6006 "optionally flag setting instruction missing optional def operand");
6007 assert(MCID.NumOperands == Inst.getNumOperands() &&
6008 "operand count mismatch!");
6009 // Find the optional-def operand (cc_out).
6010 unsigned OpNo;
6011 for (OpNo = 0;
6012 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6013 ++OpNo)
6014 ;
6015 // If we're parsing Thumb1, reject it completely.
6016 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6017 return Match_MnemonicFail;
6018 // If we're parsing Thumb2, which form is legal depends on whether we're
6019 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006020 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6021 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006022 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006023 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6024 inITBlock())
6025 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006026 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006027 // Some high-register supporting Thumb1 encodings only allow both registers
6028 // to be from r0-r7 when in Thumb2.
6029 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6030 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6031 isARMLowRegister(Inst.getOperand(2).getReg()))
6032 return Match_RequiresThumb2;
6033 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006034 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006035 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6036 isARMLowRegister(Inst.getOperand(1).getReg()))
6037 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006038 return Match_Success;
6039}
6040
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006041bool ARMAsmParser::
6042MatchAndEmitInstruction(SMLoc IDLoc,
6043 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6044 MCStreamer &Out) {
6045 MCInst Inst;
6046 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006047 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006048 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006049 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006050 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006051 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006052 // Context sensitive operand constraints aren't handled by the matcher,
6053 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006054 if (validateInstruction(Inst, Operands)) {
6055 // Still progress the IT block, otherwise one wrong condition causes
6056 // nasty cascading errors.
6057 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006058 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006059 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006060
Jim Grosbachf8fce712011-08-11 17:35:48 +00006061 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006062 // encoding is selected. Loop on it while changes happen so the
6063 // individual transformations can chain off each other. E.g.,
6064 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6065 while (processInstruction(Inst, Operands))
6066 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006067
Jim Grosbacha1109882011-09-02 23:22:08 +00006068 // Only move forward at the very end so that everything in validate
6069 // and process gets a consistent answer about whether we're in an IT
6070 // block.
6071 forwardITPosition();
6072
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006073 Out.EmitInstruction(Inst);
6074 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006075 case Match_MissingFeature:
6076 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6077 return true;
6078 case Match_InvalidOperand: {
6079 SMLoc ErrorLoc = IDLoc;
6080 if (ErrorInfo != ~0U) {
6081 if (ErrorInfo >= Operands.size())
6082 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006083
Chris Lattnere73d4f82010-10-28 21:41:58 +00006084 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6085 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6086 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006087
Chris Lattnere73d4f82010-10-28 21:41:58 +00006088 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006089 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006090 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006091 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006092 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006093 // The converter function will have already emited a diagnostic.
6094 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006095 case Match_RequiresNotITBlock:
6096 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006097 case Match_RequiresITBlock:
6098 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006099 case Match_RequiresV6:
6100 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6101 case Match_RequiresThumb2:
6102 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006103 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006104
Eric Christopherc223e2b2010-10-29 09:26:59 +00006105 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006106 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006107}
6108
Jim Grosbach1355cf12011-07-26 17:10:22 +00006109/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006110bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6111 StringRef IDVal = DirectiveID.getIdentifier();
6112 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006113 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006114 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006115 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006116 else if (IDVal == ".arm")
6117 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006118 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006119 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006120 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006121 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006122 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006123 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006124 else if (IDVal == ".unreq")
6125 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006126 else if (IDVal == ".arch")
6127 return parseDirectiveArch(DirectiveID.getLoc());
6128 else if (IDVal == ".eabi_attribute")
6129 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006130 return true;
6131}
6132
Jim Grosbach1355cf12011-07-26 17:10:22 +00006133/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006134/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006135bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6137 for (;;) {
6138 const MCExpr *Value;
6139 if (getParser().ParseExpression(Value))
6140 return true;
6141
Chris Lattneraaec2052010-01-19 19:46:13 +00006142 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006143
6144 if (getLexer().is(AsmToken::EndOfStatement))
6145 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006146
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006147 // FIXME: Improve diagnostic.
6148 if (getLexer().isNot(AsmToken::Comma))
6149 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006150 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006151 }
6152 }
6153
Sean Callananb9a25b72010-01-19 20:27:46 +00006154 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006155 return false;
6156}
6157
Jim Grosbach1355cf12011-07-26 17:10:22 +00006158/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006159/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006160bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006161 if (getLexer().isNot(AsmToken::EndOfStatement))
6162 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006163 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006164
Jim Grosbach9a70df92011-12-07 18:04:19 +00006165 if (!isThumb())
6166 SwitchMode();
6167 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6168 return false;
6169}
6170
6171/// parseDirectiveARM
6172/// ::= .arm
6173bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6174 if (getLexer().isNot(AsmToken::EndOfStatement))
6175 return Error(L, "unexpected token in directive");
6176 Parser.Lex();
6177
6178 if (isThumb())
6179 SwitchMode();
6180 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006181 return false;
6182}
6183
Jim Grosbach1355cf12011-07-26 17:10:22 +00006184/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006185/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006186bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006187 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6188 bool isMachO = MAI.hasSubsectionsViaSymbols();
6189 StringRef Name;
6190
6191 // Darwin asm has function name after .thumb_func direction
6192 // ELF doesn't
6193 if (isMachO) {
6194 const AsmToken &Tok = Parser.getTok();
6195 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6196 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00006197 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006198 Parser.Lex(); // Consume the identifier token.
6199 }
6200
Jim Grosbachd475f862011-11-10 20:48:53 +00006201 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006202 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006203 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006204
Rafael Espindola64695402011-05-16 16:17:21 +00006205 // FIXME: assuming function name will be the line following .thumb_func
6206 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006207 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006208 }
6209
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006210 // Mark symbol as a thumb symbol.
6211 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6212 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006213 return false;
6214}
6215
Jim Grosbach1355cf12011-07-26 17:10:22 +00006216/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006217/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006218bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006219 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006220 if (Tok.isNot(AsmToken::Identifier))
6221 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006222 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006223 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006224 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006225 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006226 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006227 else
6228 return Error(L, "unrecognized syntax mode in .syntax directive");
6229
6230 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006231 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006232 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006233
6234 // TODO tell the MC streamer the mode
6235 // getParser().getStreamer().Emit???();
6236 return false;
6237}
6238
Jim Grosbach1355cf12011-07-26 17:10:22 +00006239/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006240/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006241bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006242 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006243 if (Tok.isNot(AsmToken::Integer))
6244 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006245 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006246 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006247 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006248 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006249 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006250 else
6251 return Error(L, "invalid operand to .code directive");
6252
6253 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006254 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006255 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006256
Evan Cheng32869202011-07-08 22:36:29 +00006257 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006258 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006259 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006260 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006261 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006262 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006263 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006264 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006265 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006266
Kevin Enderby515d5092009-10-15 20:48:48 +00006267 return false;
6268}
6269
Jim Grosbacha39cda72011-12-14 02:16:11 +00006270/// parseDirectiveReq
6271/// ::= name .req registername
6272bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6273 Parser.Lex(); // Eat the '.req' token.
6274 unsigned Reg;
6275 SMLoc SRegLoc, ERegLoc;
6276 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6277 Parser.EatToEndOfStatement();
6278 return Error(SRegLoc, "register name expected");
6279 }
6280
6281 // Shouldn't be anything else.
6282 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6283 Parser.EatToEndOfStatement();
6284 return Error(Parser.getTok().getLoc(),
6285 "unexpected input in .req directive.");
6286 }
6287
6288 Parser.Lex(); // Consume the EndOfStatement
6289
6290 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6291 return Error(SRegLoc, "redefinition of '" + Name +
6292 "' does not match original.");
6293
6294 return false;
6295}
6296
6297/// parseDirectiveUneq
6298/// ::= .unreq registername
6299bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6300 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6301 Parser.EatToEndOfStatement();
6302 return Error(L, "unexpected input in .unreq directive.");
6303 }
6304 RegisterReqs.erase(Parser.getTok().getIdentifier());
6305 Parser.Lex(); // Eat the identifier.
6306 return false;
6307}
6308
Jason W Kimd7c9e082011-12-20 17:38:12 +00006309/// parseDirectiveArch
6310/// ::= .arch token
6311bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6312 return true;
6313}
6314
6315/// parseDirectiveEabiAttr
6316/// ::= .eabi_attribute int, int
6317bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6318 return true;
6319}
6320
Sean Callanan90b70972010-04-07 20:29:34 +00006321extern "C" void LLVMInitializeARMAsmLexer();
6322
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006323/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006324extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006325 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6326 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006327 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006328}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006329
Chris Lattner0692ee62010-09-06 19:11:01 +00006330#define GET_REGISTER_MATCHER
6331#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006332#include "ARMGenAsmMatcher.inc"