blob: 35251f02b8ef147995fd0c48f13c777b06dffa6a [file] [log] [blame]
Kevin Enderbyccab3172009-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 Cheng11424442011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chenga20cde32011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattner00646cf2010-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 Espindolae90c1cb2011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbachc6db8ce2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyccab3172009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng4d6c9d72011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng11424442011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng11424442011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach3d1eac82011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng2bb40352011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbar4a863e62010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach5c932b22011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramerdebe69f2011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng11424442011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000035
Kevin Enderbyccab3172009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000038namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000041
Jim Grosbach04945c42011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbachcd6f5e72011-11-30 01:09:44 +000043
Evan Cheng11424442011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbached16ec42011-08-29 22:24:09 +000048 struct {
49 ARMCC::CondCodes Cond; // Condition for IT block.
50 unsigned Mask:4; // Condition mask for instructions.
51 // Starting at first 1 (from lsb).
52 // '1' condition as indicated in IT.
53 // '0' inverse of condition (else).
54 // Count of instructions in IT block is
55 // 4 - trailingzeroes(mask)
56
57 bool FirstCond; // Explicit flag for when we're parsing the
58 // First instruction in the IT block. It's
59 // implied in the mask, so needs special
60 // handling.
61
62 unsigned CurPosition; // Current position in parsing of IT
63 // block. In range [0,3]. Initialized
64 // according to count of instructions in block.
65 // ~0U if no active IT block.
66 } ITState;
67 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000068 void forwardITPosition() {
69 if (!inITBlock()) return;
70 // Move to the next instruction in the IT block, if there is one. If not,
71 // mark the block as done.
72 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
73 if (++ITState.CurPosition == 5 - TZ)
74 ITState.CurPosition = ~0U; // Done with the IT block after this.
75 }
Jim Grosbached16ec42011-08-29 22:24:09 +000076
77
Kevin Enderbyccab3172009-09-15 00:27:25 +000078 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000079 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
80
81 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000082 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
83
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000084 int tryParseRegister();
85 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000086 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000087 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000088 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000089 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
90 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000091 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
92 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
94 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach7f882392011-12-07 18:04:19 +000095 bool parseDirectiveARM(SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000096 bool parseDirectiveThumbFunc(SMLoc L);
97 bool parseDirectiveCode(SMLoc L);
98 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000099
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000100 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000101 bool &CarrySetting, unsigned &ProcessorIMod,
102 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000103 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000104 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000105
Evan Cheng4d1ca962011-07-08 01:53:10 +0000106 bool isThumb() const {
107 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000108 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000109 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000110 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000112 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000113 bool isThumbTwo() const {
114 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
115 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000116 bool hasV6Ops() const {
117 return STI.getFeatureBits() & ARM::HasV6Ops;
118 }
James Molloy21efa7d2011-09-28 14:21:38 +0000119 bool hasV7Ops() const {
120 return STI.getFeatureBits() & ARM::HasV7Ops;
121 }
Evan Cheng284b4672011-07-08 22:36:29 +0000122 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000123 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
124 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000125 }
James Molloy21efa7d2011-09-28 14:21:38 +0000126 bool isMClass() const {
127 return STI.getFeatureBits() & ARM::FeatureMClass;
128 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000129
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000130 /// @name Auto-generated Match Functions
131 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000132
Chris Lattner3e4582a2010-09-06 19:11:01 +0000133#define GET_ASSEMBLER_HEADER
134#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000135
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000136 /// }
137
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000138 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000141 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000143 OperandMatchResultTy parseCoprocOptionOperand(
144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000147 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000149 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000151 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
152 StringRef Op, int Low, int High);
153 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "lsl", 0, 31);
155 }
156 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
157 return parsePKHImm(O, "asr", 1, 32);
158 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000159 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000160 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000161 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000162 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000163 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000164 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000165 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000166 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach04945c42011-12-02 00:35:16 +0000167 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000168
169 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000170 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
172 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000174 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000176 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000178 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000180 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000182 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000184 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000186 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000188 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
192 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
194 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000196 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000198 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000200 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000202 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000204 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000208 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
210 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000212
213 bool validateInstruction(MCInst &Inst,
214 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000215 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000216 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000217 bool shouldOmitCCOutOperand(StringRef Mnemonic,
218 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000219
Kevin Enderbyccab3172009-09-15 00:27:25 +0000220public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000221 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000222 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000223 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000224 Match_RequiresV6,
225 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000226 };
227
Evan Cheng91111d22011-07-09 05:47:46 +0000228 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000229 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000230 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000231
Evan Cheng4d1ca962011-07-08 01:53:10 +0000232 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000233 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000234
235 // Not in an ITBlock to start with.
236 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000237 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000238
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000239 // Implementation of the MCTargetAsmParser interface:
240 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
241 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000242 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000243 bool ParseDirective(AsmToken DirectiveID);
244
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000245 unsigned checkTargetMatchPredicate(MCInst &Inst);
246
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000247 bool MatchAndEmitInstruction(SMLoc IDLoc,
248 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
249 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000250};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000251} // end anonymous namespace
252
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000253namespace {
254
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000255/// ARMOperand - Instances of this class represent a parsed ARM machine
256/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000257class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000258 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000259 k_CondCode,
260 k_CCOut,
261 k_ITCondMask,
262 k_CoprocNum,
263 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000264 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000265 k_Immediate,
266 k_FPImmediate,
267 k_MemBarrierOpt,
268 k_Memory,
269 k_PostIndexRegister,
270 k_MSRMask,
271 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000272 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000273 k_Register,
274 k_RegisterList,
275 k_DPRRegisterList,
276 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000277 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000278 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000279 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000280 k_ShiftedRegister,
281 k_ShiftedImmediate,
282 k_ShifterImmediate,
283 k_RotateImmediate,
284 k_BitfieldDescriptor,
285 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000286 } Kind;
287
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000288 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000289 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000290
291 union {
292 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000293 ARMCC::CondCodes Val;
294 } CC;
295
296 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000297 unsigned Val;
298 } Cop;
299
300 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000301 unsigned Val;
302 } CoprocOption;
303
304 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000305 unsigned Mask:4;
306 } ITMask;
307
308 struct {
309 ARM_MB::MemBOpt Val;
310 } MBOpt;
311
312 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000313 ARM_PROC::IFlags Val;
314 } IFlags;
315
316 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000317 unsigned Val;
318 } MMask;
319
320 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000321 const char *Data;
322 unsigned Length;
323 } Tok;
324
325 struct {
326 unsigned RegNum;
327 } Reg;
328
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000329 // A vector register list is a sequential list of 1 to 4 registers.
330 struct {
331 unsigned RegNum;
332 unsigned Count;
Jim Grosbach04945c42011-12-02 00:35:16 +0000333 unsigned LaneIndex;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000334 } VectorList;
335
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000336 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000337 unsigned Val;
338 } VectorIndex;
339
340 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000341 const MCExpr *Val;
342 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000343
Jim Grosbache7fbce72011-10-03 23:38:36 +0000344 struct {
345 unsigned Val; // encoded 8-bit representation
346 } FPImm;
347
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000348 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000349 struct {
350 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000351 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
352 // was specified.
353 const MCConstantExpr *OffsetImm; // Offset immediate value
354 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
355 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000356 unsigned ShiftImm; // shift for OffsetReg.
357 unsigned Alignment; // 0 = no alignment specified
358 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000359 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000360 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000361
362 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000363 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000364 bool isAdd;
365 ARM_AM::ShiftOpc ShiftTy;
366 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000367 } PostIdxReg;
368
369 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000370 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000371 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000372 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000373 struct {
374 ARM_AM::ShiftOpc ShiftTy;
375 unsigned SrcReg;
376 unsigned ShiftReg;
377 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000378 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000379 struct {
380 ARM_AM::ShiftOpc ShiftTy;
381 unsigned SrcReg;
382 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000383 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000384 struct {
385 unsigned Imm;
386 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000387 struct {
388 unsigned LSB;
389 unsigned Width;
390 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000391 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000392
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000393 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
394public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000395 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
396 Kind = o.Kind;
397 StartLoc = o.StartLoc;
398 EndLoc = o.EndLoc;
399 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000400 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000401 CC = o.CC;
402 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000404 ITMask = o.ITMask;
405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000407 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000408 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000409 case k_CCOut:
410 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000411 Reg = o.Reg;
412 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000413 case k_RegisterList:
414 case k_DPRRegisterList:
415 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000416 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000417 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000418 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000419 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000420 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000421 VectorList = o.VectorList;
422 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000423 case k_CoprocNum:
424 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000425 Cop = o.Cop;
426 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000427 case k_CoprocOption:
428 CoprocOption = o.CoprocOption;
429 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000430 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000431 Imm = o.Imm;
432 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000433 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000434 FPImm = o.FPImm;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000441 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000450 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000453 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000456 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000459 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000471
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000476
Daniel Dunbard8042b72010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000495 }
496
Bill Wendlingbed94652010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000501 }
502
Kevin Enderbyf5079942009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000504 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbache7fbce72011-10-03 23:38:36 +0000508 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000509 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000510 return FPImm.Val;
511 }
512
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000513 unsigned getVectorIndex() const {
514 assert(Kind == k_VectorIndex && "Invalid access!");
515 return VectorIndex.Val;
516 }
517
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000518 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000519 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000520 return MBOpt.Val;
521 }
522
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000523 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000525 return IFlags.Val;
526 }
527
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000528 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000529 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000530 return MMask.Val;
531 }
532
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000533 bool isCoprocNum() const { return Kind == k_CoprocNum; }
534 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000535 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000536 bool isCondCode() const { return Kind == k_CondCode; }
537 bool isCCOut() const { return Kind == k_CCOut; }
538 bool isITMask() const { return Kind == k_ITCondMask; }
539 bool isITCondCode() const { return Kind == k_CondCode; }
540 bool isImm() const { return Kind == k_Immediate; }
541 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000542 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
549 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000550 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +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 >= 0 && Value <= 1020;
557 }
558 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-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 <= 508;
565 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000566 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +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 >= 0 && Value < 256;
573 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000574 bool isImm0_1() const {
575 if (Kind != k_Immediate)
576 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 < 2;
581 }
582 bool isImm0_3() 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 < 4;
589 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000590 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000592 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 < 8;
597 }
598 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach31756c22011-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 < 16;
605 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000606 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +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 < 32;
613 }
Jim Grosbach00326402011-12-08 01:30:04 +0000614 bool isImm0_63() const {
615 if (Kind != k_Immediate)
616 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 < 64;
621 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000622 bool isImm8() 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 == 8;
629 }
630 bool isImm16() 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 == 16;
637 }
638 bool isImm32() 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 == 32;
645 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000646 bool isShrImm8() 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 > 0 && Value <= 8;
653 }
654 bool isShrImm16() 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 <= 16;
661 }
662 bool isShrImm32() 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 <= 32;
669 }
670 bool isShrImm64() 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 <= 64;
677 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000678 bool isImm1_7() 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 < 8;
685 }
686 bool isImm1_15() 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 < 16;
693 }
694 bool isImm1_31() 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 < 32;
701 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000702 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000703 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000704 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 < 17;
709 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000710 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +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 < 33;
717 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000718 bool isImm0_32() const {
719 if (Kind != k_Immediate)
720 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 Grosbach975b6412011-07-13 20:10:10 +0000726 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000727 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000728 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 < 65536;
733 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000734 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 // If it's not a constant expression, it'll generate a fixup and be
739 // handled later.
740 if (!CE) return true;
741 int64_t Value = CE->getValue();
742 return Value >= 0 && Value < 65536;
743 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000744 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000745 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000746 return false;
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value <= 0xffffff;
751 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000752 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51: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 < 33;
759 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000760 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +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 < 32;
767 }
768 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-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 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000776 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return ARM_AM::getSOImmVal(Value) != -1;
783 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000784 bool isARMSOImmNot() const {
785 if (Kind != k_Immediate)
786 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 Grosbach30506252011-12-08 00:31:07 +0000792 bool isARMSOImmNeg() 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 Grosbacha6f7a1e2011-06-27 23:54:06 +0000800 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000801 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000802 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::getT2SOImmVal(Value) != -1;
807 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000808 bool isT2SOImmNot() const {
809 if (Kind != k_Immediate)
810 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 Grosbach30506252011-12-08 00:31:07 +0000816 bool isT2SOImmNeg() 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 Grosbach0a547702011-07-22 17:44:50 +0000824 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000825 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return Value == 1 || Value == 0;
831 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000832 bool isReg() const { return Kind == k_Register; }
833 bool isRegList() const { return Kind == k_RegisterList; }
834 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
835 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
836 bool isToken() const { return Kind == k_Token; }
837 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
838 bool isMemory() const { return Kind == k_Memory; }
839 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
840 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
841 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
842 bool isRotImm() const { return Kind == k_RotateImmediate; }
843 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
844 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000845 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000846 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000847 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000848 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000849 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000850 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000851 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000852 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
853 (alignOK || Memory.Alignment == 0);
854 }
855 bool isAlignedMemory() const {
856 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000857 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000858 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000860 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000861 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000862 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000865 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000866 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000867 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000868 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000869 return false;
870 // Immediate offset in range [-4095, 4095].
871 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
872 if (!CE) return false;
873 int64_t Val = CE->getValue();
874 return Val > -4096 && Val < 4096;
875 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000876 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000877 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000878 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000879 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000880 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000881 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000882 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000883 if (!Memory.OffsetImm) return true;
884 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000885 return Val > -256 && Val < 256;
886 }
887 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000888 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000889 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000890 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000891 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
892 // Immediate offset in range [-255, 255].
893 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
894 if (!CE) return false;
895 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000896 // Special case, #-0 is INT32_MIN.
897 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000898 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000899 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000900 // If we have an immediate that's not a constant, treat it as a label
901 // reference needing a fixup. If it is a constant, it's something else
902 // and we reject it.
903 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
904 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000905 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000906 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000907 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000908 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000909 if (!Memory.OffsetImm) return true;
910 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000911 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000912 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000913 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000914 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000915 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000916 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000917 return false;
918 return true;
919 }
920 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000921 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000922 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
923 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000924 return false;
925 return true;
926 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000927 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000929 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000930 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000931 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000932 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000933 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
934 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000935 return false;
936 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000937 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000938 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000939 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000940 return false;
941 return true;
942 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000943 bool isMemThumbRR() const {
944 // Thumb reg+reg addressing is simple. Just two registers, a base and
945 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000947 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000948 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000949 return isARMLowRegister(Memory.BaseRegNum) &&
950 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000951 }
952 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000953 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000954 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000955 return false;
956 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000957 if (!Memory.OffsetImm) return true;
958 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000959 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
960 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000961 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000962 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000963 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000964 return false;
965 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000966 if (!Memory.OffsetImm) return true;
967 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000968 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
969 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000970 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000971 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000972 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000973 return false;
974 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000975 if (!Memory.OffsetImm) return true;
976 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000977 return Val >= 0 && Val <= 31;
978 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000979 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000980 if (!isMemory() || Memory.OffsetRegNum != 0 ||
981 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000982 return false;
983 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000984 if (!Memory.OffsetImm) return true;
985 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000986 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000987 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000988 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000989 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000990 return false;
991 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000992 if (!Memory.OffsetImm) return true;
993 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000994 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
995 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000996 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000997 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000998 return false;
999 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001000 if (!Memory.OffsetImm) return true;
1001 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001002 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1003 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001004 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001005 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001006 return false;
1007 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001008 if (!Memory.OffsetImm) return true;
1009 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001010 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001011 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001012 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001013 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001014 return false;
1015 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001018 return Val >= 0 && Val < 256;
1019 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001020 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001021 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001022 return false;
1023 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001024 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001025 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001026 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001027 }
1028 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001029 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001030 return false;
1031 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001032 if (!Memory.OffsetImm) return true;
1033 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001034 return (Val >= 0 && Val < 4096);
1035 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001036 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001037 // If we have an immediate that's not a constant, treat it as a label
1038 // reference needing a fixup. If it is a constant, it's something else
1039 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001040 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001041 return true;
1042
Jim Grosbacha95ec992011-10-11 17:29:55 +00001043 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001044 return false;
1045 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001046 if (!Memory.OffsetImm) return true;
1047 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001048 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001049 }
1050 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001051 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +00001052 return false;
1053 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1054 if (!CE) return false;
1055 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001056 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001057 }
Jim Grosbach93981412011-10-11 21:55:36 +00001058 bool isPostIdxImm8s4() const {
1059 if (Kind != k_Immediate)
1060 return false;
1061 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1062 if (!CE) return false;
1063 int64_t Val = CE->getValue();
1064 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1065 (Val == INT32_MIN);
1066 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001067
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001068 bool isMSRMask() const { return Kind == k_MSRMask; }
1069 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001070
Jim Grosbach741cd732011-10-17 22:26:03 +00001071 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001072 bool isVecListOneD() const {
1073 if (Kind != k_VectorList) return false;
1074 return VectorList.Count == 1;
1075 }
1076
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001077 bool isVecListTwoD() const {
1078 if (Kind != k_VectorList) return false;
1079 return VectorList.Count == 2;
1080 }
1081
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001082 bool isVecListThreeD() const {
1083 if (Kind != k_VectorList) return false;
1084 return VectorList.Count == 3;
1085 }
1086
Jim Grosbach846bcff2011-10-21 20:35:01 +00001087 bool isVecListFourD() const {
1088 if (Kind != k_VectorList) return false;
1089 return VectorList.Count == 4;
1090 }
1091
Jim Grosbach118b38c2011-10-21 22:21:10 +00001092 bool isVecListTwoQ() const {
1093 if (Kind != k_VectorList) return false;
1094 //FIXME: We haven't taught the parser to handle by-two register lists
1095 // yet, so don't pretend to know one.
1096 return VectorList.Count == 2 && false;
1097 }
1098
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001099 bool isVecListOneDAllLanes() const {
1100 if (Kind != k_VectorListAllLanes) return false;
1101 return VectorList.Count == 1;
1102 }
1103
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001104 bool isVecListTwoDAllLanes() const {
1105 if (Kind != k_VectorListAllLanes) return false;
1106 return VectorList.Count == 2;
1107 }
1108
Jim Grosbach04945c42011-12-02 00:35:16 +00001109 bool isVecListOneDByteIndexed() const {
1110 if (Kind != k_VectorListIndexed) return false;
1111 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1112 }
1113
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001114 bool isVectorIndex8() const {
1115 if (Kind != k_VectorIndex) return false;
1116 return VectorIndex.Val < 8;
1117 }
1118 bool isVectorIndex16() const {
1119 if (Kind != k_VectorIndex) return false;
1120 return VectorIndex.Val < 4;
1121 }
1122 bool isVectorIndex32() const {
1123 if (Kind != k_VectorIndex) return false;
1124 return VectorIndex.Val < 2;
1125 }
1126
Jim Grosbach741cd732011-10-17 22:26:03 +00001127 bool isNEONi8splat() const {
1128 if (Kind != k_Immediate)
1129 return false;
1130 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1131 // Must be a constant.
1132 if (!CE) return false;
1133 int64_t Value = CE->getValue();
1134 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1135 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001136 return Value >= 0 && Value < 256;
1137 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001138
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001139 bool isNEONi16splat() const {
1140 if (Kind != k_Immediate)
1141 return false;
1142 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1143 // Must be a constant.
1144 if (!CE) return false;
1145 int64_t Value = CE->getValue();
1146 // i16 value in the range [0,255] or [0x0100, 0xff00]
1147 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1148 }
1149
Jim Grosbach8211c052011-10-18 00:22:00 +00001150 bool isNEONi32splat() const {
1151 if (Kind != k_Immediate)
1152 return false;
1153 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1154 // Must be a constant.
1155 if (!CE) return false;
1156 int64_t Value = CE->getValue();
1157 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1158 return (Value >= 0 && Value < 256) ||
1159 (Value >= 0x0100 && Value <= 0xff00) ||
1160 (Value >= 0x010000 && Value <= 0xff0000) ||
1161 (Value >= 0x01000000 && Value <= 0xff000000);
1162 }
1163
1164 bool isNEONi32vmov() const {
1165 if (Kind != k_Immediate)
1166 return false;
1167 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1168 // Must be a constant.
1169 if (!CE) return false;
1170 int64_t Value = CE->getValue();
1171 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1172 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1173 return (Value >= 0 && Value < 256) ||
1174 (Value >= 0x0100 && Value <= 0xff00) ||
1175 (Value >= 0x010000 && Value <= 0xff0000) ||
1176 (Value >= 0x01000000 && Value <= 0xff000000) ||
1177 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1178 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1179 }
1180
Jim Grosbache4454e02011-10-18 16:18:11 +00001181 bool isNEONi64splat() const {
1182 if (Kind != k_Immediate)
1183 return false;
1184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1185 // Must be a constant.
1186 if (!CE) return false;
1187 uint64_t Value = CE->getValue();
1188 // i64 value with each byte being either 0 or 0xff.
1189 for (unsigned i = 0; i < 8; ++i)
1190 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1191 return true;
1192 }
1193
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001194 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001195 // Add as immediates when possible. Null MCExpr = 0.
1196 if (Expr == 0)
1197 Inst.addOperand(MCOperand::CreateImm(0));
1198 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001199 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1200 else
1201 Inst.addOperand(MCOperand::CreateExpr(Expr));
1202 }
1203
Daniel Dunbard8042b72010-08-11 06:36:53 +00001204 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001205 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001206 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001207 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1208 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001209 }
1210
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001211 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 1 && "Invalid number of operands!");
1213 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1214 }
1215
Jim Grosbach48399582011-10-12 17:34:41 +00001216 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1219 }
1220
1221 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1224 }
1225
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001226 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1229 }
1230
1231 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1234 }
1235
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001236 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 Inst.addOperand(MCOperand::CreateReg(getReg()));
1239 }
1240
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001241 void addRegOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 Inst.addOperand(MCOperand::CreateReg(getReg()));
1244 }
1245
Jim Grosbachac798e12011-07-25 20:49:51 +00001246 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001247 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001248 assert(isRegShiftedReg() &&
1249 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001250 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1251 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001252 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001253 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001254 }
1255
Jim Grosbachac798e12011-07-25 20:49:51 +00001256 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001257 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001258 assert(isRegShiftedImm() &&
1259 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001260 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001261 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001262 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001263 }
1264
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001265 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001266 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001267 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1268 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001269 }
1270
Bill Wendling8d2aa032010-11-08 23:49:57 +00001271 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001272 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001273 const SmallVectorImpl<unsigned> &RegList = getRegList();
1274 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001275 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1276 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001277 }
1278
Bill Wendling9898ac92010-11-17 04:32:08 +00001279 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1280 addRegListOperands(Inst, N);
1281 }
1282
1283 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1284 addRegListOperands(Inst, N);
1285 }
1286
Jim Grosbach833b9d32011-07-27 20:15:40 +00001287 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1288 assert(N == 1 && "Invalid number of operands!");
1289 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1290 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1291 }
1292
Jim Grosbach864b6092011-07-28 21:34:26 +00001293 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1294 assert(N == 1 && "Invalid number of operands!");
1295 // Munge the lsb/width into a bitfield mask.
1296 unsigned lsb = Bitfield.LSB;
1297 unsigned width = Bitfield.Width;
1298 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1299 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1300 (32 - (lsb + width)));
1301 Inst.addOperand(MCOperand::CreateImm(Mask));
1302 }
1303
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001304 void addImmOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 1 && "Invalid number of operands!");
1306 addExpr(Inst, getImm());
1307 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001308
Jim Grosbache7fbce72011-10-03 23:38:36 +00001309 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
1311 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1312 }
1313
Jim Grosbach7db8d692011-09-08 22:07:06 +00001314 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
1316 // FIXME: We really want to scale the value here, but the LDRD/STRD
1317 // instruction don't encode operands that way yet.
1318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1320 }
1321
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001322 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
1324 // The immediate is scaled by four in the encoding and is stored
1325 // in the MCInst as such. Lop off the low two bits here.
1326 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1327 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1328 }
1329
1330 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1331 assert(N == 1 && "Invalid number of operands!");
1332 // The immediate is scaled by four in the encoding and is stored
1333 // in the MCInst as such. Lop off the low two bits here.
1334 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1335 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1336 }
1337
Jim Grosbach475c6db2011-07-25 23:09:14 +00001338 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1339 assert(N == 1 && "Invalid number of operands!");
1340 // The constant encodes as the immediate-1, and we store in the instruction
1341 // the bits as encoded, so subtract off one here.
1342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1343 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1344 }
1345
Jim Grosbach801e0a32011-07-22 23:16:18 +00001346 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
1348 // The constant encodes as the immediate-1, and we store in the instruction
1349 // the bits as encoded, so subtract off one here.
1350 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1351 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1352 }
1353
Jim Grosbach46dd4132011-08-17 21:51:27 +00001354 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
1356 // The constant encodes as the immediate, except for 32, which encodes as
1357 // zero.
1358 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1359 unsigned Imm = CE->getValue();
1360 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1361 }
1362
Jim Grosbach27c1e252011-07-21 17:23:04 +00001363 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1364 assert(N == 1 && "Invalid number of operands!");
1365 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1366 // the instruction as well.
1367 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1368 int Val = CE->getValue();
1369 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1370 }
1371
Jim Grosbachb009a872011-10-28 22:36:30 +00001372 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 // The operand is actually a t2_so_imm, but we have its bitwise
1375 // negation in the assembly source, so twiddle it here.
1376 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1377 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1378 }
1379
Jim Grosbach30506252011-12-08 00:31:07 +00001380 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1381 assert(N == 1 && "Invalid number of operands!");
1382 // The operand is actually a t2_so_imm, but we have its
1383 // negation in the assembly source, so twiddle it here.
1384 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1385 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1386 }
1387
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001388 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 // The operand is actually a so_imm, but we have its bitwise
1391 // negation in the assembly source, so twiddle it here.
1392 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1393 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1394 }
1395
Jim Grosbach30506252011-12-08 00:31:07 +00001396 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 // The operand is actually a so_imm, but we have its
1399 // negation in the assembly source, so twiddle it here.
1400 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1401 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1402 }
1403
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001404 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1407 }
1408
Jim Grosbachd3595712011-08-03 23:50:40 +00001409 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001411 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001412 }
1413
Jim Grosbacha95ec992011-10-11 17:29:55 +00001414 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 2 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1417 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1418 }
1419
Jim Grosbachd3595712011-08-03 23:50:40 +00001420 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1421 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001422 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1423 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001424 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1425 // Special case for #-0
1426 if (Val == INT32_MIN) Val = 0;
1427 if (Val < 0) Val = -Val;
1428 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1429 } else {
1430 // For register offset, we encode the shift type and negation flag
1431 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001432 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1433 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001434 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001435 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1436 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001437 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001438 }
1439
Jim Grosbachcd17c122011-08-04 23:01:30 +00001440 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1441 assert(N == 2 && "Invalid number of operands!");
1442 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1443 assert(CE && "non-constant AM2OffsetImm operand!");
1444 int32_t Val = CE->getValue();
1445 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1446 // Special case for #-0
1447 if (Val == INT32_MIN) Val = 0;
1448 if (Val < 0) Val = -Val;
1449 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1450 Inst.addOperand(MCOperand::CreateReg(0));
1451 Inst.addOperand(MCOperand::CreateImm(Val));
1452 }
1453
Jim Grosbach5b96b802011-08-10 20:29:19 +00001454 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1455 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001456 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1457 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001458 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1459 // Special case for #-0
1460 if (Val == INT32_MIN) Val = 0;
1461 if (Val < 0) Val = -Val;
1462 Val = ARM_AM::getAM3Opc(AddSub, Val);
1463 } else {
1464 // For register offset, we encode the shift type and negation flag
1465 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001466 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001467 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001468 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1469 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001470 Inst.addOperand(MCOperand::CreateImm(Val));
1471 }
1472
1473 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001475 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001476 int32_t Val =
1477 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1478 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1479 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001480 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001481 }
1482
1483 // Constant offset.
1484 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1485 int32_t Val = CE->getValue();
1486 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1487 // Special case for #-0
1488 if (Val == INT32_MIN) Val = 0;
1489 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001490 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001491 Inst.addOperand(MCOperand::CreateReg(0));
1492 Inst.addOperand(MCOperand::CreateImm(Val));
1493 }
1494
Jim Grosbachd3595712011-08-03 23:50:40 +00001495 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001497 // If we have an immediate that's not a constant, treat it as a label
1498 // reference needing a fixup. If it is a constant, it's something else
1499 // and we reject it.
1500 if (isImm()) {
1501 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1502 Inst.addOperand(MCOperand::CreateImm(0));
1503 return;
1504 }
1505
Jim Grosbachd3595712011-08-03 23:50:40 +00001506 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001507 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001508 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::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001513 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001514 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001515 }
1516
Jim Grosbach7db8d692011-09-08 22:07:06 +00001517 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001519 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1520 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001521 Inst.addOperand(MCOperand::CreateImm(Val));
1522 }
1523
Jim Grosbacha05627e2011-09-09 18:37:27 +00001524 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 2 && "Invalid number of operands!");
1526 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001527 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1528 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001529 Inst.addOperand(MCOperand::CreateImm(Val));
1530 }
1531
Jim Grosbachd3595712011-08-03 23:50:40 +00001532 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1533 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001534 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1535 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001536 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001537 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001538
Jim Grosbach2392c532011-09-07 23:39:14 +00001539 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1540 addMemImm8OffsetOperands(Inst, N);
1541 }
1542
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001543 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001544 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001545 }
1546
1547 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 2 && "Invalid number of operands!");
1549 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001550 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001551 addExpr(Inst, getImm());
1552 Inst.addOperand(MCOperand::CreateImm(0));
1553 return;
1554 }
1555
1556 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001557 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1558 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001559 Inst.addOperand(MCOperand::CreateImm(Val));
1560 }
1561
Jim Grosbachd3595712011-08-03 23:50:40 +00001562 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001564 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001565 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001566 addExpr(Inst, getImm());
1567 Inst.addOperand(MCOperand::CreateImm(0));
1568 return;
1569 }
1570
1571 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001572 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1573 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001574 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001575 }
Bill Wendling811c9362010-11-30 07:44:32 +00001576
Jim Grosbach05541f42011-09-19 22:21:13 +00001577 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001579 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1580 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001581 }
1582
1583 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001585 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1586 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001587 }
1588
Jim Grosbachd3595712011-08-03 23:50:40 +00001589 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001591 unsigned Val =
1592 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1593 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001594 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1595 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001596 Inst.addOperand(MCOperand::CreateImm(Val));
1597 }
1598
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001599 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001601 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1602 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1603 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001604 }
1605
Jim Grosbachd3595712011-08-03 23:50:40 +00001606 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001608 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1609 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001610 }
1611
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001612 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1613 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001614 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1615 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001616 Inst.addOperand(MCOperand::CreateImm(Val));
1617 }
1618
Jim Grosbach26d35872011-08-19 18:55:51 +00001619 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1620 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001621 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1622 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001623 Inst.addOperand(MCOperand::CreateImm(Val));
1624 }
1625
Jim Grosbacha32c7532011-08-19 18:49:59 +00001626 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1627 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001628 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001630 Inst.addOperand(MCOperand::CreateImm(Val));
1631 }
1632
Jim Grosbach23983d62011-08-19 18:13:48 +00001633 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1634 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001635 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1636 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001637 Inst.addOperand(MCOperand::CreateImm(Val));
1638 }
1639
Jim Grosbachd3595712011-08-03 23:50:40 +00001640 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1641 assert(N == 1 && "Invalid number of operands!");
1642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1643 assert(CE && "non-constant post-idx-imm8 operand!");
1644 int Imm = CE->getValue();
1645 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001646 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001647 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1648 Inst.addOperand(MCOperand::CreateImm(Imm));
1649 }
1650
Jim Grosbach93981412011-10-11 21:55:36 +00001651 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1652 assert(N == 1 && "Invalid number of operands!");
1653 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1654 assert(CE && "non-constant post-idx-imm8s4 operand!");
1655 int Imm = CE->getValue();
1656 bool isAdd = Imm >= 0;
1657 if (Imm == INT32_MIN) Imm = 0;
1658 // Immediate is scaled by 4.
1659 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1660 Inst.addOperand(MCOperand::CreateImm(Imm));
1661 }
1662
Jim Grosbachd3595712011-08-03 23:50:40 +00001663 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
1665 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001666 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1667 }
1668
1669 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1670 assert(N == 2 && "Invalid number of operands!");
1671 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1672 // The sign, shift type, and shift amount are encoded in a single operand
1673 // using the AM2 encoding helpers.
1674 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1675 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1676 PostIdxReg.ShiftTy);
1677 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001678 }
1679
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001680 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1681 assert(N == 1 && "Invalid number of operands!");
1682 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1683 }
1684
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001685 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 1 && "Invalid number of operands!");
1687 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1688 }
1689
Jim Grosbach182b6a02011-11-29 23:51:09 +00001690 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001691 assert(N == 1 && "Invalid number of operands!");
1692 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1693 }
1694
Jim Grosbach04945c42011-12-02 00:35:16 +00001695 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1696 assert(N == 2 && "Invalid number of operands!");
1697 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1698 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1699 }
1700
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001701 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1702 assert(N == 1 && "Invalid number of operands!");
1703 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1704 }
1705
1706 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1707 assert(N == 1 && "Invalid number of operands!");
1708 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1709 }
1710
1711 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1712 assert(N == 1 && "Invalid number of operands!");
1713 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1714 }
1715
Jim Grosbach741cd732011-10-17 22:26:03 +00001716 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 1 && "Invalid number of operands!");
1718 // The immediate encodes the type of constant as well as the value.
1719 // Mask in that this is an i8 splat.
1720 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1721 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1722 }
1723
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001724 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1725 assert(N == 1 && "Invalid number of operands!");
1726 // The immediate encodes the type of constant as well as the value.
1727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1728 unsigned Value = CE->getValue();
1729 if (Value >= 256)
1730 Value = (Value >> 8) | 0xa00;
1731 else
1732 Value |= 0x800;
1733 Inst.addOperand(MCOperand::CreateImm(Value));
1734 }
1735
Jim Grosbach8211c052011-10-18 00:22:00 +00001736 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1737 assert(N == 1 && "Invalid number of operands!");
1738 // The immediate encodes the type of constant as well as the value.
1739 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1740 unsigned Value = CE->getValue();
1741 if (Value >= 256 && Value <= 0xff00)
1742 Value = (Value >> 8) | 0x200;
1743 else if (Value > 0xffff && Value <= 0xff0000)
1744 Value = (Value >> 16) | 0x400;
1745 else if (Value > 0xffffff)
1746 Value = (Value >> 24) | 0x600;
1747 Inst.addOperand(MCOperand::CreateImm(Value));
1748 }
1749
1750 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1751 assert(N == 1 && "Invalid number of operands!");
1752 // The immediate encodes the type of constant as well as the value.
1753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1754 unsigned Value = CE->getValue();
1755 if (Value >= 256 && Value <= 0xffff)
1756 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1757 else if (Value > 0xffff && Value <= 0xffffff)
1758 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1759 else if (Value > 0xffffff)
1760 Value = (Value >> 24) | 0x600;
1761 Inst.addOperand(MCOperand::CreateImm(Value));
1762 }
1763
Jim Grosbache4454e02011-10-18 16:18:11 +00001764 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1765 assert(N == 1 && "Invalid number of operands!");
1766 // The immediate encodes the type of constant as well as the value.
1767 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1768 uint64_t Value = CE->getValue();
1769 unsigned Imm = 0;
1770 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1771 Imm |= (Value & 1) << i;
1772 }
1773 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1774 }
1775
Jim Grosbach602aa902011-07-13 15:34:57 +00001776 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001777
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001778 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001779 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001780 Op->ITMask.Mask = Mask;
1781 Op->StartLoc = S;
1782 Op->EndLoc = S;
1783 return Op;
1784 }
1785
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001786 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001787 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001788 Op->CC.Val = CC;
1789 Op->StartLoc = S;
1790 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001791 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001792 }
1793
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001794 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001795 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001796 Op->Cop.Val = CopVal;
1797 Op->StartLoc = S;
1798 Op->EndLoc = S;
1799 return Op;
1800 }
1801
1802 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001803 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001804 Op->Cop.Val = CopVal;
1805 Op->StartLoc = S;
1806 Op->EndLoc = S;
1807 return Op;
1808 }
1809
Jim Grosbach48399582011-10-12 17:34:41 +00001810 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1811 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1812 Op->Cop.Val = Val;
1813 Op->StartLoc = S;
1814 Op->EndLoc = E;
1815 return Op;
1816 }
1817
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001818 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001819 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001820 Op->Reg.RegNum = RegNum;
1821 Op->StartLoc = S;
1822 Op->EndLoc = S;
1823 return Op;
1824 }
1825
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001826 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001827 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001828 Op->Tok.Data = Str.data();
1829 Op->Tok.Length = Str.size();
1830 Op->StartLoc = S;
1831 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001832 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001833 }
1834
Bill Wendling2063b842010-11-18 23:43:05 +00001835 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001836 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001837 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001838 Op->StartLoc = S;
1839 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001840 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001841 }
1842
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001843 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1844 unsigned SrcReg,
1845 unsigned ShiftReg,
1846 unsigned ShiftImm,
1847 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001848 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001849 Op->RegShiftedReg.ShiftTy = ShTy;
1850 Op->RegShiftedReg.SrcReg = SrcReg;
1851 Op->RegShiftedReg.ShiftReg = ShiftReg;
1852 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001853 Op->StartLoc = S;
1854 Op->EndLoc = E;
1855 return Op;
1856 }
1857
Owen Andersonb595ed02011-07-21 18:54:16 +00001858 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1859 unsigned SrcReg,
1860 unsigned ShiftImm,
1861 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001862 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001863 Op->RegShiftedImm.ShiftTy = ShTy;
1864 Op->RegShiftedImm.SrcReg = SrcReg;
1865 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001866 Op->StartLoc = S;
1867 Op->EndLoc = E;
1868 return Op;
1869 }
1870
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001871 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001872 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001873 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001874 Op->ShifterImm.isASR = isASR;
1875 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001876 Op->StartLoc = S;
1877 Op->EndLoc = E;
1878 return Op;
1879 }
1880
Jim Grosbach833b9d32011-07-27 20:15:40 +00001881 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001882 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001883 Op->RotImm.Imm = Imm;
1884 Op->StartLoc = S;
1885 Op->EndLoc = E;
1886 return Op;
1887 }
1888
Jim Grosbach864b6092011-07-28 21:34:26 +00001889 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1890 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001892 Op->Bitfield.LSB = LSB;
1893 Op->Bitfield.Width = Width;
1894 Op->StartLoc = S;
1895 Op->EndLoc = E;
1896 return Op;
1897 }
1898
Bill Wendling2cae3272010-11-09 22:44:22 +00001899 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001900 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001901 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001902 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001903
Jim Grosbach75461af2011-09-13 22:56:44 +00001904 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001905 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001906 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001907 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001908 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001909
1910 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001911 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001912 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001913 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001914 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001915 Op->StartLoc = StartLoc;
1916 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001917 return Op;
1918 }
1919
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001920 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1921 SMLoc S, SMLoc E) {
1922 ARMOperand *Op = new ARMOperand(k_VectorList);
1923 Op->VectorList.RegNum = RegNum;
1924 Op->VectorList.Count = Count;
1925 Op->StartLoc = S;
1926 Op->EndLoc = E;
1927 return Op;
1928 }
1929
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001930 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1931 SMLoc S, SMLoc E) {
1932 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1933 Op->VectorList.RegNum = RegNum;
1934 Op->VectorList.Count = Count;
1935 Op->StartLoc = S;
1936 Op->EndLoc = E;
1937 return Op;
1938 }
1939
Jim Grosbach04945c42011-12-02 00:35:16 +00001940 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1941 unsigned Index, SMLoc S, SMLoc E) {
1942 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1943 Op->VectorList.RegNum = RegNum;
1944 Op->VectorList.Count = Count;
1945 Op->VectorList.LaneIndex = Index;
1946 Op->StartLoc = S;
1947 Op->EndLoc = E;
1948 return Op;
1949 }
1950
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001951 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1952 MCContext &Ctx) {
1953 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1954 Op->VectorIndex.Val = Idx;
1955 Op->StartLoc = S;
1956 Op->EndLoc = E;
1957 return Op;
1958 }
1959
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001960 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001961 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001962 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001963 Op->StartLoc = S;
1964 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001965 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001966 }
1967
Jim Grosbache7fbce72011-10-03 23:38:36 +00001968 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001969 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001970 Op->FPImm.Val = Val;
1971 Op->StartLoc = S;
1972 Op->EndLoc = S;
1973 return Op;
1974 }
1975
Jim Grosbachd3595712011-08-03 23:50:40 +00001976 static ARMOperand *CreateMem(unsigned BaseRegNum,
1977 const MCConstantExpr *OffsetImm,
1978 unsigned OffsetRegNum,
1979 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001980 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001981 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001982 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001983 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001984 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001985 Op->Memory.BaseRegNum = BaseRegNum;
1986 Op->Memory.OffsetImm = OffsetImm;
1987 Op->Memory.OffsetRegNum = OffsetRegNum;
1988 Op->Memory.ShiftType = ShiftType;
1989 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001990 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001991 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001992 Op->StartLoc = S;
1993 Op->EndLoc = E;
1994 return Op;
1995 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001996
Jim Grosbachc320c852011-08-05 21:28:30 +00001997 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1998 ARM_AM::ShiftOpc ShiftTy,
1999 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002000 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002001 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002002 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002003 Op->PostIdxReg.isAdd = isAdd;
2004 Op->PostIdxReg.ShiftTy = ShiftTy;
2005 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002006 Op->StartLoc = S;
2007 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002008 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002009 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002010
2011 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002012 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002013 Op->MBOpt.Val = Opt;
2014 Op->StartLoc = S;
2015 Op->EndLoc = S;
2016 return Op;
2017 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002018
2019 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002020 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002021 Op->IFlags.Val = IFlags;
2022 Op->StartLoc = S;
2023 Op->EndLoc = S;
2024 return Op;
2025 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002026
2027 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002028 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002029 Op->MMask.Val = MMask;
2030 Op->StartLoc = S;
2031 Op->EndLoc = S;
2032 return Op;
2033 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002034};
2035
2036} // end anonymous namespace.
2037
Jim Grosbach602aa902011-07-13 15:34:57 +00002038void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002039 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002040 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00002041 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2042 << ") >";
2043 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002044 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002045 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002046 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002047 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002048 OS << "<ccout " << getReg() << ">";
2049 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002050 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002051 static const char *MaskStr[] = {
2052 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2053 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2054 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002055 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2056 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2057 break;
2058 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002059 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002060 OS << "<coprocessor number: " << getCoproc() << ">";
2061 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002062 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002063 OS << "<coprocessor register: " << getCoproc() << ">";
2064 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002065 case k_CoprocOption:
2066 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2067 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002068 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002069 OS << "<mask: " << getMSRMask() << ">";
2070 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002071 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002072 getImm()->print(OS);
2073 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002074 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002075 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2076 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002077 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002078 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002079 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002080 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002081 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002082 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002083 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2084 << PostIdxReg.RegNum;
2085 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2086 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2087 << PostIdxReg.ShiftImm;
2088 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002089 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002090 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002091 OS << "<ARM_PROC::";
2092 unsigned IFlags = getProcIFlags();
2093 for (int i=2; i >= 0; --i)
2094 if (IFlags & (1 << i))
2095 OS << ARM_PROC::IFlagsToString(1 << i);
2096 OS << ">";
2097 break;
2098 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002099 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002100 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002101 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002102 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002103 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2104 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002105 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002106 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002107 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002108 << RegShiftedReg.SrcReg << " "
2109 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2110 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002111 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002112 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002113 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002114 << RegShiftedImm.SrcReg << " "
2115 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2116 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002117 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002118 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002119 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2120 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002121 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002122 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2123 << ", width: " << Bitfield.Width << ">";
2124 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002125 case k_RegisterList:
2126 case k_DPRRegisterList:
2127 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002128 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002129
Bill Wendlingbed94652010-11-09 23:28:44 +00002130 const SmallVectorImpl<unsigned> &RegList = getRegList();
2131 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002132 I = RegList.begin(), E = RegList.end(); I != E; ) {
2133 OS << *I;
2134 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002135 }
2136
2137 OS << ">";
2138 break;
2139 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002140 case k_VectorList:
2141 OS << "<vector_list " << VectorList.Count << " * "
2142 << VectorList.RegNum << ">";
2143 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002144 case k_VectorListAllLanes:
2145 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2146 << VectorList.RegNum << ">";
2147 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002148 case k_VectorListIndexed:
2149 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2150 << VectorList.Count << " * " << VectorList.RegNum << ">";
2151 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002152 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002153 OS << "'" << getToken() << "'";
2154 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002155 case k_VectorIndex:
2156 OS << "<vectorindex " << getVectorIndex() << ">";
2157 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002158 }
2159}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002160
2161/// @name Auto-generated Match Functions
2162/// {
2163
2164static unsigned MatchRegisterName(StringRef Name);
2165
2166/// }
2167
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002168bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2169 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002170 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002171
2172 return (RegNo == (unsigned)-1);
2173}
2174
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002175/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002176/// and if it is a register name the token is eaten and the register number is
2177/// returned. Otherwise return -1.
2178///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002179int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002180 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002181 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002182
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002183 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002184 unsigned RegNum = MatchRegisterName(lowerCase);
2185 if (!RegNum) {
2186 RegNum = StringSwitch<unsigned>(lowerCase)
2187 .Case("r13", ARM::SP)
2188 .Case("r14", ARM::LR)
2189 .Case("r15", ARM::PC)
2190 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002191 // Additional register name aliases for 'gas' compatibility.
2192 .Case("a1", ARM::R0)
2193 .Case("a2", ARM::R1)
2194 .Case("a3", ARM::R2)
2195 .Case("a4", ARM::R3)
2196 .Case("v1", ARM::R4)
2197 .Case("v2", ARM::R5)
2198 .Case("v3", ARM::R6)
2199 .Case("v4", ARM::R7)
2200 .Case("v5", ARM::R8)
2201 .Case("v6", ARM::R9)
2202 .Case("v7", ARM::R10)
2203 .Case("v8", ARM::R11)
2204 .Case("sb", ARM::R9)
2205 .Case("sl", ARM::R10)
2206 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002207 .Default(0);
2208 }
2209 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002210
Chris Lattner44e5981c2010-10-30 04:09:10 +00002211 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002212
Chris Lattner44e5981c2010-10-30 04:09:10 +00002213 return RegNum;
2214}
Jim Grosbach99710a82010-11-01 16:44:21 +00002215
Jim Grosbachbb24c592011-07-13 18:49:30 +00002216// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2217// If a recoverable error occurs, return 1. If an irrecoverable error
2218// occurs, return -1. An irrecoverable error is one where tokens have been
2219// consumed in the process of trying to parse the shifter (i.e., when it is
2220// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002221int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002222 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2223 SMLoc S = Parser.getTok().getLoc();
2224 const AsmToken &Tok = Parser.getTok();
2225 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2226
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002227 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002228 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002229 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002230 .Case("lsl", ARM_AM::lsl)
2231 .Case("lsr", ARM_AM::lsr)
2232 .Case("asr", ARM_AM::asr)
2233 .Case("ror", ARM_AM::ror)
2234 .Case("rrx", ARM_AM::rrx)
2235 .Default(ARM_AM::no_shift);
2236
2237 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002238 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002239
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002240 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002241
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002242 // The source register for the shift has already been added to the
2243 // operand list, so we need to pop it off and combine it into the shifted
2244 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002245 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002246 if (!PrevOp->isReg())
2247 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2248 int SrcReg = PrevOp->getReg();
2249 int64_t Imm = 0;
2250 int ShiftReg = 0;
2251 if (ShiftTy == ARM_AM::rrx) {
2252 // RRX Doesn't have an explicit shift amount. The encoder expects
2253 // the shift register to be the same as the source register. Seems odd,
2254 // but OK.
2255 ShiftReg = SrcReg;
2256 } else {
2257 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002258 if (Parser.getTok().is(AsmToken::Hash) ||
2259 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002260 Parser.Lex(); // Eat hash.
2261 SMLoc ImmLoc = Parser.getTok().getLoc();
2262 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002263 if (getParser().ParseExpression(ShiftExpr)) {
2264 Error(ImmLoc, "invalid immediate shift value");
2265 return -1;
2266 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002267 // The expression must be evaluatable as an immediate.
2268 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002269 if (!CE) {
2270 Error(ImmLoc, "invalid immediate shift value");
2271 return -1;
2272 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002273 // Range check the immediate.
2274 // lsl, ror: 0 <= imm <= 31
2275 // lsr, asr: 0 <= imm <= 32
2276 Imm = CE->getValue();
2277 if (Imm < 0 ||
2278 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2279 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002280 Error(ImmLoc, "immediate shift value out of range");
2281 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002282 }
2283 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002284 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002285 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002286 if (ShiftReg == -1) {
2287 Error (L, "expected immediate or register in shift operand");
2288 return -1;
2289 }
2290 } else {
2291 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002292 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002293 return -1;
2294 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002295 }
2296
Owen Andersonb595ed02011-07-21 18:54:16 +00002297 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2298 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002299 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002300 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002301 else
2302 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2303 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002304
Jim Grosbachbb24c592011-07-13 18:49:30 +00002305 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002306}
2307
2308
Bill Wendling2063b842010-11-18 23:43:05 +00002309/// Try to parse a register name. The token must be an Identifier when called.
2310/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2311/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002312///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002313/// TODO this is likely to change to allow different register types and or to
2314/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002315bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002316tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002317 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002318 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002319 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002320 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002321
Bill Wendling2063b842010-11-18 23:43:05 +00002322 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002323
Chris Lattner44e5981c2010-10-30 04:09:10 +00002324 const AsmToken &ExclaimTok = Parser.getTok();
2325 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002326 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2327 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002328 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002329 return false;
2330 }
2331
2332 // Also check for an index operand. This is only legal for vector registers,
2333 // but that'll get caught OK in operand matching, so we don't need to
2334 // explicitly filter everything else out here.
2335 if (Parser.getTok().is(AsmToken::LBrac)) {
2336 SMLoc SIdx = Parser.getTok().getLoc();
2337 Parser.Lex(); // Eat left bracket token.
2338
2339 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002340 if (getParser().ParseExpression(ImmVal))
2341 return MatchOperand_ParseFail;
2342 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2343 if (!MCE) {
2344 TokError("immediate value expected for vector index");
2345 return MatchOperand_ParseFail;
2346 }
2347
2348 SMLoc E = Parser.getTok().getLoc();
2349 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2350 Error(E, "']' expected");
2351 return MatchOperand_ParseFail;
2352 }
2353
2354 Parser.Lex(); // Eat right bracket token.
2355
2356 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2357 SIdx, E,
2358 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002359 }
2360
Bill Wendling2063b842010-11-18 23:43:05 +00002361 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002362}
2363
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002364/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2365/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2366/// "c5", ...
2367static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002368 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2369 // but efficient.
2370 switch (Name.size()) {
2371 default: break;
2372 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002373 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002374 return -1;
2375 switch (Name[1]) {
2376 default: return -1;
2377 case '0': return 0;
2378 case '1': return 1;
2379 case '2': return 2;
2380 case '3': return 3;
2381 case '4': return 4;
2382 case '5': return 5;
2383 case '6': return 6;
2384 case '7': return 7;
2385 case '8': return 8;
2386 case '9': return 9;
2387 }
2388 break;
2389 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002390 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002391 return -1;
2392 switch (Name[2]) {
2393 default: return -1;
2394 case '0': return 10;
2395 case '1': return 11;
2396 case '2': return 12;
2397 case '3': return 13;
2398 case '4': return 14;
2399 case '5': return 15;
2400 }
2401 break;
2402 }
2403
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002404 return -1;
2405}
2406
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002407/// parseITCondCode - Try to parse a condition code for an IT instruction.
2408ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2409parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2410 SMLoc S = Parser.getTok().getLoc();
2411 const AsmToken &Tok = Parser.getTok();
2412 if (!Tok.is(AsmToken::Identifier))
2413 return MatchOperand_NoMatch;
2414 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2415 .Case("eq", ARMCC::EQ)
2416 .Case("ne", ARMCC::NE)
2417 .Case("hs", ARMCC::HS)
2418 .Case("cs", ARMCC::HS)
2419 .Case("lo", ARMCC::LO)
2420 .Case("cc", ARMCC::LO)
2421 .Case("mi", ARMCC::MI)
2422 .Case("pl", ARMCC::PL)
2423 .Case("vs", ARMCC::VS)
2424 .Case("vc", ARMCC::VC)
2425 .Case("hi", ARMCC::HI)
2426 .Case("ls", ARMCC::LS)
2427 .Case("ge", ARMCC::GE)
2428 .Case("lt", ARMCC::LT)
2429 .Case("gt", ARMCC::GT)
2430 .Case("le", ARMCC::LE)
2431 .Case("al", ARMCC::AL)
2432 .Default(~0U);
2433 if (CC == ~0U)
2434 return MatchOperand_NoMatch;
2435 Parser.Lex(); // Eat the token.
2436
2437 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2438
2439 return MatchOperand_Success;
2440}
2441
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002442/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002443/// token must be an Identifier when called, and if it is a coprocessor
2444/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002445ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002446parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002447 SMLoc S = Parser.getTok().getLoc();
2448 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002449 if (Tok.isNot(AsmToken::Identifier))
2450 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002451
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002452 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002453 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002454 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002455
2456 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002457 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002458 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002459}
2460
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002461/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002462/// token must be an Identifier when called, and if it is a coprocessor
2463/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002464ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002465parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002466 SMLoc S = Parser.getTok().getLoc();
2467 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002468 if (Tok.isNot(AsmToken::Identifier))
2469 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002470
2471 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2472 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002473 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002474
2475 Parser.Lex(); // Eat identifier token.
2476 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002477 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002478}
2479
Jim Grosbach48399582011-10-12 17:34:41 +00002480/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2481/// coproc_option : '{' imm0_255 '}'
2482ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2483parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2484 SMLoc S = Parser.getTok().getLoc();
2485
2486 // If this isn't a '{', this isn't a coprocessor immediate operand.
2487 if (Parser.getTok().isNot(AsmToken::LCurly))
2488 return MatchOperand_NoMatch;
2489 Parser.Lex(); // Eat the '{'
2490
2491 const MCExpr *Expr;
2492 SMLoc Loc = Parser.getTok().getLoc();
2493 if (getParser().ParseExpression(Expr)) {
2494 Error(Loc, "illegal expression");
2495 return MatchOperand_ParseFail;
2496 }
2497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2498 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2499 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2500 return MatchOperand_ParseFail;
2501 }
2502 int Val = CE->getValue();
2503
2504 // Check for and consume the closing '}'
2505 if (Parser.getTok().isNot(AsmToken::RCurly))
2506 return MatchOperand_ParseFail;
2507 SMLoc E = Parser.getTok().getLoc();
2508 Parser.Lex(); // Eat the '}'
2509
2510 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2511 return MatchOperand_Success;
2512}
2513
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002514// For register list parsing, we need to map from raw GPR register numbering
2515// to the enumeration values. The enumeration values aren't sorted by
2516// register number due to our using "sp", "lr" and "pc" as canonical names.
2517static unsigned getNextRegister(unsigned Reg) {
2518 // If this is a GPR, we need to do it manually, otherwise we can rely
2519 // on the sort ordering of the enumeration since the other reg-classes
2520 // are sane.
2521 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2522 return Reg + 1;
2523 switch(Reg) {
2524 default: assert(0 && "Invalid GPR number!");
2525 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2526 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2527 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2528 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2529 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2530 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2531 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2532 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2533 }
2534}
2535
Jim Grosbach85a23432011-11-11 21:27:40 +00002536// Return the low-subreg of a given Q register.
2537static unsigned getDRegFromQReg(unsigned QReg) {
2538 switch (QReg) {
2539 default: llvm_unreachable("expected a Q register!");
2540 case ARM::Q0: return ARM::D0;
2541 case ARM::Q1: return ARM::D2;
2542 case ARM::Q2: return ARM::D4;
2543 case ARM::Q3: return ARM::D6;
2544 case ARM::Q4: return ARM::D8;
2545 case ARM::Q5: return ARM::D10;
2546 case ARM::Q6: return ARM::D12;
2547 case ARM::Q7: return ARM::D14;
2548 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002549 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002550 case ARM::Q10: return ARM::D20;
2551 case ARM::Q11: return ARM::D22;
2552 case ARM::Q12: return ARM::D24;
2553 case ARM::Q13: return ARM::D26;
2554 case ARM::Q14: return ARM::D28;
2555 case ARM::Q15: return ARM::D30;
2556 }
2557}
2558
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002559/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002560bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002561parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002562 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002563 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002564 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002565 Parser.Lex(); // Eat '{' token.
2566 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002567
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002568 // Check the first register in the list to see what register class
2569 // this is a list of.
2570 int Reg = tryParseRegister();
2571 if (Reg == -1)
2572 return Error(RegLoc, "register expected");
2573
Jim Grosbach85a23432011-11-11 21:27:40 +00002574 // The reglist instructions have at most 16 registers, so reserve
2575 // space for that many.
2576 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2577
2578 // Allow Q regs and just interpret them as the two D sub-registers.
2579 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2580 Reg = getDRegFromQReg(Reg);
2581 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2582 ++Reg;
2583 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002584 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002585 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2586 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2587 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2588 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2589 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2590 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2591 else
2592 return Error(RegLoc, "invalid register in register list");
2593
Jim Grosbach85a23432011-11-11 21:27:40 +00002594 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002595 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002596
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002597 // This starts immediately after the first register token in the list,
2598 // so we can see either a comma or a minus (range separator) as a legal
2599 // next token.
2600 while (Parser.getTok().is(AsmToken::Comma) ||
2601 Parser.getTok().is(AsmToken::Minus)) {
2602 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002603 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002604 SMLoc EndLoc = Parser.getTok().getLoc();
2605 int EndReg = tryParseRegister();
2606 if (EndReg == -1)
2607 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002608 // Allow Q regs and just interpret them as the two D sub-registers.
2609 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2610 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002611 // If the register is the same as the start reg, there's nothing
2612 // more to do.
2613 if (Reg == EndReg)
2614 continue;
2615 // The register must be in the same register class as the first.
2616 if (!RC->contains(EndReg))
2617 return Error(EndLoc, "invalid register in register list");
2618 // Ranges must go from low to high.
2619 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2620 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002621
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002622 // Add all the registers in the range to the register list.
2623 while (Reg != EndReg) {
2624 Reg = getNextRegister(Reg);
2625 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2626 }
2627 continue;
2628 }
2629 Parser.Lex(); // Eat the comma.
2630 RegLoc = Parser.getTok().getLoc();
2631 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002632 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002633 Reg = tryParseRegister();
2634 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002635 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002636 // Allow Q regs and just interpret them as the two D sub-registers.
2637 bool isQReg = false;
2638 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2639 Reg = getDRegFromQReg(Reg);
2640 isQReg = true;
2641 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002642 // The register must be in the same register class as the first.
2643 if (!RC->contains(Reg))
2644 return Error(RegLoc, "invalid register in register list");
2645 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002646 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002647 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002648 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2649 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2650 ") in register list");
2651 continue;
2652 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002653 // VFP register lists must also be contiguous.
2654 // It's OK to use the enumeration values directly here rather, as the
2655 // VFP register classes have the enum sorted properly.
2656 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2657 Reg != OldReg + 1)
2658 return Error(RegLoc, "non-contiguous register range");
2659 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002660 if (isQReg)
2661 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002662 }
2663
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002664 SMLoc E = Parser.getTok().getLoc();
2665 if (Parser.getTok().isNot(AsmToken::RCurly))
2666 return Error(E, "'}' expected");
2667 Parser.Lex(); // Eat '}' token.
2668
Bill Wendling2063b842010-11-18 23:43:05 +00002669 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2670 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002671}
2672
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002673// Helper function to parse the lane index for vector lists.
2674ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002675parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2676 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002677 if (Parser.getTok().is(AsmToken::LBrac)) {
2678 Parser.Lex(); // Eat the '['.
2679 if (Parser.getTok().is(AsmToken::RBrac)) {
2680 // "Dn[]" is the 'all lanes' syntax.
2681 LaneKind = AllLanes;
2682 Parser.Lex(); // Eat the ']'.
2683 return MatchOperand_Success;
2684 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002685 if (Parser.getTok().is(AsmToken::Integer)) {
2686 int64_t Val = Parser.getTok().getIntVal();
2687 // Make this range check context sensitive for .8, .16, .32.
2688 if (Val < 0 && Val > 7)
2689 Error(Parser.getTok().getLoc(), "lane index out of range");
2690 Index = Val;
2691 LaneKind = IndexedLane;
2692 Parser.Lex(); // Eat the token;
2693 if (Parser.getTok().isNot(AsmToken::RBrac))
2694 Error(Parser.getTok().getLoc(), "']' expected");
2695 Parser.Lex(); // Eat the ']'.
2696 return MatchOperand_Success;
2697 }
2698 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002699 return MatchOperand_ParseFail;
2700 }
2701 LaneKind = NoLanes;
2702 return MatchOperand_Success;
2703}
2704
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002705// parse a vector register list
2706ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2707parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002708 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002709 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002710 SMLoc S = Parser.getTok().getLoc();
2711 // As an extension (to match gas), support a plain D register or Q register
2712 // (without encosing curly braces) as a single or double entry list,
2713 // respectively.
2714 if (Parser.getTok().is(AsmToken::Identifier)) {
2715 int Reg = tryParseRegister();
2716 if (Reg == -1)
2717 return MatchOperand_NoMatch;
2718 SMLoc E = Parser.getTok().getLoc();
2719 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002720 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002721 if (Res != MatchOperand_Success)
2722 return Res;
2723 switch (LaneKind) {
2724 default:
2725 assert(0 && "unexpected lane kind!");
2726 case NoLanes:
2727 E = Parser.getTok().getLoc();
2728 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2729 break;
2730 case AllLanes:
2731 E = Parser.getTok().getLoc();
2732 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2733 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002734 case IndexedLane:
2735 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2736 LaneIndex, S,E));
2737 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002738 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002739 return MatchOperand_Success;
2740 }
2741 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2742 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002743 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002744 if (Res != MatchOperand_Success)
2745 return Res;
2746 switch (LaneKind) {
2747 default:
2748 assert(0 && "unexpected lane kind!");
2749 case NoLanes:
2750 E = Parser.getTok().getLoc();
2751 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2752 break;
2753 case AllLanes:
2754 E = Parser.getTok().getLoc();
2755 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2756 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002757 case IndexedLane:
2758 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2759 LaneIndex, S,E));
2760 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002761 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002762 return MatchOperand_Success;
2763 }
2764 Error(S, "vector register expected");
2765 return MatchOperand_ParseFail;
2766 }
2767
2768 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002769 return MatchOperand_NoMatch;
2770
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002771 Parser.Lex(); // Eat '{' token.
2772 SMLoc RegLoc = Parser.getTok().getLoc();
2773
2774 int Reg = tryParseRegister();
2775 if (Reg == -1) {
2776 Error(RegLoc, "register expected");
2777 return MatchOperand_ParseFail;
2778 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002779 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002780 unsigned FirstReg = Reg;
2781 // The list is of D registers, but we also allow Q regs and just interpret
2782 // them as the two D sub-registers.
2783 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2784 FirstReg = Reg = getDRegFromQReg(Reg);
2785 ++Reg;
2786 ++Count;
2787 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002788 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002789 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002790
Jim Grosbache891fe82011-11-15 23:19:15 +00002791 while (Parser.getTok().is(AsmToken::Comma) ||
2792 Parser.getTok().is(AsmToken::Minus)) {
2793 if (Parser.getTok().is(AsmToken::Minus)) {
2794 Parser.Lex(); // Eat the minus.
2795 SMLoc EndLoc = Parser.getTok().getLoc();
2796 int EndReg = tryParseRegister();
2797 if (EndReg == -1) {
2798 Error(EndLoc, "register expected");
2799 return MatchOperand_ParseFail;
2800 }
2801 // Allow Q regs and just interpret them as the two D sub-registers.
2802 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2803 EndReg = getDRegFromQReg(EndReg) + 1;
2804 // If the register is the same as the start reg, there's nothing
2805 // more to do.
2806 if (Reg == EndReg)
2807 continue;
2808 // The register must be in the same register class as the first.
2809 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2810 Error(EndLoc, "invalid register in register list");
2811 return MatchOperand_ParseFail;
2812 }
2813 // Ranges must go from low to high.
2814 if (Reg > EndReg) {
2815 Error(EndLoc, "bad range in register list");
2816 return MatchOperand_ParseFail;
2817 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002818 // Parse the lane specifier if present.
2819 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002820 unsigned NextLaneIndex;
2821 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002822 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002823 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002824 Error(EndLoc, "mismatched lane index in register list");
2825 return MatchOperand_ParseFail;
2826 }
2827 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002828
2829 // Add all the registers in the range to the register list.
2830 Count += EndReg - Reg;
2831 Reg = EndReg;
2832 continue;
2833 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002834 Parser.Lex(); // Eat the comma.
2835 RegLoc = Parser.getTok().getLoc();
2836 int OldReg = Reg;
2837 Reg = tryParseRegister();
2838 if (Reg == -1) {
2839 Error(RegLoc, "register expected");
2840 return MatchOperand_ParseFail;
2841 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002842 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002843 // It's OK to use the enumeration values directly here rather, as the
2844 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002845 //
2846 // The list is of D registers, but we also allow Q regs and just interpret
2847 // them as the two D sub-registers.
2848 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2849 Reg = getDRegFromQReg(Reg);
2850 if (Reg != OldReg + 1) {
2851 Error(RegLoc, "non-contiguous register range");
2852 return MatchOperand_ParseFail;
2853 }
2854 ++Reg;
2855 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002856 // Parse the lane specifier if present.
2857 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002858 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002859 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002860 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002861 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002862 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002863 Error(EndLoc, "mismatched lane index in register list");
2864 return MatchOperand_ParseFail;
2865 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002866 continue;
2867 }
2868 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002869 if (Reg != OldReg + 1) {
2870 Error(RegLoc, "non-contiguous register range");
2871 return MatchOperand_ParseFail;
2872 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002873 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002874 // Parse the lane specifier if present.
2875 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002876 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002877 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002878 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002879 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002880 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002881 Error(EndLoc, "mismatched lane index in register list");
2882 return MatchOperand_ParseFail;
2883 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002884 }
2885
2886 SMLoc E = Parser.getTok().getLoc();
2887 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2888 Error(E, "'}' expected");
2889 return MatchOperand_ParseFail;
2890 }
2891 Parser.Lex(); // Eat '}' token.
2892
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002893 switch (LaneKind) {
2894 default:
2895 assert(0 && "unexpected lane kind in register list.");
2896 case NoLanes:
2897 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2898 break;
2899 case AllLanes:
2900 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2901 S, E));
2902 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002903 case IndexedLane:
2904 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2905 LaneIndex, S, E));
2906 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002907 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002908 return MatchOperand_Success;
2909}
2910
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002911/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002912ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002913parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002914 SMLoc S = Parser.getTok().getLoc();
2915 const AsmToken &Tok = Parser.getTok();
2916 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2917 StringRef OptStr = Tok.getString();
2918
2919 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2920 .Case("sy", ARM_MB::SY)
2921 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002922 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002923 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002924 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002925 .Case("ishst", ARM_MB::ISHST)
2926 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002927 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002928 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002929 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002930 .Case("osh", ARM_MB::OSH)
2931 .Case("oshst", ARM_MB::OSHST)
2932 .Default(~0U);
2933
2934 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002935 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002936
2937 Parser.Lex(); // Eat identifier token.
2938 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002939 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002940}
2941
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002942/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002943ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002944parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002945 SMLoc S = Parser.getTok().getLoc();
2946 const AsmToken &Tok = Parser.getTok();
2947 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2948 StringRef IFlagsStr = Tok.getString();
2949
Owen Anderson10c5b122011-10-05 17:16:40 +00002950 // An iflags string of "none" is interpreted to mean that none of the AIF
2951 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002952 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002953 if (IFlagsStr != "none") {
2954 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2955 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2956 .Case("a", ARM_PROC::A)
2957 .Case("i", ARM_PROC::I)
2958 .Case("f", ARM_PROC::F)
2959 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002960
Owen Anderson10c5b122011-10-05 17:16:40 +00002961 // If some specific iflag is already set, it means that some letter is
2962 // present more than once, this is not acceptable.
2963 if (Flag == ~0U || (IFlags & Flag))
2964 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002965
Owen Anderson10c5b122011-10-05 17:16:40 +00002966 IFlags |= Flag;
2967 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002968 }
2969
2970 Parser.Lex(); // Eat identifier token.
2971 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2972 return MatchOperand_Success;
2973}
2974
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002975/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002976ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002977parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002978 SMLoc S = Parser.getTok().getLoc();
2979 const AsmToken &Tok = Parser.getTok();
2980 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2981 StringRef Mask = Tok.getString();
2982
James Molloy21efa7d2011-09-28 14:21:38 +00002983 if (isMClass()) {
2984 // See ARMv6-M 10.1.1
2985 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2986 .Case("apsr", 0)
2987 .Case("iapsr", 1)
2988 .Case("eapsr", 2)
2989 .Case("xpsr", 3)
2990 .Case("ipsr", 5)
2991 .Case("epsr", 6)
2992 .Case("iepsr", 7)
2993 .Case("msp", 8)
2994 .Case("psp", 9)
2995 .Case("primask", 16)
2996 .Case("basepri", 17)
2997 .Case("basepri_max", 18)
2998 .Case("faultmask", 19)
2999 .Case("control", 20)
3000 .Default(~0U);
3001
3002 if (FlagsVal == ~0U)
3003 return MatchOperand_NoMatch;
3004
3005 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3006 // basepri, basepri_max and faultmask only valid for V7m.
3007 return MatchOperand_NoMatch;
3008
3009 Parser.Lex(); // Eat identifier token.
3010 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3011 return MatchOperand_Success;
3012 }
3013
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003014 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3015 size_t Start = 0, Next = Mask.find('_');
3016 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003017 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003018 if (Next != StringRef::npos)
3019 Flags = Mask.slice(Next+1, Mask.size());
3020
3021 // FlagsVal contains the complete mask:
3022 // 3-0: Mask
3023 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3024 unsigned FlagsVal = 0;
3025
3026 if (SpecReg == "apsr") {
3027 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003028 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003029 .Case("g", 0x4) // same as CPSR_s
3030 .Case("nzcvqg", 0xc) // same as CPSR_fs
3031 .Default(~0U);
3032
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003033 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003034 if (!Flags.empty())
3035 return MatchOperand_NoMatch;
3036 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003037 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003038 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003039 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003040 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3041 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003042 for (int i = 0, e = Flags.size(); i != e; ++i) {
3043 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3044 .Case("c", 1)
3045 .Case("x", 2)
3046 .Case("s", 4)
3047 .Case("f", 8)
3048 .Default(~0U);
3049
3050 // If some specific flag is already set, it means that some letter is
3051 // present more than once, this is not acceptable.
3052 if (FlagsVal == ~0U || (FlagsVal & Flag))
3053 return MatchOperand_NoMatch;
3054 FlagsVal |= Flag;
3055 }
3056 } else // No match for special register.
3057 return MatchOperand_NoMatch;
3058
Owen Anderson03a173e2011-10-21 18:43:28 +00003059 // Special register without flags is NOT equivalent to "fc" flags.
3060 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3061 // two lines would enable gas compatibility at the expense of breaking
3062 // round-tripping.
3063 //
3064 // if (!FlagsVal)
3065 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003066
3067 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3068 if (SpecReg == "spsr")
3069 FlagsVal |= 16;
3070
3071 Parser.Lex(); // Eat identifier token.
3072 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3073 return MatchOperand_Success;
3074}
3075
Jim Grosbach27c1e252011-07-21 17:23:04 +00003076ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3077parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3078 int Low, int High) {
3079 const AsmToken &Tok = Parser.getTok();
3080 if (Tok.isNot(AsmToken::Identifier)) {
3081 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3082 return MatchOperand_ParseFail;
3083 }
3084 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003085 std::string LowerOp = Op.lower();
3086 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003087 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3088 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3089 return MatchOperand_ParseFail;
3090 }
3091 Parser.Lex(); // Eat shift type token.
3092
3093 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003094 if (Parser.getTok().isNot(AsmToken::Hash) &&
3095 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003096 Error(Parser.getTok().getLoc(), "'#' expected");
3097 return MatchOperand_ParseFail;
3098 }
3099 Parser.Lex(); // Eat hash token.
3100
3101 const MCExpr *ShiftAmount;
3102 SMLoc Loc = Parser.getTok().getLoc();
3103 if (getParser().ParseExpression(ShiftAmount)) {
3104 Error(Loc, "illegal expression");
3105 return MatchOperand_ParseFail;
3106 }
3107 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3108 if (!CE) {
3109 Error(Loc, "constant expression expected");
3110 return MatchOperand_ParseFail;
3111 }
3112 int Val = CE->getValue();
3113 if (Val < Low || Val > High) {
3114 Error(Loc, "immediate value out of range");
3115 return MatchOperand_ParseFail;
3116 }
3117
3118 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3119
3120 return MatchOperand_Success;
3121}
3122
Jim Grosbach0a547702011-07-22 17:44:50 +00003123ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3124parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3125 const AsmToken &Tok = Parser.getTok();
3126 SMLoc S = Tok.getLoc();
3127 if (Tok.isNot(AsmToken::Identifier)) {
3128 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3129 return MatchOperand_ParseFail;
3130 }
3131 int Val = StringSwitch<int>(Tok.getString())
3132 .Case("be", 1)
3133 .Case("le", 0)
3134 .Default(-1);
3135 Parser.Lex(); // Eat the token.
3136
3137 if (Val == -1) {
3138 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3139 return MatchOperand_ParseFail;
3140 }
3141 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3142 getContext()),
3143 S, Parser.getTok().getLoc()));
3144 return MatchOperand_Success;
3145}
3146
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003147/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3148/// instructions. Legal values are:
3149/// lsl #n 'n' in [0,31]
3150/// asr #n 'n' in [1,32]
3151/// n == 32 encoded as n == 0.
3152ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3153parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3154 const AsmToken &Tok = Parser.getTok();
3155 SMLoc S = Tok.getLoc();
3156 if (Tok.isNot(AsmToken::Identifier)) {
3157 Error(S, "shift operator 'asr' or 'lsl' expected");
3158 return MatchOperand_ParseFail;
3159 }
3160 StringRef ShiftName = Tok.getString();
3161 bool isASR;
3162 if (ShiftName == "lsl" || ShiftName == "LSL")
3163 isASR = false;
3164 else if (ShiftName == "asr" || ShiftName == "ASR")
3165 isASR = true;
3166 else {
3167 Error(S, "shift operator 'asr' or 'lsl' expected");
3168 return MatchOperand_ParseFail;
3169 }
3170 Parser.Lex(); // Eat the operator.
3171
3172 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003173 if (Parser.getTok().isNot(AsmToken::Hash) &&
3174 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003175 Error(Parser.getTok().getLoc(), "'#' expected");
3176 return MatchOperand_ParseFail;
3177 }
3178 Parser.Lex(); // Eat hash token.
3179
3180 const MCExpr *ShiftAmount;
3181 SMLoc E = Parser.getTok().getLoc();
3182 if (getParser().ParseExpression(ShiftAmount)) {
3183 Error(E, "malformed shift expression");
3184 return MatchOperand_ParseFail;
3185 }
3186 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3187 if (!CE) {
3188 Error(E, "shift amount must be an immediate");
3189 return MatchOperand_ParseFail;
3190 }
3191
3192 int64_t Val = CE->getValue();
3193 if (isASR) {
3194 // Shift amount must be in [1,32]
3195 if (Val < 1 || Val > 32) {
3196 Error(E, "'asr' shift amount must be in range [1,32]");
3197 return MatchOperand_ParseFail;
3198 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003199 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3200 if (isThumb() && Val == 32) {
3201 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3202 return MatchOperand_ParseFail;
3203 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003204 if (Val == 32) Val = 0;
3205 } else {
3206 // Shift amount must be in [1,32]
3207 if (Val < 0 || Val > 31) {
3208 Error(E, "'lsr' shift amount must be in range [0,31]");
3209 return MatchOperand_ParseFail;
3210 }
3211 }
3212
3213 E = Parser.getTok().getLoc();
3214 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3215
3216 return MatchOperand_Success;
3217}
3218
Jim Grosbach833b9d32011-07-27 20:15:40 +00003219/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3220/// of instructions. Legal values are:
3221/// ror #n 'n' in {0, 8, 16, 24}
3222ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3223parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3224 const AsmToken &Tok = Parser.getTok();
3225 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003226 if (Tok.isNot(AsmToken::Identifier))
3227 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003228 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003229 if (ShiftName != "ror" && ShiftName != "ROR")
3230 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003231 Parser.Lex(); // Eat the operator.
3232
3233 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003234 if (Parser.getTok().isNot(AsmToken::Hash) &&
3235 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003236 Error(Parser.getTok().getLoc(), "'#' expected");
3237 return MatchOperand_ParseFail;
3238 }
3239 Parser.Lex(); // Eat hash token.
3240
3241 const MCExpr *ShiftAmount;
3242 SMLoc E = Parser.getTok().getLoc();
3243 if (getParser().ParseExpression(ShiftAmount)) {
3244 Error(E, "malformed rotate expression");
3245 return MatchOperand_ParseFail;
3246 }
3247 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3248 if (!CE) {
3249 Error(E, "rotate amount must be an immediate");
3250 return MatchOperand_ParseFail;
3251 }
3252
3253 int64_t Val = CE->getValue();
3254 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3255 // normally, zero is represented in asm by omitting the rotate operand
3256 // entirely.
3257 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3258 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3259 return MatchOperand_ParseFail;
3260 }
3261
3262 E = Parser.getTok().getLoc();
3263 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3264
3265 return MatchOperand_Success;
3266}
3267
Jim Grosbach864b6092011-07-28 21:34:26 +00003268ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3269parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3270 SMLoc S = Parser.getTok().getLoc();
3271 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003272 if (Parser.getTok().isNot(AsmToken::Hash) &&
3273 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003274 Error(Parser.getTok().getLoc(), "'#' expected");
3275 return MatchOperand_ParseFail;
3276 }
3277 Parser.Lex(); // Eat hash token.
3278
3279 const MCExpr *LSBExpr;
3280 SMLoc E = Parser.getTok().getLoc();
3281 if (getParser().ParseExpression(LSBExpr)) {
3282 Error(E, "malformed immediate expression");
3283 return MatchOperand_ParseFail;
3284 }
3285 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3286 if (!CE) {
3287 Error(E, "'lsb' operand must be an immediate");
3288 return MatchOperand_ParseFail;
3289 }
3290
3291 int64_t LSB = CE->getValue();
3292 // The LSB must be in the range [0,31]
3293 if (LSB < 0 || LSB > 31) {
3294 Error(E, "'lsb' operand must be in the range [0,31]");
3295 return MatchOperand_ParseFail;
3296 }
3297 E = Parser.getTok().getLoc();
3298
3299 // Expect another immediate operand.
3300 if (Parser.getTok().isNot(AsmToken::Comma)) {
3301 Error(Parser.getTok().getLoc(), "too few operands");
3302 return MatchOperand_ParseFail;
3303 }
3304 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003305 if (Parser.getTok().isNot(AsmToken::Hash) &&
3306 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003307 Error(Parser.getTok().getLoc(), "'#' expected");
3308 return MatchOperand_ParseFail;
3309 }
3310 Parser.Lex(); // Eat hash token.
3311
3312 const MCExpr *WidthExpr;
3313 if (getParser().ParseExpression(WidthExpr)) {
3314 Error(E, "malformed immediate expression");
3315 return MatchOperand_ParseFail;
3316 }
3317 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3318 if (!CE) {
3319 Error(E, "'width' operand must be an immediate");
3320 return MatchOperand_ParseFail;
3321 }
3322
3323 int64_t Width = CE->getValue();
3324 // The LSB must be in the range [1,32-lsb]
3325 if (Width < 1 || Width > 32 - LSB) {
3326 Error(E, "'width' operand must be in the range [1,32-lsb]");
3327 return MatchOperand_ParseFail;
3328 }
3329 E = Parser.getTok().getLoc();
3330
3331 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3332
3333 return MatchOperand_Success;
3334}
3335
Jim Grosbachd3595712011-08-03 23:50:40 +00003336ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3337parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3338 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003339 // postidx_reg := '+' register {, shift}
3340 // | '-' register {, shift}
3341 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003342
3343 // This method must return MatchOperand_NoMatch without consuming any tokens
3344 // in the case where there is no match, as other alternatives take other
3345 // parse methods.
3346 AsmToken Tok = Parser.getTok();
3347 SMLoc S = Tok.getLoc();
3348 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003349 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003350 int Reg = -1;
3351 if (Tok.is(AsmToken::Plus)) {
3352 Parser.Lex(); // Eat the '+' token.
3353 haveEaten = true;
3354 } else if (Tok.is(AsmToken::Minus)) {
3355 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003356 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003357 haveEaten = true;
3358 }
3359 if (Parser.getTok().is(AsmToken::Identifier))
3360 Reg = tryParseRegister();
3361 if (Reg == -1) {
3362 if (!haveEaten)
3363 return MatchOperand_NoMatch;
3364 Error(Parser.getTok().getLoc(), "register expected");
3365 return MatchOperand_ParseFail;
3366 }
3367 SMLoc E = Parser.getTok().getLoc();
3368
Jim Grosbachc320c852011-08-05 21:28:30 +00003369 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3370 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003371 if (Parser.getTok().is(AsmToken::Comma)) {
3372 Parser.Lex(); // Eat the ','.
3373 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3374 return MatchOperand_ParseFail;
3375 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003376
3377 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3378 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003379
3380 return MatchOperand_Success;
3381}
3382
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003383ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3384parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3385 // Check for a post-index addressing register operand. Specifically:
3386 // am3offset := '+' register
3387 // | '-' register
3388 // | register
3389 // | # imm
3390 // | # + imm
3391 // | # - imm
3392
3393 // This method must return MatchOperand_NoMatch without consuming any tokens
3394 // in the case where there is no match, as other alternatives take other
3395 // parse methods.
3396 AsmToken Tok = Parser.getTok();
3397 SMLoc S = Tok.getLoc();
3398
3399 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003400 if (Parser.getTok().is(AsmToken::Hash) ||
3401 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003402 Parser.Lex(); // Eat the '#'.
3403 // Explicitly look for a '-', as we need to encode negative zero
3404 // differently.
3405 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3406 const MCExpr *Offset;
3407 if (getParser().ParseExpression(Offset))
3408 return MatchOperand_ParseFail;
3409 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3410 if (!CE) {
3411 Error(S, "constant expression expected");
3412 return MatchOperand_ParseFail;
3413 }
3414 SMLoc E = Tok.getLoc();
3415 // Negative zero is encoded as the flag value INT32_MIN.
3416 int32_t Val = CE->getValue();
3417 if (isNegative && Val == 0)
3418 Val = INT32_MIN;
3419
3420 Operands.push_back(
3421 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3422
3423 return MatchOperand_Success;
3424 }
3425
3426
3427 bool haveEaten = false;
3428 bool isAdd = true;
3429 int Reg = -1;
3430 if (Tok.is(AsmToken::Plus)) {
3431 Parser.Lex(); // Eat the '+' token.
3432 haveEaten = true;
3433 } else if (Tok.is(AsmToken::Minus)) {
3434 Parser.Lex(); // Eat the '-' token.
3435 isAdd = false;
3436 haveEaten = true;
3437 }
3438 if (Parser.getTok().is(AsmToken::Identifier))
3439 Reg = tryParseRegister();
3440 if (Reg == -1) {
3441 if (!haveEaten)
3442 return MatchOperand_NoMatch;
3443 Error(Parser.getTok().getLoc(), "register expected");
3444 return MatchOperand_ParseFail;
3445 }
3446 SMLoc E = Parser.getTok().getLoc();
3447
3448 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3449 0, S, E));
3450
3451 return MatchOperand_Success;
3452}
3453
Jim Grosbach7db8d692011-09-08 22:07:06 +00003454/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3455/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3456/// when they refer multiple MIOperands inside a single one.
3457bool ARMAsmParser::
3458cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3459 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3460 // Rt, Rt2
3461 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3462 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3463 // Create a writeback register dummy placeholder.
3464 Inst.addOperand(MCOperand::CreateReg(0));
3465 // addr
3466 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3467 // pred
3468 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3469 return true;
3470}
3471
3472/// cvtT2StrdPre - Convert parsed operands to MCInst.
3473/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3474/// when they refer multiple MIOperands inside a single one.
3475bool ARMAsmParser::
3476cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3477 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3478 // Create a writeback register dummy placeholder.
3479 Inst.addOperand(MCOperand::CreateReg(0));
3480 // Rt, Rt2
3481 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3482 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3483 // addr
3484 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3485 // pred
3486 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3487 return true;
3488}
3489
Jim Grosbachc086f682011-09-08 00:39:19 +00003490/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3491/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3492/// when they refer multiple MIOperands inside a single one.
3493bool ARMAsmParser::
3494cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3495 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3496 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3497
3498 // Create a writeback register dummy placeholder.
3499 Inst.addOperand(MCOperand::CreateImm(0));
3500
3501 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3502 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3503 return true;
3504}
3505
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003506/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3507/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3508/// when they refer multiple MIOperands inside a single one.
3509bool ARMAsmParser::
3510cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3511 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3512 // Create a writeback register dummy placeholder.
3513 Inst.addOperand(MCOperand::CreateImm(0));
3514 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3515 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3516 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3517 return true;
3518}
3519
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003520/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003521/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3522/// when they refer multiple MIOperands inside a single one.
3523bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003524cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003525 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3526 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3527
3528 // Create a writeback register dummy placeholder.
3529 Inst.addOperand(MCOperand::CreateImm(0));
3530
Jim Grosbachd3595712011-08-03 23:50:40 +00003531 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003532 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3533 return true;
3534}
3535
Owen Anderson16d33f32011-08-26 20:43:14 +00003536/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3537/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3538/// when they refer multiple MIOperands inside a single one.
3539bool ARMAsmParser::
3540cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3541 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3542 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3543
3544 // Create a writeback register dummy placeholder.
3545 Inst.addOperand(MCOperand::CreateImm(0));
3546
3547 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3548 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3549 return true;
3550}
3551
3552
Jim Grosbachd564bf32011-08-11 19:22:40 +00003553/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3554/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3555/// when they refer multiple MIOperands inside a single one.
3556bool ARMAsmParser::
3557cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3558 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3559 // Create a writeback register dummy placeholder.
3560 Inst.addOperand(MCOperand::CreateImm(0));
3561 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3562 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3563 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3564 return true;
3565}
3566
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003567/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003568/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3569/// when they refer multiple MIOperands inside a single one.
3570bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003571cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003572 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3573 // Create a writeback register dummy placeholder.
3574 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003575 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3576 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3577 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003578 return true;
3579}
3580
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003581/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3582/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3583/// when they refer multiple MIOperands inside a single one.
3584bool ARMAsmParser::
3585cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3586 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3587 // Create a writeback register dummy placeholder.
3588 Inst.addOperand(MCOperand::CreateImm(0));
3589 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3590 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3591 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3592 return true;
3593}
3594
Jim Grosbachd3595712011-08-03 23:50:40 +00003595/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3596/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3597/// when they refer multiple MIOperands inside a single one.
3598bool ARMAsmParser::
3599cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3600 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3601 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003602 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003603 // Create a writeback register dummy placeholder.
3604 Inst.addOperand(MCOperand::CreateImm(0));
3605 // addr
3606 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3607 // offset
3608 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3609 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003610 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3611 return true;
3612}
3613
Jim Grosbachd3595712011-08-03 23:50:40 +00003614/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003615/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3616/// when they refer multiple MIOperands inside a single one.
3617bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003618cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3619 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3620 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003621 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003622 // Create a writeback register dummy placeholder.
3623 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003624 // addr
3625 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3626 // offset
3627 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3628 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003629 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3630 return true;
3631}
3632
Jim Grosbachd3595712011-08-03 23:50:40 +00003633/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003634/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3635/// when they refer multiple MIOperands inside a single one.
3636bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003637cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3638 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003639 // Create a writeback register dummy placeholder.
3640 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003641 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003642 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003643 // addr
3644 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3645 // offset
3646 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3647 // pred
3648 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3649 return true;
3650}
3651
3652/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3653/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3654/// when they refer multiple MIOperands inside a single one.
3655bool ARMAsmParser::
3656cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3657 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3658 // Create a writeback register dummy placeholder.
3659 Inst.addOperand(MCOperand::CreateImm(0));
3660 // Rt
3661 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3662 // addr
3663 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3664 // offset
3665 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3666 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003667 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3668 return true;
3669}
3670
Jim Grosbach5b96b802011-08-10 20:29:19 +00003671/// cvtLdrdPre - Convert parsed operands to MCInst.
3672/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3673/// when they refer multiple MIOperands inside a single one.
3674bool ARMAsmParser::
3675cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3676 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3677 // Rt, Rt2
3678 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3679 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3680 // Create a writeback register dummy placeholder.
3681 Inst.addOperand(MCOperand::CreateImm(0));
3682 // addr
3683 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3684 // pred
3685 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3686 return true;
3687}
3688
Jim Grosbacheb09f492011-08-11 20:28:23 +00003689/// cvtStrdPre - Convert parsed operands to MCInst.
3690/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3691/// when they refer multiple MIOperands inside a single one.
3692bool ARMAsmParser::
3693cvtStrdPre(MCInst &Inst, unsigned Opcode,
3694 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3695 // Create a writeback register dummy placeholder.
3696 Inst.addOperand(MCOperand::CreateImm(0));
3697 // Rt, Rt2
3698 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3699 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3700 // addr
3701 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3702 // pred
3703 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3704 return true;
3705}
3706
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003707/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3708/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3709/// when they refer multiple MIOperands inside a single one.
3710bool ARMAsmParser::
3711cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3712 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3713 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3714 // Create a writeback register dummy placeholder.
3715 Inst.addOperand(MCOperand::CreateImm(0));
3716 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3717 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3718 return true;
3719}
3720
Jim Grosbach8e048492011-08-19 22:07:46 +00003721/// cvtThumbMultiple- Convert parsed operands to MCInst.
3722/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3723/// when they refer multiple MIOperands inside a single one.
3724bool ARMAsmParser::
3725cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3726 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3727 // The second source operand must be the same register as the destination
3728 // operand.
3729 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003730 (((ARMOperand*)Operands[3])->getReg() !=
3731 ((ARMOperand*)Operands[5])->getReg()) &&
3732 (((ARMOperand*)Operands[3])->getReg() !=
3733 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003734 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003735 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003736 return false;
3737 }
3738 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3739 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003740 // If we have a three-operand form, make sure to set Rn to be the operand
3741 // that isn't the same as Rd.
3742 unsigned RegOp = 4;
3743 if (Operands.size() == 6 &&
3744 ((ARMOperand*)Operands[4])->getReg() ==
3745 ((ARMOperand*)Operands[3])->getReg())
3746 RegOp = 5;
3747 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3748 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003749 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3750
3751 return true;
3752}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003753
Jim Grosbach3ea06572011-10-24 22:16:58 +00003754bool ARMAsmParser::
3755cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3756 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3757 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003758 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003759 // Create a writeback register dummy placeholder.
3760 Inst.addOperand(MCOperand::CreateImm(0));
3761 // Vn
3762 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3763 // pred
3764 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3765 return true;
3766}
3767
3768bool ARMAsmParser::
3769cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3770 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3771 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003772 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003773 // Create a writeback register dummy placeholder.
3774 Inst.addOperand(MCOperand::CreateImm(0));
3775 // Vn
3776 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3777 // Vm
3778 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3779 // pred
3780 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3781 return true;
3782}
3783
Jim Grosbach05df4602011-10-31 21:50:31 +00003784bool ARMAsmParser::
3785cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3786 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3787 // Create a writeback register dummy placeholder.
3788 Inst.addOperand(MCOperand::CreateImm(0));
3789 // Vn
3790 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3791 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003792 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003793 // pred
3794 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3795 return true;
3796}
3797
3798bool ARMAsmParser::
3799cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3800 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3801 // Create a writeback register dummy placeholder.
3802 Inst.addOperand(MCOperand::CreateImm(0));
3803 // Vn
3804 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3805 // Vm
3806 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3807 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003808 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003809 // pred
3810 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3811 return true;
3812}
3813
Bill Wendlinge18980a2010-11-06 22:36:58 +00003814/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003815/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003816bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003817parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003818 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003819 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003820 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003821 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003822 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003823
Sean Callanan936b0d32010-01-19 21:44:56 +00003824 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003825 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003826 if (BaseRegNum == -1)
3827 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003828
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003829 // The next token must either be a comma or a closing bracket.
3830 const AsmToken &Tok = Parser.getTok();
3831 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003832 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003833
Jim Grosbachd3595712011-08-03 23:50:40 +00003834 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003835 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003836 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003837
Jim Grosbachd3595712011-08-03 23:50:40 +00003838 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003839 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003840
Jim Grosbach40700e02011-09-19 18:42:21 +00003841 // If there's a pre-indexing writeback marker, '!', just add it as a token
3842 // operand. It's rather odd, but syntactically valid.
3843 if (Parser.getTok().is(AsmToken::Exclaim)) {
3844 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3845 Parser.Lex(); // Eat the '!'.
3846 }
3847
Jim Grosbachd3595712011-08-03 23:50:40 +00003848 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003849 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003850
Jim Grosbachd3595712011-08-03 23:50:40 +00003851 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3852 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003853
Jim Grosbacha95ec992011-10-11 17:29:55 +00003854 // If we have a ':', it's an alignment specifier.
3855 if (Parser.getTok().is(AsmToken::Colon)) {
3856 Parser.Lex(); // Eat the ':'.
3857 E = Parser.getTok().getLoc();
3858
3859 const MCExpr *Expr;
3860 if (getParser().ParseExpression(Expr))
3861 return true;
3862
3863 // The expression has to be a constant. Memory references with relocations
3864 // don't come through here, as they use the <label> forms of the relevant
3865 // instructions.
3866 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3867 if (!CE)
3868 return Error (E, "constant expression expected");
3869
3870 unsigned Align = 0;
3871 switch (CE->getValue()) {
3872 default:
3873 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3874 case 64: Align = 8; break;
3875 case 128: Align = 16; break;
3876 case 256: Align = 32; break;
3877 }
3878
3879 // Now we should have the closing ']'
3880 E = Parser.getTok().getLoc();
3881 if (Parser.getTok().isNot(AsmToken::RBrac))
3882 return Error(E, "']' expected");
3883 Parser.Lex(); // Eat right bracket token.
3884
3885 // Don't worry about range checking the value here. That's handled by
3886 // the is*() predicates.
3887 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3888 ARM_AM::no_shift, 0, Align,
3889 false, S, E));
3890
3891 // If there's a pre-indexing writeback marker, '!', just add it as a token
3892 // operand.
3893 if (Parser.getTok().is(AsmToken::Exclaim)) {
3894 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3895 Parser.Lex(); // Eat the '!'.
3896 }
3897
3898 return false;
3899 }
3900
3901 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00003902 // offset. Be friendly and also accept a plain integer (without a leading
3903 // hash) for gas compatibility.
3904 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003905 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00003906 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003907 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00003908 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00003909 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003910
Owen Anderson967674d2011-08-29 19:36:44 +00003911 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003912 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003913 if (getParser().ParseExpression(Offset))
3914 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003915
3916 // The expression has to be a constant. Memory references with relocations
3917 // don't come through here, as they use the <label> forms of the relevant
3918 // instructions.
3919 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3920 if (!CE)
3921 return Error (E, "constant expression expected");
3922
Owen Anderson967674d2011-08-29 19:36:44 +00003923 // If the constant was #-0, represent it as INT32_MIN.
3924 int32_t Val = CE->getValue();
3925 if (isNegative && Val == 0)
3926 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3927
Jim Grosbachd3595712011-08-03 23:50:40 +00003928 // Now we should have the closing ']'
3929 E = Parser.getTok().getLoc();
3930 if (Parser.getTok().isNot(AsmToken::RBrac))
3931 return Error(E, "']' expected");
3932 Parser.Lex(); // Eat right bracket token.
3933
3934 // Don't worry about range checking the value here. That's handled by
3935 // the is*() predicates.
3936 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003937 ARM_AM::no_shift, 0, 0,
3938 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003939
3940 // If there's a pre-indexing writeback marker, '!', just add it as a token
3941 // operand.
3942 if (Parser.getTok().is(AsmToken::Exclaim)) {
3943 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3944 Parser.Lex(); // Eat the '!'.
3945 }
3946
3947 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003948 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003949
3950 // The register offset is optionally preceded by a '+' or '-'
3951 bool isNegative = false;
3952 if (Parser.getTok().is(AsmToken::Minus)) {
3953 isNegative = true;
3954 Parser.Lex(); // Eat the '-'.
3955 } else if (Parser.getTok().is(AsmToken::Plus)) {
3956 // Nothing to do.
3957 Parser.Lex(); // Eat the '+'.
3958 }
3959
3960 E = Parser.getTok().getLoc();
3961 int OffsetRegNum = tryParseRegister();
3962 if (OffsetRegNum == -1)
3963 return Error(E, "register expected");
3964
3965 // If there's a shift operator, handle it.
3966 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003967 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003968 if (Parser.getTok().is(AsmToken::Comma)) {
3969 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003970 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003971 return true;
3972 }
3973
3974 // Now we should have the closing ']'
3975 E = Parser.getTok().getLoc();
3976 if (Parser.getTok().isNot(AsmToken::RBrac))
3977 return Error(E, "']' expected");
3978 Parser.Lex(); // Eat right bracket token.
3979
3980 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003981 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003982 S, E));
3983
Jim Grosbachc320c852011-08-05 21:28:30 +00003984 // If there's a pre-indexing writeback marker, '!', just add it as a token
3985 // operand.
3986 if (Parser.getTok().is(AsmToken::Exclaim)) {
3987 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3988 Parser.Lex(); // Eat the '!'.
3989 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003990
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003991 return false;
3992}
3993
Jim Grosbachd3595712011-08-03 23:50:40 +00003994/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003995/// ( lsl | lsr | asr | ror ) , # shift_amount
3996/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003997/// return true if it parses a shift otherwise it returns false.
3998bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3999 unsigned &Amount) {
4000 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004001 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004002 if (Tok.isNot(AsmToken::Identifier))
4003 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004004 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004005 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4006 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004007 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004008 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004009 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004010 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004011 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004012 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004013 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004014 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004015 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004016 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004017 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004018 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004019
Jim Grosbachd3595712011-08-03 23:50:40 +00004020 // rrx stands alone.
4021 Amount = 0;
4022 if (St != ARM_AM::rrx) {
4023 Loc = Parser.getTok().getLoc();
4024 // A '#' and a shift amount.
4025 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004026 if (HashTok.isNot(AsmToken::Hash) &&
4027 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004028 return Error(HashTok.getLoc(), "'#' expected");
4029 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004030
Jim Grosbachd3595712011-08-03 23:50:40 +00004031 const MCExpr *Expr;
4032 if (getParser().ParseExpression(Expr))
4033 return true;
4034 // Range check the immediate.
4035 // lsl, ror: 0 <= imm <= 31
4036 // lsr, asr: 0 <= imm <= 32
4037 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4038 if (!CE)
4039 return Error(Loc, "shift amount must be an immediate");
4040 int64_t Imm = CE->getValue();
4041 if (Imm < 0 ||
4042 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4043 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4044 return Error(Loc, "immediate shift value out of range");
4045 Amount = Imm;
4046 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004047
4048 return false;
4049}
4050
Jim Grosbache7fbce72011-10-03 23:38:36 +00004051/// parseFPImm - A floating point immediate expression operand.
4052ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4053parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4054 SMLoc S = Parser.getTok().getLoc();
4055
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004056 if (Parser.getTok().isNot(AsmToken::Hash) &&
4057 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004058 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004059
4060 // Disambiguate the VMOV forms that can accept an FP immediate.
4061 // vmov.f32 <sreg>, #imm
4062 // vmov.f64 <dreg>, #imm
4063 // vmov.f32 <dreg>, #imm @ vector f32x2
4064 // vmov.f32 <qreg>, #imm @ vector f32x4
4065 //
4066 // There are also the NEON VMOV instructions which expect an
4067 // integer constant. Make sure we don't try to parse an FPImm
4068 // for these:
4069 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4070 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4071 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4072 TyOp->getToken() != ".f64"))
4073 return MatchOperand_NoMatch;
4074
Jim Grosbache7fbce72011-10-03 23:38:36 +00004075 Parser.Lex(); // Eat the '#'.
4076
4077 // Handle negation, as that still comes through as a separate token.
4078 bool isNegative = false;
4079 if (Parser.getTok().is(AsmToken::Minus)) {
4080 isNegative = true;
4081 Parser.Lex();
4082 }
4083 const AsmToken &Tok = Parser.getTok();
4084 if (Tok.is(AsmToken::Real)) {
4085 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4086 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4087 // If we had a '-' in front, toggle the sign bit.
4088 IntVal ^= (uint64_t)isNegative << 63;
4089 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4090 Parser.Lex(); // Eat the token.
4091 if (Val == -1) {
4092 TokError("floating point value out of range");
4093 return MatchOperand_ParseFail;
4094 }
4095 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4096 return MatchOperand_Success;
4097 }
4098 if (Tok.is(AsmToken::Integer)) {
4099 int64_t Val = Tok.getIntVal();
4100 Parser.Lex(); // Eat the token.
4101 if (Val > 255 || Val < 0) {
4102 TokError("encoded floating point value out of range");
4103 return MatchOperand_ParseFail;
4104 }
4105 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4106 return MatchOperand_Success;
4107 }
4108
4109 TokError("invalid floating point immediate");
4110 return MatchOperand_ParseFail;
4111}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004112/// Parse a arm instruction operand. For now this parses the operand regardless
4113/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004114bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004115 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004116 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004117
4118 // Check if the current operand has a custom associated parser, if so, try to
4119 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004120 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4121 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004122 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004123 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4124 // there was a match, but an error occurred, in which case, just return that
4125 // the operand parsing failed.
4126 if (ResTy == MatchOperand_ParseFail)
4127 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004128
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004129 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004130 default:
4131 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004132 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004133 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004134 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004135 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004136 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004137 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004138 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004139 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004140 else if (Res == -1) // irrecoverable error
4141 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004142 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4143 S = Parser.getTok().getLoc();
4144 Parser.Lex();
4145 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4146 return false;
4147 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004148
4149 // Fall though for the Identifier case that is not a register or a
4150 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004151 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004152 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004153 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004154 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004155 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004156 // This was not a register so parse other operands that start with an
4157 // identifier (like labels) as expressions and create them as immediates.
4158 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004159 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004160 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004161 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004162 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004163 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4164 return false;
4165 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004166 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004167 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004168 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004169 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004170 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004171 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004172 // #42 -> immediate.
4173 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004174 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004175 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004176 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004177 const MCExpr *ImmVal;
4178 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004179 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004180 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004181 if (CE) {
4182 int32_t Val = CE->getValue();
4183 if (isNegative && Val == 0)
4184 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004185 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004186 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004187 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4188 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004189 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004190 case AsmToken::Colon: {
4191 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004192 // FIXME: Check it's an expression prefix,
4193 // e.g. (FOO - :lower16:BAR) isn't legal.
4194 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004195 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004196 return true;
4197
Evan Cheng965b3c72011-01-13 07:58:56 +00004198 const MCExpr *SubExprVal;
4199 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004200 return true;
4201
Evan Cheng965b3c72011-01-13 07:58:56 +00004202 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4203 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004204 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004205 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004206 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004207 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004208 }
4209}
4210
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004211// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004212// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004213bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004214 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004215
4216 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004217 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004218 Parser.Lex(); // Eat ':'
4219
4220 if (getLexer().isNot(AsmToken::Identifier)) {
4221 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4222 return true;
4223 }
4224
4225 StringRef IDVal = Parser.getTok().getIdentifier();
4226 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004227 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004228 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004229 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004230 } else {
4231 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4232 return true;
4233 }
4234 Parser.Lex();
4235
4236 if (getLexer().isNot(AsmToken::Colon)) {
4237 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4238 return true;
4239 }
4240 Parser.Lex(); // Eat the last ':'
4241 return false;
4242}
4243
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004244/// \brief Given a mnemonic, split out possible predication code and carry
4245/// setting letters to form a canonical mnemonic and flags.
4246//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004247// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004248// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004249StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004250 unsigned &PredicationCode,
4251 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004252 unsigned &ProcessorIMod,
4253 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004254 PredicationCode = ARMCC::AL;
4255 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004256 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004257
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004258 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004259 //
4260 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004261 if ((Mnemonic == "movs" && isThumb()) ||
4262 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4263 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4264 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4265 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4266 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4267 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4268 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004269 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004270
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004271 // First, split out any predication code. Ignore mnemonics we know aren't
4272 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004273 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004274 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004275 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004276 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004277 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4278 .Case("eq", ARMCC::EQ)
4279 .Case("ne", ARMCC::NE)
4280 .Case("hs", ARMCC::HS)
4281 .Case("cs", ARMCC::HS)
4282 .Case("lo", ARMCC::LO)
4283 .Case("cc", ARMCC::LO)
4284 .Case("mi", ARMCC::MI)
4285 .Case("pl", ARMCC::PL)
4286 .Case("vs", ARMCC::VS)
4287 .Case("vc", ARMCC::VC)
4288 .Case("hi", ARMCC::HI)
4289 .Case("ls", ARMCC::LS)
4290 .Case("ge", ARMCC::GE)
4291 .Case("lt", ARMCC::LT)
4292 .Case("gt", ARMCC::GT)
4293 .Case("le", ARMCC::LE)
4294 .Case("al", ARMCC::AL)
4295 .Default(~0U);
4296 if (CC != ~0U) {
4297 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4298 PredicationCode = CC;
4299 }
Bill Wendling193961b2010-10-29 23:50:21 +00004300 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004301
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004302 // Next, determine if we have a carry setting bit. We explicitly ignore all
4303 // the instructions we know end in 's'.
4304 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004305 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004306 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4307 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4308 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004309 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004310 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach2a2348e2011-12-13 20:13:48 +00004311 Mnemonic == "fsts" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004312 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004313 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4314 CarrySetting = true;
4315 }
4316
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004317 // The "cps" instruction can have a interrupt mode operand which is glued into
4318 // the mnemonic. Check if this is the case, split it and parse the imod op
4319 if (Mnemonic.startswith("cps")) {
4320 // Split out any imod code.
4321 unsigned IMod =
4322 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4323 .Case("ie", ARM_PROC::IE)
4324 .Case("id", ARM_PROC::ID)
4325 .Default(~0U);
4326 if (IMod != ~0U) {
4327 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4328 ProcessorIMod = IMod;
4329 }
4330 }
4331
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004332 // The "it" instruction has the condition mask on the end of the mnemonic.
4333 if (Mnemonic.startswith("it")) {
4334 ITMask = Mnemonic.slice(2, Mnemonic.size());
4335 Mnemonic = Mnemonic.slice(0, 2);
4336 }
4337
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004338 return Mnemonic;
4339}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004340
4341/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4342/// inclusion of carry set or predication code operands.
4343//
4344// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004345void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004346getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004347 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004348 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4349 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004350 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004351 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004352 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004353 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004354 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004355 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004356 Mnemonic == "mla" || Mnemonic == "smlal" ||
4357 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004358 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004359 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004360 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004361
Daniel Dunbar09264122011-01-11 19:06:29 +00004362 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4363 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4364 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4365 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004366 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4367 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004368 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004369 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4370 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4371 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004372 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4373 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004374 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004375 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004376 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004377 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004378
Jim Grosbach6c45b752011-09-16 16:39:25 +00004379 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004380 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004381 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004382 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004383 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004384}
4385
Jim Grosbach7283da92011-08-16 21:12:37 +00004386bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4387 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004388 // FIXME: This is all horribly hacky. We really need a better way to deal
4389 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004390
4391 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4392 // another does not. Specifically, the MOVW instruction does not. So we
4393 // special case it here and remove the defaulted (non-setting) cc_out
4394 // operand if that's the instruction we're trying to match.
4395 //
4396 // We do this as post-processing of the explicit operands rather than just
4397 // conditionally adding the cc_out in the first place because we need
4398 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004399 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004400 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4401 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4402 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4403 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004404
4405 // Register-register 'add' for thumb does not have a cc_out operand
4406 // when there are only two register operands.
4407 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4408 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4409 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4410 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4411 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004412 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004413 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4414 // have to check the immediate range here since Thumb2 has a variant
4415 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004416 if (((isThumb() && Mnemonic == "add") ||
4417 (isThumbTwo() && Mnemonic == "sub")) &&
4418 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004419 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4420 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4421 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004422 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4423 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4424 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004425 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004426 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4427 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004428 // selecting via the generic "add" mnemonic, so to know that we
4429 // should remove the cc_out operand, we have to explicitly check that
4430 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004431 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4432 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004433 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4434 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4435 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4436 // Nest conditions rather than one big 'if' statement for readability.
4437 //
4438 // If either register is a high reg, it's either one of the SP
4439 // variants (handled above) or a 32-bit encoding, so we just
4440 // check against T3.
4441 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4442 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4443 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4444 return false;
4445 // If both registers are low, we're in an IT block, and the immediate is
4446 // in range, we should use encoding T1 instead, which has a cc_out.
4447 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004448 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004449 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4450 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4451 return false;
4452
4453 // Otherwise, we use encoding T4, which does not have a cc_out
4454 // operand.
4455 return true;
4456 }
4457
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004458 // The thumb2 multiply instruction doesn't have a CCOut register, so
4459 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4460 // use the 16-bit encoding or not.
4461 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4462 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4463 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4464 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4465 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4466 // If the registers aren't low regs, the destination reg isn't the
4467 // same as one of the source regs, or the cc_out operand is zero
4468 // outside of an IT block, we have to use the 32-bit encoding, so
4469 // remove the cc_out operand.
4470 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4471 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004472 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004473 !inITBlock() ||
4474 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4475 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4476 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4477 static_cast<ARMOperand*>(Operands[4])->getReg())))
4478 return true;
4479
Jim Grosbachefa7e952011-11-15 19:55:16 +00004480 // Also check the 'mul' syntax variant that doesn't specify an explicit
4481 // destination register.
4482 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4483 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4484 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4485 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4486 // If the registers aren't low regs or the cc_out operand is zero
4487 // outside of an IT block, we have to use the 32-bit encoding, so
4488 // remove the cc_out operand.
4489 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4490 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4491 !inITBlock()))
4492 return true;
4493
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004494
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004495
Jim Grosbach4b701af2011-08-24 21:42:27 +00004496 // Register-register 'add/sub' for thumb does not have a cc_out operand
4497 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4498 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4499 // right, this will result in better diagnostics (which operand is off)
4500 // anyway.
4501 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4502 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004503 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4504 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4505 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4506 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004507
Jim Grosbach7283da92011-08-16 21:12:37 +00004508 return false;
4509}
4510
Jim Grosbach12952fe2011-11-11 23:08:10 +00004511static bool isDataTypeToken(StringRef Tok) {
4512 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4513 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4514 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4515 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4516 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4517 Tok == ".f" || Tok == ".d";
4518}
4519
4520// FIXME: This bit should probably be handled via an explicit match class
4521// in the .td files that matches the suffix instead of having it be
4522// a literal string token the way it is now.
4523static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4524 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4525}
4526
Jim Grosbach8be2f652011-12-09 23:34:09 +00004527static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004528/// Parse an arm instruction mnemonic followed by its operands.
4529bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4530 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004531 // Apply mnemonic aliases before doing anything else, as the destination
4532 // mnemnonic may include suffices and we want to handle them normally.
4533 // The generic tblgen'erated code does this later, at the start of
4534 // MatchInstructionImpl(), but that's too late for aliases that include
4535 // any sort of suffix.
4536 unsigned AvailableFeatures = getAvailableFeatures();
4537 applyMnemonicAliases(Name, AvailableFeatures);
4538
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004539 // Create the leading tokens for the mnemonic, split by '.' characters.
4540 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004541 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004542
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004543 // Split out the predication code and carry setting flag from the mnemonic.
4544 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004545 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004546 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004547 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004548 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004549 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004550
Jim Grosbach1c171b12011-08-25 17:23:55 +00004551 // In Thumb1, only the branch (B) instruction can be predicated.
4552 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4553 Parser.EatToEndOfStatement();
4554 return Error(NameLoc, "conditional execution not supported in Thumb1");
4555 }
4556
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004557 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4558
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004559 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4560 // is the mask as it will be for the IT encoding if the conditional
4561 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4562 // where the conditional bit0 is zero, the instruction post-processing
4563 // will adjust the mask accordingly.
4564 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004565 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4566 if (ITMask.size() > 3) {
4567 Parser.EatToEndOfStatement();
4568 return Error(Loc, "too many conditions on IT instruction");
4569 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004570 unsigned Mask = 8;
4571 for (unsigned i = ITMask.size(); i != 0; --i) {
4572 char pos = ITMask[i - 1];
4573 if (pos != 't' && pos != 'e') {
4574 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004575 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004576 }
4577 Mask >>= 1;
4578 if (ITMask[i - 1] == 't')
4579 Mask |= 8;
4580 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004581 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004582 }
4583
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004584 // FIXME: This is all a pretty gross hack. We should automatically handle
4585 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004586
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004587 // Next, add the CCOut and ConditionCode operands, if needed.
4588 //
4589 // For mnemonics which can ever incorporate a carry setting bit or predication
4590 // code, our matching model involves us always generating CCOut and
4591 // ConditionCode operands to match the mnemonic "as written" and then we let
4592 // the matcher deal with finding the right instruction or generating an
4593 // appropriate error.
4594 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004595 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004596
Jim Grosbach03a8a162011-07-14 22:04:21 +00004597 // If we had a carry-set on an instruction that can't do that, issue an
4598 // error.
4599 if (!CanAcceptCarrySet && CarrySetting) {
4600 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004601 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004602 "' can not set flags, but 's' suffix specified");
4603 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004604 // If we had a predication code on an instruction that can't do that, issue an
4605 // error.
4606 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4607 Parser.EatToEndOfStatement();
4608 return Error(NameLoc, "instruction '" + Mnemonic +
4609 "' is not predicable, but condition code specified");
4610 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004611
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004612 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004613 if (CanAcceptCarrySet) {
4614 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004615 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004616 Loc));
4617 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004618
4619 // Add the predication code operand, if necessary.
4620 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004621 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4622 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004623 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004624 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004625 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004626
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004627 // Add the processor imod operand, if necessary.
4628 if (ProcessorIMod) {
4629 Operands.push_back(ARMOperand::CreateImm(
4630 MCConstantExpr::Create(ProcessorIMod, getContext()),
4631 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004632 }
4633
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004634 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004635 while (Next != StringRef::npos) {
4636 Start = Next;
4637 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004638 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004639
Jim Grosbach12952fe2011-11-11 23:08:10 +00004640 // Some NEON instructions have an optional datatype suffix that is
4641 // completely ignored. Check for that.
4642 if (isDataTypeToken(ExtraToken) &&
4643 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4644 continue;
4645
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004646 if (ExtraToken != ".n") {
4647 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4648 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4649 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004650 }
4651
4652 // Read the remaining operands.
4653 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004654 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004655 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004656 Parser.EatToEndOfStatement();
4657 return true;
4658 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004659
4660 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004661 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004662
4663 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004664 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004665 Parser.EatToEndOfStatement();
4666 return true;
4667 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004668 }
4669 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004670
Chris Lattnera2a9d162010-09-11 16:18:25 +00004671 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004672 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004673 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004674 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004675 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004676
Chris Lattner91689c12010-09-08 05:10:46 +00004677 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004678
Jim Grosbach7283da92011-08-16 21:12:37 +00004679 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4680 // do and don't have a cc_out optional-def operand. With some spot-checks
4681 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004682 // parse and adjust accordingly before actually matching. We shouldn't ever
4683 // try to remove a cc_out operand that was explicitly set on the the
4684 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4685 // table driven matcher doesn't fit well with the ARM instruction set.
4686 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004687 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4688 Operands.erase(Operands.begin() + 1);
4689 delete Op;
4690 }
4691
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004692 // ARM mode 'blx' need special handling, as the register operand version
4693 // is predicable, but the label operand version is not. So, we can't rely
4694 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004695 // a k_CondCode operand in the list. If we're trying to match the label
4696 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004697 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4698 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4699 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4700 Operands.erase(Operands.begin() + 1);
4701 delete Op;
4702 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004703
4704 // The vector-compare-to-zero instructions have a literal token "#0" at
4705 // the end that comes to here as an immediate operand. Convert it to a
4706 // token to play nicely with the matcher.
4707 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4708 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4709 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4710 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4711 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4712 if (CE && CE->getValue() == 0) {
4713 Operands.erase(Operands.begin() + 5);
4714 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4715 delete Op;
4716 }
4717 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004718 // VCMP{E} does the same thing, but with a different operand count.
4719 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4720 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4721 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4723 if (CE && CE->getValue() == 0) {
4724 Operands.erase(Operands.begin() + 4);
4725 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4726 delete Op;
4727 }
4728 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004729 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4730 // end. Convert it to a token here.
4731 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4732 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4733 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4734 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4735 if (CE && CE->getValue() == 0) {
4736 Operands.erase(Operands.begin() + 5);
4737 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4738 delete Op;
4739 }
4740 }
4741
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004742 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004743}
4744
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004745// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004746
4747// return 'true' if register list contains non-low GPR registers,
4748// 'false' otherwise. If Reg is in the register list or is HiReg, set
4749// 'containsReg' to true.
4750static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4751 unsigned HiReg, bool &containsReg) {
4752 containsReg = false;
4753 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4754 unsigned OpReg = Inst.getOperand(i).getReg();
4755 if (OpReg == Reg)
4756 containsReg = true;
4757 // Anything other than a low register isn't legal here.
4758 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4759 return true;
4760 }
4761 return false;
4762}
4763
Jim Grosbacha31f2232011-09-07 18:05:34 +00004764// Check if the specified regisgter is in the register list of the inst,
4765// starting at the indicated operand number.
4766static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4767 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4768 unsigned OpReg = Inst.getOperand(i).getReg();
4769 if (OpReg == Reg)
4770 return true;
4771 }
4772 return false;
4773}
4774
Jim Grosbached16ec42011-08-29 22:24:09 +00004775// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4776// the ARMInsts array) instead. Getting that here requires awkward
4777// API changes, though. Better way?
4778namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004779extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004780}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004781static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004782 return ARMInsts[Opcode];
4783}
4784
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004785// FIXME: We would really like to be able to tablegen'erate this.
4786bool ARMAsmParser::
4787validateInstruction(MCInst &Inst,
4788 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004789 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004790 SMLoc Loc = Operands[0]->getStartLoc();
4791 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004792 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4793 // being allowed in IT blocks, but not being predicable. It just always
4794 // executes.
4795 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004796 unsigned bit = 1;
4797 if (ITState.FirstCond)
4798 ITState.FirstCond = false;
4799 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004800 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004801 // The instruction must be predicable.
4802 if (!MCID.isPredicable())
4803 return Error(Loc, "instructions in IT block must be predicable");
4804 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4805 unsigned ITCond = bit ? ITState.Cond :
4806 ARMCC::getOppositeCondition(ITState.Cond);
4807 if (Cond != ITCond) {
4808 // Find the condition code Operand to get its SMLoc information.
4809 SMLoc CondLoc;
4810 for (unsigned i = 1; i < Operands.size(); ++i)
4811 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4812 CondLoc = Operands[i]->getStartLoc();
4813 return Error(CondLoc, "incorrect condition in IT block; got '" +
4814 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4815 "', but expected '" +
4816 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4817 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004818 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004819 } else if (isThumbTwo() && MCID.isPredicable() &&
4820 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004821 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4822 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004823 return Error(Loc, "predicated instructions must be in IT block");
4824
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004825 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004826 case ARM::LDRD:
4827 case ARM::LDRD_PRE:
4828 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004829 case ARM::LDREXD: {
4830 // Rt2 must be Rt + 1.
4831 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4832 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4833 if (Rt2 != Rt + 1)
4834 return Error(Operands[3]->getStartLoc(),
4835 "destination operands must be sequential");
4836 return false;
4837 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004838 case ARM::STRD: {
4839 // Rt2 must be Rt + 1.
4840 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4841 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4842 if (Rt2 != Rt + 1)
4843 return Error(Operands[3]->getStartLoc(),
4844 "source operands must be sequential");
4845 return false;
4846 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004847 case ARM::STRD_PRE:
4848 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004849 case ARM::STREXD: {
4850 // Rt2 must be Rt + 1.
4851 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4852 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4853 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004854 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004855 "source operands must be sequential");
4856 return false;
4857 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004858 case ARM::SBFX:
4859 case ARM::UBFX: {
4860 // width must be in range [1, 32-lsb]
4861 unsigned lsb = Inst.getOperand(2).getImm();
4862 unsigned widthm1 = Inst.getOperand(3).getImm();
4863 if (widthm1 >= 32 - lsb)
4864 return Error(Operands[5]->getStartLoc(),
4865 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004866 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004867 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004868 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004869 // If we're parsing Thumb2, the .w variant is available and handles
4870 // most cases that are normally illegal for a Thumb1 LDM
4871 // instruction. We'll make the transformation in processInstruction()
4872 // if necessary.
4873 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004874 // Thumb LDM instructions are writeback iff the base register is not
4875 // in the register list.
4876 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004877 bool hasWritebackToken =
4878 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4879 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004880 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004881 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004882 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4883 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004884 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004885 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004886 return Error(Operands[2]->getStartLoc(),
4887 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004888 // If we should not have writeback, there must not be a '!'. This is
4889 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004890 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004891 return Error(Operands[3]->getStartLoc(),
4892 "writeback operator '!' not allowed when base register "
4893 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004894
4895 break;
4896 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004897 case ARM::t2LDMIA_UPD: {
4898 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4899 return Error(Operands[4]->getStartLoc(),
4900 "writeback operator '!' not allowed when base register "
4901 "in register list");
4902 break;
4903 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004904 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4905 // so only issue a diagnostic for thumb1. The instructions will be
4906 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004907 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004908 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004909 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4910 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004911 return Error(Operands[2]->getStartLoc(),
4912 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004913 break;
4914 }
4915 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004916 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004917 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4918 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004919 return Error(Operands[2]->getStartLoc(),
4920 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004921 break;
4922 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004923 case ARM::tSTMIA_UPD: {
4924 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004925 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004926 return Error(Operands[4]->getStartLoc(),
4927 "registers must be in range r0-r7");
4928 break;
4929 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004930 }
4931
4932 return false;
4933}
4934
Jim Grosbacheb538222011-12-02 22:34:51 +00004935static unsigned getRealVSTLNOpcode(unsigned Opc) {
4936 switch(Opc) {
4937 default: assert(0 && "unexpected opcode!");
4938 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4939 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4940 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4941 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4942 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4943 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4944 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4945 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4946 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4947 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4948 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4949 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4950 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4951 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4952 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4953 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4954 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4955 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4956 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4957 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4958 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4959 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4960 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4961 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4962 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4963 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4964 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4965 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4966 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4967 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4968 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4969 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4970 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4971 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4972 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4973 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4974 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4975 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4976 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4977 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4978 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4979 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4980 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4981 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4982 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
4983 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
4984 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
4985 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
4986 }
4987}
4988
4989static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach04945c42011-12-02 00:35:16 +00004990 switch(Opc) {
4991 default: assert(0 && "unexpected opcode!");
Jim Grosbachdda976b2011-12-02 22:01:52 +00004992 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
4993 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
4994 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
4995 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
4996 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
4997 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
4998 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
4999 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
5000 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
5001 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
5002 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
5003 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
5004 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
5005 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
5006 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
5007 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
5008 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
5009 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
5010 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
5011 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
5012 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
5013 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
5014 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
5015 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
5016 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
5017 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
5018 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
5019 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
5020 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
5021 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
5022 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
5023 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005024 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
5025 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
5026 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
5027 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
5028 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbachdda976b2011-12-02 22:01:52 +00005029 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
5030 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
5031 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
5032 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
5033 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005034 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
5035 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
5036 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
5037 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
5038 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
5039 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005040 }
5041}
5042
Jim Grosbachafad0532011-11-10 23:42:14 +00005043bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005044processInstruction(MCInst &Inst,
5045 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5046 switch (Inst.getOpcode()) {
Jim Grosbacheb538222011-12-02 22:34:51 +00005047 // Handle NEON VST1 complex aliases.
5048 case ARM::VST1LNdWB_register_Asm_8:
5049 case ARM::VST1LNdWB_register_Asm_P8:
5050 case ARM::VST1LNdWB_register_Asm_I8:
5051 case ARM::VST1LNdWB_register_Asm_S8:
5052 case ARM::VST1LNdWB_register_Asm_U8:
5053 case ARM::VST1LNdWB_register_Asm_16:
5054 case ARM::VST1LNdWB_register_Asm_P16:
5055 case ARM::VST1LNdWB_register_Asm_I16:
5056 case ARM::VST1LNdWB_register_Asm_S16:
5057 case ARM::VST1LNdWB_register_Asm_U16:
5058 case ARM::VST1LNdWB_register_Asm_32:
5059 case ARM::VST1LNdWB_register_Asm_F:
5060 case ARM::VST1LNdWB_register_Asm_F32:
5061 case ARM::VST1LNdWB_register_Asm_I32:
5062 case ARM::VST1LNdWB_register_Asm_S32:
5063 case ARM::VST1LNdWB_register_Asm_U32: {
5064 MCInst TmpInst;
5065 // Shuffle the operands around so the lane index operand is in the
5066 // right place.
5067 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5068 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5069 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5070 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5071 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5072 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5073 TmpInst.addOperand(Inst.getOperand(1)); // lane
5074 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5075 TmpInst.addOperand(Inst.getOperand(6));
5076 Inst = TmpInst;
5077 return true;
5078 }
5079 case ARM::VST1LNdWB_fixed_Asm_8:
5080 case ARM::VST1LNdWB_fixed_Asm_P8:
5081 case ARM::VST1LNdWB_fixed_Asm_I8:
5082 case ARM::VST1LNdWB_fixed_Asm_S8:
5083 case ARM::VST1LNdWB_fixed_Asm_U8:
5084 case ARM::VST1LNdWB_fixed_Asm_16:
5085 case ARM::VST1LNdWB_fixed_Asm_P16:
5086 case ARM::VST1LNdWB_fixed_Asm_I16:
5087 case ARM::VST1LNdWB_fixed_Asm_S16:
5088 case ARM::VST1LNdWB_fixed_Asm_U16:
5089 case ARM::VST1LNdWB_fixed_Asm_32:
5090 case ARM::VST1LNdWB_fixed_Asm_F:
5091 case ARM::VST1LNdWB_fixed_Asm_F32:
5092 case ARM::VST1LNdWB_fixed_Asm_I32:
5093 case ARM::VST1LNdWB_fixed_Asm_S32:
5094 case ARM::VST1LNdWB_fixed_Asm_U32: {
5095 MCInst TmpInst;
5096 // Shuffle the operands around so the lane index operand is in the
5097 // right place.
5098 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5099 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5100 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5101 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5102 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5103 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5104 TmpInst.addOperand(Inst.getOperand(1)); // lane
5105 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5106 TmpInst.addOperand(Inst.getOperand(5));
5107 Inst = TmpInst;
5108 return true;
5109 }
5110 case ARM::VST1LNdAsm_8:
5111 case ARM::VST1LNdAsm_P8:
5112 case ARM::VST1LNdAsm_I8:
5113 case ARM::VST1LNdAsm_S8:
5114 case ARM::VST1LNdAsm_U8:
5115 case ARM::VST1LNdAsm_16:
5116 case ARM::VST1LNdAsm_P16:
5117 case ARM::VST1LNdAsm_I16:
5118 case ARM::VST1LNdAsm_S16:
5119 case ARM::VST1LNdAsm_U16:
5120 case ARM::VST1LNdAsm_32:
5121 case ARM::VST1LNdAsm_F:
5122 case ARM::VST1LNdAsm_F32:
5123 case ARM::VST1LNdAsm_I32:
5124 case ARM::VST1LNdAsm_S32:
5125 case ARM::VST1LNdAsm_U32: {
5126 MCInst TmpInst;
5127 // Shuffle the operands around so the lane index operand is in the
5128 // right place.
5129 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5130 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5131 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5132 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5133 TmpInst.addOperand(Inst.getOperand(1)); // lane
5134 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5135 TmpInst.addOperand(Inst.getOperand(5));
5136 Inst = TmpInst;
5137 return true;
5138 }
Jim Grosbach04945c42011-12-02 00:35:16 +00005139 // Handle NEON VLD1 complex aliases.
Jim Grosbachdda976b2011-12-02 22:01:52 +00005140 case ARM::VLD1LNdWB_register_Asm_8:
5141 case ARM::VLD1LNdWB_register_Asm_P8:
5142 case ARM::VLD1LNdWB_register_Asm_I8:
5143 case ARM::VLD1LNdWB_register_Asm_S8:
5144 case ARM::VLD1LNdWB_register_Asm_U8:
5145 case ARM::VLD1LNdWB_register_Asm_16:
5146 case ARM::VLD1LNdWB_register_Asm_P16:
5147 case ARM::VLD1LNdWB_register_Asm_I16:
5148 case ARM::VLD1LNdWB_register_Asm_S16:
5149 case ARM::VLD1LNdWB_register_Asm_U16:
5150 case ARM::VLD1LNdWB_register_Asm_32:
5151 case ARM::VLD1LNdWB_register_Asm_F:
5152 case ARM::VLD1LNdWB_register_Asm_F32:
5153 case ARM::VLD1LNdWB_register_Asm_I32:
5154 case ARM::VLD1LNdWB_register_Asm_S32:
5155 case ARM::VLD1LNdWB_register_Asm_U32: {
5156 MCInst TmpInst;
5157 // Shuffle the operands around so the lane index operand is in the
5158 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005159 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005160 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5161 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5162 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5163 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5164 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5165 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5166 TmpInst.addOperand(Inst.getOperand(1)); // lane
5167 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5168 TmpInst.addOperand(Inst.getOperand(6));
5169 Inst = TmpInst;
5170 return true;
5171 }
5172 case ARM::VLD1LNdWB_fixed_Asm_8:
5173 case ARM::VLD1LNdWB_fixed_Asm_P8:
5174 case ARM::VLD1LNdWB_fixed_Asm_I8:
5175 case ARM::VLD1LNdWB_fixed_Asm_S8:
5176 case ARM::VLD1LNdWB_fixed_Asm_U8:
5177 case ARM::VLD1LNdWB_fixed_Asm_16:
5178 case ARM::VLD1LNdWB_fixed_Asm_P16:
5179 case ARM::VLD1LNdWB_fixed_Asm_I16:
5180 case ARM::VLD1LNdWB_fixed_Asm_S16:
5181 case ARM::VLD1LNdWB_fixed_Asm_U16:
5182 case ARM::VLD1LNdWB_fixed_Asm_32:
5183 case ARM::VLD1LNdWB_fixed_Asm_F:
5184 case ARM::VLD1LNdWB_fixed_Asm_F32:
5185 case ARM::VLD1LNdWB_fixed_Asm_I32:
5186 case ARM::VLD1LNdWB_fixed_Asm_S32:
5187 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5188 MCInst TmpInst;
5189 // Shuffle the operands around so the lane index operand is in the
5190 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005191 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005192 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5193 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5194 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5195 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5196 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5197 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5198 TmpInst.addOperand(Inst.getOperand(1)); // lane
5199 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5200 TmpInst.addOperand(Inst.getOperand(5));
5201 Inst = TmpInst;
5202 return true;
5203 }
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005204 case ARM::VLD1LNdAsm_8:
5205 case ARM::VLD1LNdAsm_P8:
5206 case ARM::VLD1LNdAsm_I8:
5207 case ARM::VLD1LNdAsm_S8:
5208 case ARM::VLD1LNdAsm_U8:
5209 case ARM::VLD1LNdAsm_16:
5210 case ARM::VLD1LNdAsm_P16:
5211 case ARM::VLD1LNdAsm_I16:
5212 case ARM::VLD1LNdAsm_S16:
5213 case ARM::VLD1LNdAsm_U16:
5214 case ARM::VLD1LNdAsm_32:
5215 case ARM::VLD1LNdAsm_F:
5216 case ARM::VLD1LNdAsm_F32:
5217 case ARM::VLD1LNdAsm_I32:
5218 case ARM::VLD1LNdAsm_S32:
5219 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005220 MCInst TmpInst;
5221 // Shuffle the operands around so the lane index operand is in the
5222 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005223 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach04945c42011-12-02 00:35:16 +00005224 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5225 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5226 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5227 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5228 TmpInst.addOperand(Inst.getOperand(1)); // lane
5229 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5230 TmpInst.addOperand(Inst.getOperand(5));
5231 Inst = TmpInst;
5232 return true;
5233 }
Jim Grosbach61db5a52011-11-10 16:44:55 +00005234 // Handle the MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005235 case ARM::ASRr:
5236 case ARM::LSRr:
5237 case ARM::LSLr:
5238 case ARM::RORr: {
5239 ARM_AM::ShiftOpc ShiftTy;
5240 switch(Inst.getOpcode()) {
5241 default: llvm_unreachable("unexpected opcode!");
5242 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5243 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5244 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5245 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5246 }
5247 // A shift by zero is a plain MOVr, not a MOVsi.
5248 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5249 MCInst TmpInst;
5250 TmpInst.setOpcode(ARM::MOVsr);
5251 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5252 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5253 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5254 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5255 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5256 TmpInst.addOperand(Inst.getOperand(4));
5257 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5258 Inst = TmpInst;
5259 return true;
5260 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005261 case ARM::ASRi:
5262 case ARM::LSRi:
5263 case ARM::LSLi:
5264 case ARM::RORi: {
5265 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005266 switch(Inst.getOpcode()) {
5267 default: llvm_unreachable("unexpected opcode!");
5268 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5269 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5270 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5271 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5272 }
5273 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005274 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005275 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5276 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005277 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005278 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005279 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5280 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005281 if (Opc == ARM::MOVsi)
5282 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005283 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5284 TmpInst.addOperand(Inst.getOperand(4));
5285 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5286 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005287 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005288 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005289 case ARM::RRXi: {
5290 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5291 MCInst TmpInst;
5292 TmpInst.setOpcode(ARM::MOVsi);
5293 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5294 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5295 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5296 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5297 TmpInst.addOperand(Inst.getOperand(3));
5298 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5299 Inst = TmpInst;
5300 return true;
5301 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005302 case ARM::t2LDMIA_UPD: {
5303 // If this is a load of a single register, then we should use
5304 // a post-indexed LDR instruction instead, per the ARM ARM.
5305 if (Inst.getNumOperands() != 5)
5306 return false;
5307 MCInst TmpInst;
5308 TmpInst.setOpcode(ARM::t2LDR_POST);
5309 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5310 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5311 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5312 TmpInst.addOperand(MCOperand::CreateImm(4));
5313 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5314 TmpInst.addOperand(Inst.getOperand(3));
5315 Inst = TmpInst;
5316 return true;
5317 }
5318 case ARM::t2STMDB_UPD: {
5319 // If this is a store of a single register, then we should use
5320 // a pre-indexed STR instruction instead, per the ARM ARM.
5321 if (Inst.getNumOperands() != 5)
5322 return false;
5323 MCInst TmpInst;
5324 TmpInst.setOpcode(ARM::t2STR_PRE);
5325 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5326 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5327 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5328 TmpInst.addOperand(MCOperand::CreateImm(-4));
5329 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5330 TmpInst.addOperand(Inst.getOperand(3));
5331 Inst = TmpInst;
5332 return true;
5333 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005334 case ARM::LDMIA_UPD:
5335 // If this is a load of a single register via a 'pop', then we should use
5336 // a post-indexed LDR instruction instead, per the ARM ARM.
5337 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5338 Inst.getNumOperands() == 5) {
5339 MCInst TmpInst;
5340 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5341 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5342 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5343 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5344 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5345 TmpInst.addOperand(MCOperand::CreateImm(4));
5346 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5347 TmpInst.addOperand(Inst.getOperand(3));
5348 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005349 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005350 }
5351 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005352 case ARM::STMDB_UPD:
5353 // If this is a store of a single register via a 'push', then we should use
5354 // a pre-indexed STR instruction instead, per the ARM ARM.
5355 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5356 Inst.getNumOperands() == 5) {
5357 MCInst TmpInst;
5358 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5359 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5360 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5361 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5362 TmpInst.addOperand(MCOperand::CreateImm(-4));
5363 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5364 TmpInst.addOperand(Inst.getOperand(3));
5365 Inst = TmpInst;
5366 }
5367 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005368 case ARM::t2ADDri12:
5369 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5370 // mnemonic was used (not "addw"), encoding T3 is preferred.
5371 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5372 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5373 break;
5374 Inst.setOpcode(ARM::t2ADDri);
5375 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5376 break;
5377 case ARM::t2SUBri12:
5378 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5379 // mnemonic was used (not "subw"), encoding T3 is preferred.
5380 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5381 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5382 break;
5383 Inst.setOpcode(ARM::t2SUBri);
5384 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5385 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005386 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005387 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5388 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5389 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5390 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005391 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005392 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005393 return true;
5394 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005395 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005396 case ARM::tSUBi8:
5397 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5398 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5399 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5400 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005401 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005402 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005403 return true;
5404 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005405 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00005406 case ARM::t2ADDrr: {
5407 // If the destination and first source operand are the same, and
5408 // there's no setting of the flags, use encoding T2 instead of T3.
5409 // Note that this is only for ADD, not SUB. This mirrors the system
5410 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5411 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5412 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00005413 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5414 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00005415 break;
5416 MCInst TmpInst;
5417 TmpInst.setOpcode(ARM::tADDhirr);
5418 TmpInst.addOperand(Inst.getOperand(0));
5419 TmpInst.addOperand(Inst.getOperand(0));
5420 TmpInst.addOperand(Inst.getOperand(2));
5421 TmpInst.addOperand(Inst.getOperand(3));
5422 TmpInst.addOperand(Inst.getOperand(4));
5423 Inst = TmpInst;
5424 return true;
5425 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005426 case ARM::tB:
5427 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005428 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005429 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005430 return true;
5431 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005432 break;
5433 case ARM::t2B:
5434 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005435 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005436 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005437 return true;
5438 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005439 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00005440 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005441 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00005442 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00005443 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00005444 return true;
5445 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00005446 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005447 case ARM::tBcc:
5448 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00005449 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005450 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00005451 return true;
5452 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00005453 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005454 case ARM::tLDMIA: {
5455 // If the register list contains any high registers, or if the writeback
5456 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5457 // instead if we're in Thumb2. Otherwise, this should have generated
5458 // an error in validateInstruction().
5459 unsigned Rn = Inst.getOperand(0).getReg();
5460 bool hasWritebackToken =
5461 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5462 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5463 bool listContainsBase;
5464 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5465 (!listContainsBase && !hasWritebackToken) ||
5466 (listContainsBase && hasWritebackToken)) {
5467 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5468 assert (isThumbTwo());
5469 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5470 // If we're switching to the updating version, we need to insert
5471 // the writeback tied operand.
5472 if (hasWritebackToken)
5473 Inst.insert(Inst.begin(),
5474 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00005475 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005476 }
5477 break;
5478 }
Jim Grosbach099c9762011-09-16 20:50:13 +00005479 case ARM::tSTMIA_UPD: {
5480 // If the register list contains any high registers, we need to use
5481 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5482 // should have generated an error in validateInstruction().
5483 unsigned Rn = Inst.getOperand(0).getReg();
5484 bool listContainsBase;
5485 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5486 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5487 assert (isThumbTwo());
5488 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00005489 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00005490 }
5491 break;
5492 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005493 case ARM::tPOP: {
5494 bool listContainsBase;
5495 // If the register list contains any high registers, we need to use
5496 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5497 // should have generated an error in validateInstruction().
5498 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005499 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005500 assert (isThumbTwo());
5501 Inst.setOpcode(ARM::t2LDMIA_UPD);
5502 // Add the base register and writeback operands.
5503 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5504 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005505 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005506 }
5507 case ARM::tPUSH: {
5508 bool listContainsBase;
5509 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005510 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005511 assert (isThumbTwo());
5512 Inst.setOpcode(ARM::t2STMDB_UPD);
5513 // Add the base register and writeback operands.
5514 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5515 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005516 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005517 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005518 case ARM::t2MOVi: {
5519 // If we can use the 16-bit encoding and the user didn't explicitly
5520 // request the 32-bit variant, transform it here.
5521 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5522 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00005523 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5524 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5525 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005526 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5527 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5528 // The operands aren't in the same order for tMOVi8...
5529 MCInst TmpInst;
5530 TmpInst.setOpcode(ARM::tMOVi8);
5531 TmpInst.addOperand(Inst.getOperand(0));
5532 TmpInst.addOperand(Inst.getOperand(4));
5533 TmpInst.addOperand(Inst.getOperand(1));
5534 TmpInst.addOperand(Inst.getOperand(2));
5535 TmpInst.addOperand(Inst.getOperand(3));
5536 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005537 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005538 }
5539 break;
5540 }
5541 case ARM::t2MOVr: {
5542 // If we can use the 16-bit encoding and the user didn't explicitly
5543 // request the 32-bit variant, transform it here.
5544 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5545 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5546 Inst.getOperand(2).getImm() == ARMCC::AL &&
5547 Inst.getOperand(4).getReg() == ARM::CPSR &&
5548 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5549 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5550 // The operands aren't the same for tMOV[S]r... (no cc_out)
5551 MCInst TmpInst;
5552 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5553 TmpInst.addOperand(Inst.getOperand(0));
5554 TmpInst.addOperand(Inst.getOperand(1));
5555 TmpInst.addOperand(Inst.getOperand(2));
5556 TmpInst.addOperand(Inst.getOperand(3));
5557 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005558 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005559 }
5560 break;
5561 }
Jim Grosbach82213192011-09-19 20:29:33 +00005562 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00005563 case ARM::t2SXTB:
5564 case ARM::t2UXTH:
5565 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00005566 // If we can use the 16-bit encoding and the user didn't explicitly
5567 // request the 32-bit variant, transform it here.
5568 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5569 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5570 Inst.getOperand(2).getImm() == 0 &&
5571 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5572 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00005573 unsigned NewOpc;
5574 switch (Inst.getOpcode()) {
5575 default: llvm_unreachable("Illegal opcode!");
5576 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5577 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5578 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5579 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5580 }
Jim Grosbach82213192011-09-19 20:29:33 +00005581 // The operands aren't the same for thumb1 (no rotate operand).
5582 MCInst TmpInst;
5583 TmpInst.setOpcode(NewOpc);
5584 TmpInst.addOperand(Inst.getOperand(0));
5585 TmpInst.addOperand(Inst.getOperand(1));
5586 TmpInst.addOperand(Inst.getOperand(3));
5587 TmpInst.addOperand(Inst.getOperand(4));
5588 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005589 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00005590 }
5591 break;
5592 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005593 case ARM::t2IT: {
5594 // The mask bits for all but the first condition are represented as
5595 // the low bit of the condition code value implies 't'. We currently
5596 // always have 1 implies 't', so XOR toggle the bits if the low bit
5597 // of the condition code is zero. The encoding also expects the low
5598 // bit of the condition to be encoded as bit 4 of the mask operand,
5599 // so mask that in if needed
5600 MCOperand &MO = Inst.getOperand(1);
5601 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00005602 unsigned OrigMask = Mask;
5603 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005604 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005605 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5606 for (unsigned i = 3; i != TZ; --i)
5607 Mask ^= 1 << i;
5608 } else
5609 Mask |= 0x10;
5610 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00005611
5612 // Set up the IT block state according to the IT instruction we just
5613 // matched.
5614 assert(!inITBlock() && "nested IT blocks?!");
5615 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5616 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5617 ITState.CurPosition = 0;
5618 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005619 break;
5620 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005621 }
Jim Grosbachafad0532011-11-10 23:42:14 +00005622 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005623}
5624
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005625unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5626 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5627 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005628 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005629 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005630 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5631 assert(MCID.hasOptionalDef() &&
5632 "optionally flag setting instruction missing optional def operand");
5633 assert(MCID.NumOperands == Inst.getNumOperands() &&
5634 "operand count mismatch!");
5635 // Find the optional-def operand (cc_out).
5636 unsigned OpNo;
5637 for (OpNo = 0;
5638 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5639 ++OpNo)
5640 ;
5641 // If we're parsing Thumb1, reject it completely.
5642 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5643 return Match_MnemonicFail;
5644 // If we're parsing Thumb2, which form is legal depends on whether we're
5645 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005646 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5647 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005648 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00005649 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5650 inITBlock())
5651 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005652 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005653 // Some high-register supporting Thumb1 encodings only allow both registers
5654 // to be from r0-r7 when in Thumb2.
5655 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5656 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5657 isARMLowRegister(Inst.getOperand(2).getReg()))
5658 return Match_RequiresThumb2;
5659 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00005660 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005661 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5662 isARMLowRegister(Inst.getOperand(1).getReg()))
5663 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005664 return Match_Success;
5665}
5666
Chris Lattner9487de62010-10-28 21:28:01 +00005667bool ARMAsmParser::
5668MatchAndEmitInstruction(SMLoc IDLoc,
5669 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5670 MCStreamer &Out) {
5671 MCInst Inst;
5672 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00005673 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00005674 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00005675 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00005676 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005677 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005678 // Context sensitive operand constraints aren't handled by the matcher,
5679 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005680 if (validateInstruction(Inst, Operands)) {
5681 // Still progress the IT block, otherwise one wrong condition causes
5682 // nasty cascading errors.
5683 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005684 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005685 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005686
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005687 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00005688 // encoding is selected. Loop on it while changes happen so the
5689 // individual transformations can chain off each other. E.g.,
5690 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5691 while (processInstruction(Inst, Operands))
5692 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005693
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005694 // Only move forward at the very end so that everything in validate
5695 // and process gets a consistent answer about whether we're in an IT
5696 // block.
5697 forwardITPosition();
5698
Chris Lattner9487de62010-10-28 21:28:01 +00005699 Out.EmitInstruction(Inst);
5700 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005701 case Match_MissingFeature:
5702 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5703 return true;
5704 case Match_InvalidOperand: {
5705 SMLoc ErrorLoc = IDLoc;
5706 if (ErrorInfo != ~0U) {
5707 if (ErrorInfo >= Operands.size())
5708 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00005709
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005710 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5711 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5712 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005713
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005714 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00005715 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005716 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005717 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00005718 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00005719 // The converter function will have already emited a diagnostic.
5720 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00005721 case Match_RequiresNotITBlock:
5722 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005723 case Match_RequiresITBlock:
5724 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005725 case Match_RequiresV6:
5726 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5727 case Match_RequiresThumb2:
5728 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005729 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005730
Eric Christopher91d7b902010-10-29 09:26:59 +00005731 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00005732 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00005733}
5734
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005735/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00005736bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5737 StringRef IDVal = DirectiveID.getIdentifier();
5738 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005739 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005740 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005741 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00005742 else if (IDVal == ".arm")
5743 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005744 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005745 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005746 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005747 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005748 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005749 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00005750 return true;
5751}
5752
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005753/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00005754/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005755bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00005756 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5757 for (;;) {
5758 const MCExpr *Value;
5759 if (getParser().ParseExpression(Value))
5760 return true;
5761
Chris Lattnerc35681b2010-01-19 19:46:13 +00005762 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00005763
5764 if (getLexer().is(AsmToken::EndOfStatement))
5765 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00005766
Kevin Enderbyccab3172009-09-15 00:27:25 +00005767 // FIXME: Improve diagnostic.
5768 if (getLexer().isNot(AsmToken::Comma))
5769 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005770 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005771 }
5772 }
5773
Sean Callanana83fd7d2010-01-19 20:27:46 +00005774 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005775 return false;
5776}
5777
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005778/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00005779/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005780bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00005781 if (getLexer().isNot(AsmToken::EndOfStatement))
5782 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005783 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005784
Jim Grosbach7f882392011-12-07 18:04:19 +00005785 if (!isThumb())
5786 SwitchMode();
5787 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5788 return false;
5789}
5790
5791/// parseDirectiveARM
5792/// ::= .arm
5793bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5794 if (getLexer().isNot(AsmToken::EndOfStatement))
5795 return Error(L, "unexpected token in directive");
5796 Parser.Lex();
5797
5798 if (isThumb())
5799 SwitchMode();
5800 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00005801 return false;
5802}
5803
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005804/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00005805/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005806bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005807 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5808 bool isMachO = MAI.hasSubsectionsViaSymbols();
5809 StringRef Name;
5810
5811 // Darwin asm has function name after .thumb_func direction
5812 // ELF doesn't
5813 if (isMachO) {
5814 const AsmToken &Tok = Parser.getTok();
5815 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5816 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00005817 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005818 Parser.Lex(); // Consume the identifier token.
5819 }
5820
Jim Grosbach42ba6282011-11-10 20:48:53 +00005821 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00005822 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005823 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005824
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005825 // FIXME: assuming function name will be the line following .thumb_func
5826 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00005827 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00005828 }
5829
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00005830 // Mark symbol as a thumb symbol.
5831 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5832 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00005833 return false;
5834}
5835
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005836/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00005837/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005838bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005839 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005840 if (Tok.isNot(AsmToken::Identifier))
5841 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00005842 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00005843 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00005844 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005845 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00005846 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00005847 else
5848 return Error(L, "unrecognized syntax mode in .syntax directive");
5849
5850 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005851 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005852 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005853
5854 // TODO tell the MC streamer the mode
5855 // getParser().getStreamer().Emit???();
5856 return false;
5857}
5858
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005859/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00005860/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005861bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00005862 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005863 if (Tok.isNot(AsmToken::Integer))
5864 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00005865 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00005866 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005867 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00005868 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00005869 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005870 else
5871 return Error(L, "invalid operand to .code directive");
5872
5873 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00005874 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00005875 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00005876
Evan Cheng284b4672011-07-08 22:36:29 +00005877 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005878 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005879 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005880 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00005881 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00005882 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00005883 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00005884 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00005885 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00005886
Kevin Enderby146dcf22009-10-15 20:48:48 +00005887 return false;
5888}
5889
Sean Callanan643a5572010-04-07 20:29:34 +00005890extern "C" void LLVMInitializeARMAsmLexer();
5891
Kevin Enderby8be42bd2009-10-30 22:55:57 +00005892/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00005893extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00005894 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5895 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00005896 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00005897}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005898
Chris Lattner3e4582a2010-09-06 19:11:01 +00005899#define GET_REGISTER_MATCHER
5900#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00005901#include "ARMGenAsmMatcher.inc"