blob: ac7532bad450cda8ad9521e7cfc842c31fc15d7b [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 Grosbachab5830e2011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbached16ec42011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbached16ec42011-08-29 22:24:09 +000079
80
Kevin Enderbyccab3172009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach7f882392011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbachab5830e2011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +0000104
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000105 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000106 bool &CarrySetting, unsigned &ProcessorIMod,
107 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000108 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000109 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000110
Evan Cheng4d1ca962011-07-08 01:53:10 +0000111 bool isThumb() const {
112 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000113 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000114 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000115 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000116 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000117 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000118 bool isThumbTwo() const {
119 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
120 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000121 bool hasV6Ops() const {
122 return STI.getFeatureBits() & ARM::HasV6Ops;
123 }
James Molloy21efa7d2011-09-28 14:21:38 +0000124 bool hasV7Ops() const {
125 return STI.getFeatureBits() & ARM::HasV7Ops;
126 }
Evan Cheng284b4672011-07-08 22:36:29 +0000127 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000128 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
129 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000130 }
James Molloy21efa7d2011-09-28 14:21:38 +0000131 bool isMClass() const {
132 return STI.getFeatureBits() & ARM::FeatureMClass;
133 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000134
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000135 /// @name Auto-generated Match Functions
136 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000137
Chris Lattner3e4582a2010-09-06 19:11:01 +0000138#define GET_ASSEMBLER_HEADER
139#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000140
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000141 /// }
142
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000143 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000144 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000148 OperandMatchResultTy parseCoprocOptionOperand(
149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000150 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000152 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000154 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000156 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
157 StringRef Op, int Low, int High);
158 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
159 return parsePKHImm(O, "lsl", 0, 31);
160 }
161 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
162 return parsePKHImm(O, "asr", 1, 32);
163 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000164 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000165 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000166 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000167 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000168 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000169 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000170 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000171 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach04945c42011-12-02 00:35:16 +0000172 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000173
174 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000175 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
177 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000179 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000181 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000183 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000185 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000187 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000189 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000191 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000193 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
195 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000201 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000203 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000205 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000207 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach3ea06572011-10-24 22:16:58 +0000209 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
211 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach05df4602011-10-31 21:50:31 +0000213 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
215 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000217
218 bool validateInstruction(MCInst &Inst,
219 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachafad0532011-11-10 23:42:14 +0000220 bool processInstruction(MCInst &Inst,
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000222 bool shouldOmitCCOutOperand(StringRef Mnemonic,
223 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000224
Kevin Enderbyccab3172009-09-15 00:27:25 +0000225public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000226 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000227 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000228 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000229 Match_RequiresV6,
230 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000231 };
232
Evan Cheng91111d22011-07-09 05:47:46 +0000233 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000234 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000235 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000236
Evan Cheng4d1ca962011-07-08 01:53:10 +0000237 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000238 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000239
240 // Not in an ITBlock to start with.
241 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000242 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000243
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000244 // Implementation of the MCTargetAsmParser interface:
245 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
246 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000247 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000248 bool ParseDirective(AsmToken DirectiveID);
249
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000250 unsigned checkTargetMatchPredicate(MCInst &Inst);
251
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000252 bool MatchAndEmitInstruction(SMLoc IDLoc,
253 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
254 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000255};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000256} // end anonymous namespace
257
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000258namespace {
259
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000260/// ARMOperand - Instances of this class represent a parsed ARM machine
261/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000262class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000263 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000264 k_CondCode,
265 k_CCOut,
266 k_ITCondMask,
267 k_CoprocNum,
268 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000269 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000270 k_Immediate,
271 k_FPImmediate,
272 k_MemBarrierOpt,
273 k_Memory,
274 k_PostIndexRegister,
275 k_MSRMask,
276 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000277 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000278 k_Register,
279 k_RegisterList,
280 k_DPRRegisterList,
281 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000282 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000283 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000284 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000285 k_ShiftedRegister,
286 k_ShiftedImmediate,
287 k_ShifterImmediate,
288 k_RotateImmediate,
289 k_BitfieldDescriptor,
290 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000291 } Kind;
292
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000293 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000294 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000295
296 union {
297 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000298 ARMCC::CondCodes Val;
299 } CC;
300
301 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000302 unsigned Val;
303 } Cop;
304
305 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000306 unsigned Val;
307 } CoprocOption;
308
309 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000310 unsigned Mask:4;
311 } ITMask;
312
313 struct {
314 ARM_MB::MemBOpt Val;
315 } MBOpt;
316
317 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000318 ARM_PROC::IFlags Val;
319 } IFlags;
320
321 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000322 unsigned Val;
323 } MMask;
324
325 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000326 const char *Data;
327 unsigned Length;
328 } Tok;
329
330 struct {
331 unsigned RegNum;
332 } Reg;
333
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000334 // A vector register list is a sequential list of 1 to 4 registers.
335 struct {
336 unsigned RegNum;
337 unsigned Count;
Jim Grosbach04945c42011-12-02 00:35:16 +0000338 unsigned LaneIndex;
Jim Grosbach2f50e922011-12-15 21:44:33 +0000339 bool isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000340 } VectorList;
341
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000342 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000343 unsigned Val;
344 } VectorIndex;
345
346 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000347 const MCExpr *Val;
348 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000349
Jim Grosbache7fbce72011-10-03 23:38:36 +0000350 struct {
351 unsigned Val; // encoded 8-bit representation
352 } FPImm;
353
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000354 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000355 struct {
356 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000357 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
358 // was specified.
359 const MCConstantExpr *OffsetImm; // Offset immediate value
360 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
361 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000362 unsigned ShiftImm; // shift for OffsetReg.
363 unsigned Alignment; // 0 = no alignment specified
Jim Grosbachcef98cd2011-12-19 18:31:43 +0000364 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000365 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000366 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000367
368 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000369 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000370 bool isAdd;
371 ARM_AM::ShiftOpc ShiftTy;
372 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000373 } PostIdxReg;
374
375 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000376 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000377 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000378 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000379 struct {
380 ARM_AM::ShiftOpc ShiftTy;
381 unsigned SrcReg;
382 unsigned ShiftReg;
383 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000384 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000385 struct {
386 ARM_AM::ShiftOpc ShiftTy;
387 unsigned SrcReg;
388 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000389 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000390 struct {
391 unsigned Imm;
392 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000393 struct {
394 unsigned LSB;
395 unsigned Width;
396 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000397 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000398
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000399 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
400public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000401 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
402 Kind = o.Kind;
403 StartLoc = o.StartLoc;
404 EndLoc = o.EndLoc;
405 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000407 CC = o.CC;
408 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000409 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000410 ITMask = o.ITMask;
411 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000412 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000413 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000414 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000415 case k_CCOut:
416 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000417 Reg = o.Reg;
418 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000419 case k_RegisterList:
420 case k_DPRRegisterList:
421 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000422 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000423 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000424 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000425 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000426 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000427 VectorList = o.VectorList;
428 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000429 case k_CoprocNum:
430 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000431 Cop = o.Cop;
432 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000433 case k_CoprocOption:
434 CoprocOption = o.CoprocOption;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000437 Imm = o.Imm;
438 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000439 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000440 FPImm = o.FPImm;
441 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000442 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000443 MBOpt = o.MBOpt;
444 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000445 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000446 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000447 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000448 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000449 PostIdxReg = o.PostIdxReg;
450 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000452 MMask = o.MMask;
453 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000454 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000455 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000456 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000457 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000458 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000459 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000460 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000461 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000462 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000463 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000464 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000465 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000466 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000467 RotImm = o.RotImm;
468 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000469 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000470 Bitfield = o.Bitfield;
471 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000472 case k_VectorIndex:
473 VectorIndex = o.VectorIndex;
474 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000475 }
476 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000477
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000478 /// getStartLoc - Get the location of the first token of this operand.
479 SMLoc getStartLoc() const { return StartLoc; }
480 /// getEndLoc - Get the location of the last token of this operand.
481 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000482
Daniel Dunbard8042b72010-08-11 06:36:53 +0000483 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000484 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000485 return CC.Val;
486 }
487
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000488 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000489 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000490 return Cop.Val;
491 }
492
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000493 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000494 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000495 return StringRef(Tok.Data, Tok.Length);
496 }
497
498 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000499 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000500 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000501 }
502
Bill Wendlingbed94652010-11-09 23:28:44 +0000503 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000504 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
505 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000506 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000507 }
508
Kevin Enderbyf5079942009-10-13 22:19:02 +0000509 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000510 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000511 return Imm.Val;
512 }
513
Jim Grosbache7fbce72011-10-03 23:38:36 +0000514 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000515 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000516 return FPImm.Val;
517 }
518
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000519 unsigned getVectorIndex() const {
520 assert(Kind == k_VectorIndex && "Invalid access!");
521 return VectorIndex.Val;
522 }
523
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000524 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000525 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000526 return MBOpt.Val;
527 }
528
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000529 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000530 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000531 return IFlags.Val;
532 }
533
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000534 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000535 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000536 return MMask.Val;
537 }
538
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000539 bool isCoprocNum() const { return Kind == k_CoprocNum; }
540 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000541 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000542 bool isCondCode() const { return Kind == k_CondCode; }
543 bool isCCOut() const { return Kind == k_CCOut; }
544 bool isITMask() const { return Kind == k_ITCondMask; }
545 bool isITCondCode() const { return Kind == k_CondCode; }
546 bool isImm() const { return Kind == k_Immediate; }
547 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000548 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000549 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000550 return false;
551 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
552 if (!CE) return false;
553 int64_t Value = CE->getValue();
554 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
555 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000556 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000557 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000558 return false;
559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
560 if (!CE) return false;
561 int64_t Value = CE->getValue();
562 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
563 }
564 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000565 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000566 return false;
567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
568 if (!CE) return false;
569 int64_t Value = CE->getValue();
570 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
571 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000572 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000573 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000574 return false;
575 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
576 if (!CE) return false;
577 int64_t Value = CE->getValue();
578 return Value >= 0 && Value < 256;
579 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000580 bool isImm0_1() const {
581 if (Kind != k_Immediate)
582 return false;
583 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
584 if (!CE) return false;
585 int64_t Value = CE->getValue();
586 return Value >= 0 && Value < 2;
587 }
588 bool isImm0_3() const {
589 if (Kind != k_Immediate)
590 return false;
591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
592 if (!CE) return false;
593 int64_t Value = CE->getValue();
594 return Value >= 0 && Value < 4;
595 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000596 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000597 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000598 return false;
599 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
600 if (!CE) return false;
601 int64_t Value = CE->getValue();
602 return Value >= 0 && Value < 8;
603 }
604 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000605 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000606 return false;
607 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
608 if (!CE) return false;
609 int64_t Value = CE->getValue();
610 return Value >= 0 && Value < 16;
611 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000612 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000613 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000614 return false;
615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value >= 0 && Value < 32;
619 }
Jim Grosbach00326402011-12-08 01:30:04 +0000620 bool isImm0_63() const {
621 if (Kind != k_Immediate)
622 return false;
623 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
624 if (!CE) return false;
625 int64_t Value = CE->getValue();
626 return Value >= 0 && Value < 64;
627 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000628 bool isImm8() const {
629 if (Kind != k_Immediate)
630 return false;
631 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
632 if (!CE) return false;
633 int64_t Value = CE->getValue();
634 return Value == 8;
635 }
636 bool isImm16() const {
637 if (Kind != k_Immediate)
638 return false;
639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
640 if (!CE) return false;
641 int64_t Value = CE->getValue();
642 return Value == 16;
643 }
644 bool isImm32() const {
645 if (Kind != k_Immediate)
646 return false;
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value == 32;
651 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000652 bool isShrImm8() const {
653 if (Kind != k_Immediate)
654 return false;
655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
656 if (!CE) return false;
657 int64_t Value = CE->getValue();
658 return Value > 0 && Value <= 8;
659 }
660 bool isShrImm16() const {
661 if (Kind != k_Immediate)
662 return false;
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return Value > 0 && Value <= 16;
667 }
668 bool isShrImm32() const {
669 if (Kind != k_Immediate)
670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return Value > 0 && Value <= 32;
675 }
676 bool isShrImm64() const {
677 if (Kind != k_Immediate)
678 return false;
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Value = CE->getValue();
682 return Value > 0 && Value <= 64;
683 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000684 bool isImm1_7() const {
685 if (Kind != k_Immediate)
686 return false;
687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return Value > 0 && Value < 8;
691 }
692 bool isImm1_15() const {
693 if (Kind != k_Immediate)
694 return false;
695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
696 if (!CE) return false;
697 int64_t Value = CE->getValue();
698 return Value > 0 && Value < 16;
699 }
700 bool isImm1_31() const {
701 if (Kind != k_Immediate)
702 return false;
703 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
704 if (!CE) return false;
705 int64_t Value = CE->getValue();
706 return Value > 0 && Value < 32;
707 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000708 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000709 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000710 return false;
711 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
712 if (!CE) return false;
713 int64_t Value = CE->getValue();
714 return Value > 0 && Value < 17;
715 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000716 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000717 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000718 return false;
719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
720 if (!CE) return false;
721 int64_t Value = CE->getValue();
722 return Value > 0 && Value < 33;
723 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000724 bool isImm0_32() const {
725 if (Kind != k_Immediate)
726 return false;
727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728 if (!CE) return false;
729 int64_t Value = CE->getValue();
730 return Value >= 0 && Value < 33;
731 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000732 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000733 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000734 return false;
735 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
736 if (!CE) return false;
737 int64_t Value = CE->getValue();
738 return Value >= 0 && Value < 65536;
739 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000740 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000741 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000742 return false;
743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 // If it's not a constant expression, it'll generate a fixup and be
745 // handled later.
746 if (!CE) return true;
747 int64_t Value = CE->getValue();
748 return Value >= 0 && Value < 65536;
749 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000750 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000751 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000752 return false;
753 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
754 if (!CE) return false;
755 int64_t Value = CE->getValue();
756 return Value >= 0 && Value <= 0xffffff;
757 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000758 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000759 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000760 return false;
761 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
762 if (!CE) return false;
763 int64_t Value = CE->getValue();
764 return Value > 0 && Value < 33;
765 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000766 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000767 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000768 return false;
769 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
770 if (!CE) return false;
771 int64_t Value = CE->getValue();
772 return Value >= 0 && Value < 32;
773 }
774 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000775 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000776 return false;
777 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
778 if (!CE) return false;
779 int64_t Value = CE->getValue();
780 return Value > 0 && Value <= 32;
781 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000782 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000783 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000784 return false;
785 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786 if (!CE) return false;
787 int64_t Value = CE->getValue();
788 return ARM_AM::getSOImmVal(Value) != -1;
789 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000790 bool isARMSOImmNot() const {
791 if (Kind != k_Immediate)
792 return false;
793 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
794 if (!CE) return false;
795 int64_t Value = CE->getValue();
796 return ARM_AM::getSOImmVal(~Value) != -1;
797 }
Jim Grosbach30506252011-12-08 00:31:07 +0000798 bool isARMSOImmNeg() const {
799 if (Kind != k_Immediate)
800 return false;
801 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
802 if (!CE) return false;
803 int64_t Value = CE->getValue();
804 return ARM_AM::getSOImmVal(-Value) != -1;
805 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000806 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000807 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000808 return false;
809 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
810 if (!CE) return false;
811 int64_t Value = CE->getValue();
812 return ARM_AM::getT2SOImmVal(Value) != -1;
813 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000814 bool isT2SOImmNot() const {
815 if (Kind != k_Immediate)
816 return false;
817 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
818 if (!CE) return false;
819 int64_t Value = CE->getValue();
820 return ARM_AM::getT2SOImmVal(~Value) != -1;
821 }
Jim Grosbach30506252011-12-08 00:31:07 +0000822 bool isT2SOImmNeg() const {
823 if (Kind != k_Immediate)
824 return false;
825 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
826 if (!CE) return false;
827 int64_t Value = CE->getValue();
828 return ARM_AM::getT2SOImmVal(-Value) != -1;
829 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000830 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000831 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000832 return false;
833 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
834 if (!CE) return false;
835 int64_t Value = CE->getValue();
836 return Value == 1 || Value == 0;
837 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000838 bool isReg() const { return Kind == k_Register; }
839 bool isRegList() const { return Kind == k_RegisterList; }
840 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
841 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
842 bool isToken() const { return Kind == k_Token; }
843 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
844 bool isMemory() const { return Kind == k_Memory; }
845 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
846 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
847 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
848 bool isRotImm() const { return Kind == k_RotateImmediate; }
849 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
850 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000851 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000852 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000853 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000854 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000855 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000856 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000857 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000858 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
859 (alignOK || Memory.Alignment == 0);
860 }
861 bool isAlignedMemory() const {
862 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000863 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000864 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000865 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000866 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000867 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000868 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000869 if (!Memory.OffsetImm) return true;
870 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000871 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000872 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000873 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000874 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000875 return false;
876 // Immediate offset in range [-4095, 4095].
877 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
878 if (!CE) return false;
879 int64_t Val = CE->getValue();
880 return Val > -4096 && Val < 4096;
881 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000882 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +0000883 // If we have an immediate that's not a constant, treat it as a label
884 // reference needing a fixup. If it is a constant, it's something else
885 // and we reject it.
886 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
887 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000888 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000889 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000890 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000891 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000892 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000893 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000894 if (!Memory.OffsetImm) return true;
895 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000896 return Val > -256 && Val < 256;
897 }
898 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000899 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000900 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000901 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000902 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
903 // Immediate offset in range [-255, 255].
904 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
905 if (!CE) return false;
906 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000907 // Special case, #-0 is INT32_MIN.
908 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000909 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000910 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000911 // If we have an immediate that's not a constant, treat it as a label
912 // reference needing a fixup. If it is a constant, it's something else
913 // and we reject it.
914 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
915 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000916 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000917 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000918 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000919 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000920 if (!Memory.OffsetImm) return true;
921 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000922 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000923 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000924 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000925 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000926 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000927 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000928 return false;
929 return true;
930 }
931 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000932 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000933 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
934 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000935 return false;
936 return true;
937 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000938 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000939 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000940 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000941 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000942 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000943 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000944 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
945 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000946 return false;
947 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000948 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000949 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000950 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000951 return false;
952 return true;
953 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000954 bool isMemThumbRR() const {
955 // Thumb reg+reg addressing is simple. Just two registers, a base and
956 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000957 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000958 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000959 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000960 return isARMLowRegister(Memory.BaseRegNum) &&
961 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000962 }
963 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000964 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000965 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000966 return false;
967 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000968 if (!Memory.OffsetImm) return true;
969 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000970 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
971 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000972 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000973 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000974 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000975 return false;
976 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000977 if (!Memory.OffsetImm) return true;
978 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000979 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
980 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000981 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000982 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000983 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000984 return false;
985 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000986 if (!Memory.OffsetImm) return true;
987 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000988 return Val >= 0 && Val <= 31;
989 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000990 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000991 if (!isMemory() || Memory.OffsetRegNum != 0 ||
992 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000993 return false;
994 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000995 if (!Memory.OffsetImm) return true;
996 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000997 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000998 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000999 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +00001000 // If we have an immediate that's not a constant, treat it as a label
1001 // reference needing a fixup. If it is a constant, it's something else
1002 // and we reject it.
1003 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
1004 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001005 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +00001006 return false;
1007 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001008 if (!Memory.OffsetImm) return true;
1009 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +00001010 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1011 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001012 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001013 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001014 return false;
1015 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001016 if (!Memory.OffsetImm) return true;
1017 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001018 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1019 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001020 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001021 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001022 return false;
1023 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001024 if (!Memory.OffsetImm) return true;
1025 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001026 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001027 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001028 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001029 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001030 return false;
1031 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001032 if (!Memory.OffsetImm) return true;
1033 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001034 return Val >= 0 && Val < 256;
1035 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001036 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001037 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001038 return false;
1039 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001040 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001041 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001042 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001043 }
1044 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001045 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001046 return false;
1047 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001048 if (!Memory.OffsetImm) return true;
1049 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001050 return (Val >= 0 && Val < 4096);
1051 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001052 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001053 // If we have an immediate that's not a constant, treat it as a label
1054 // reference needing a fixup. If it is a constant, it's something else
1055 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001056 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001057 return true;
1058
Jim Grosbacha95ec992011-10-11 17:29:55 +00001059 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001060 return false;
1061 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001062 if (!Memory.OffsetImm) return true;
1063 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001064 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001065 }
1066 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001067 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +00001068 return false;
1069 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1070 if (!CE) return false;
1071 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001072 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001073 }
Jim Grosbach93981412011-10-11 21:55:36 +00001074 bool isPostIdxImm8s4() const {
1075 if (Kind != k_Immediate)
1076 return false;
1077 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1078 if (!CE) return false;
1079 int64_t Val = CE->getValue();
1080 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1081 (Val == INT32_MIN);
1082 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001083
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001084 bool isMSRMask() const { return Kind == k_MSRMask; }
1085 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001086
Jim Grosbach741cd732011-10-17 22:26:03 +00001087 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001088 bool isSingleSpacedVectorList() const {
1089 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1090 }
1091 bool isDoubleSpacedVectorList() const {
1092 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1093 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001094 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001096 return VectorList.Count == 1;
1097 }
1098
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001099 bool isVecListTwoD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001100 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001101 return VectorList.Count == 2;
1102 }
1103
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001104 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001105 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001106 return VectorList.Count == 3;
1107 }
1108
Jim Grosbach846bcff2011-10-21 20:35:01 +00001109 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001110 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001111 return VectorList.Count == 4;
1112 }
1113
Jim Grosbach118b38c2011-10-21 22:21:10 +00001114 bool isVecListTwoQ() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001115 if (!isDoubleSpacedVectorList()) return false;
1116 return VectorList.Count == 2;
Jim Grosbach118b38c2011-10-21 22:21:10 +00001117 }
1118
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001119 bool isVecListOneDAllLanes() const {
1120 if (Kind != k_VectorListAllLanes) return false;
1121 return VectorList.Count == 1;
1122 }
1123
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001124 bool isVecListTwoDAllLanes() const {
1125 if (Kind != k_VectorListAllLanes) return false;
1126 return VectorList.Count == 2;
1127 }
1128
Jim Grosbach04945c42011-12-02 00:35:16 +00001129 bool isVecListOneDByteIndexed() const {
1130 if (Kind != k_VectorListIndexed) return false;
1131 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1132 }
1133
Jim Grosbachda511042011-12-14 23:35:06 +00001134 bool isVecListOneDHWordIndexed() const {
1135 if (Kind != k_VectorListIndexed) return false;
1136 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1137 }
1138
1139 bool isVecListOneDWordIndexed() const {
1140 if (Kind != k_VectorListIndexed) return false;
1141 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1142 }
1143
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001144 bool isVecListTwoDByteIndexed() const {
1145 if (Kind != k_VectorListIndexed) return false;
1146 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1147 }
1148
Jim Grosbachda511042011-12-14 23:35:06 +00001149 bool isVecListTwoDHWordIndexed() const {
1150 if (Kind != k_VectorListIndexed) return false;
1151 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1152 }
1153
1154 bool isVecListTwoDWordIndexed() const {
1155 if (Kind != k_VectorListIndexed) return false;
1156 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1157 }
1158
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001159 bool isVectorIndex8() const {
1160 if (Kind != k_VectorIndex) return false;
1161 return VectorIndex.Val < 8;
1162 }
1163 bool isVectorIndex16() const {
1164 if (Kind != k_VectorIndex) return false;
1165 return VectorIndex.Val < 4;
1166 }
1167 bool isVectorIndex32() const {
1168 if (Kind != k_VectorIndex) return false;
1169 return VectorIndex.Val < 2;
1170 }
1171
Jim Grosbach741cd732011-10-17 22:26:03 +00001172 bool isNEONi8splat() const {
1173 if (Kind != k_Immediate)
1174 return false;
1175 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1176 // Must be a constant.
1177 if (!CE) return false;
1178 int64_t Value = CE->getValue();
1179 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1180 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001181 return Value >= 0 && Value < 256;
1182 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001183
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001184 bool isNEONi16splat() const {
1185 if (Kind != k_Immediate)
1186 return false;
1187 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1188 // Must be a constant.
1189 if (!CE) return false;
1190 int64_t Value = CE->getValue();
1191 // i16 value in the range [0,255] or [0x0100, 0xff00]
1192 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1193 }
1194
Jim Grosbach8211c052011-10-18 00:22:00 +00001195 bool isNEONi32splat() const {
1196 if (Kind != k_Immediate)
1197 return false;
1198 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1199 // Must be a constant.
1200 if (!CE) return false;
1201 int64_t Value = CE->getValue();
1202 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1203 return (Value >= 0 && Value < 256) ||
1204 (Value >= 0x0100 && Value <= 0xff00) ||
1205 (Value >= 0x010000 && Value <= 0xff0000) ||
1206 (Value >= 0x01000000 && Value <= 0xff000000);
1207 }
1208
1209 bool isNEONi32vmov() const {
1210 if (Kind != k_Immediate)
1211 return false;
1212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1213 // Must be a constant.
1214 if (!CE) return false;
1215 int64_t Value = CE->getValue();
1216 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1217 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1218 return (Value >= 0 && Value < 256) ||
1219 (Value >= 0x0100 && Value <= 0xff00) ||
1220 (Value >= 0x010000 && Value <= 0xff0000) ||
1221 (Value >= 0x01000000 && Value <= 0xff000000) ||
1222 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1223 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1224 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001225 bool isNEONi32vmovNeg() const {
1226 if (Kind != k_Immediate)
1227 return false;
1228 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1229 // Must be a constant.
1230 if (!CE) return false;
1231 int64_t Value = ~CE->getValue();
1232 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1233 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1234 return (Value >= 0 && Value < 256) ||
1235 (Value >= 0x0100 && Value <= 0xff00) ||
1236 (Value >= 0x010000 && Value <= 0xff0000) ||
1237 (Value >= 0x01000000 && Value <= 0xff000000) ||
1238 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1239 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1240 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001241
Jim Grosbache4454e02011-10-18 16:18:11 +00001242 bool isNEONi64splat() const {
1243 if (Kind != k_Immediate)
1244 return false;
1245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1246 // Must be a constant.
1247 if (!CE) return false;
1248 uint64_t Value = CE->getValue();
1249 // i64 value with each byte being either 0 or 0xff.
1250 for (unsigned i = 0; i < 8; ++i)
1251 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1252 return true;
1253 }
1254
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001255 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001256 // Add as immediates when possible. Null MCExpr = 0.
1257 if (Expr == 0)
1258 Inst.addOperand(MCOperand::CreateImm(0));
1259 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001260 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1261 else
1262 Inst.addOperand(MCOperand::CreateExpr(Expr));
1263 }
1264
Daniel Dunbard8042b72010-08-11 06:36:53 +00001265 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001266 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001267 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001268 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1269 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001270 }
1271
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001272 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
1274 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1275 }
1276
Jim Grosbach48399582011-10-12 17:34:41 +00001277 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
1279 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1280 }
1281
1282 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1283 assert(N == 1 && "Invalid number of operands!");
1284 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1285 }
1286
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001287 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1288 assert(N == 1 && "Invalid number of operands!");
1289 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1290 }
1291
1292 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
1294 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1295 }
1296
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001297 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
1299 Inst.addOperand(MCOperand::CreateReg(getReg()));
1300 }
1301
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001302 void addRegOperands(MCInst &Inst, unsigned N) const {
1303 assert(N == 1 && "Invalid number of operands!");
1304 Inst.addOperand(MCOperand::CreateReg(getReg()));
1305 }
1306
Jim Grosbachac798e12011-07-25 20:49:51 +00001307 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001308 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001309 assert(isRegShiftedReg() &&
1310 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001311 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1312 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001313 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001314 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001315 }
1316
Jim Grosbachac798e12011-07-25 20:49:51 +00001317 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001318 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001319 assert(isRegShiftedImm() &&
1320 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001321 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001322 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001323 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001324 }
1325
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001326 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001327 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001328 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1329 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001330 }
1331
Bill Wendling8d2aa032010-11-08 23:49:57 +00001332 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001333 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001334 const SmallVectorImpl<unsigned> &RegList = getRegList();
1335 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001336 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1337 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001338 }
1339
Bill Wendling9898ac92010-11-17 04:32:08 +00001340 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1341 addRegListOperands(Inst, N);
1342 }
1343
1344 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1345 addRegListOperands(Inst, N);
1346 }
1347
Jim Grosbach833b9d32011-07-27 20:15:40 +00001348 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1351 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1352 }
1353
Jim Grosbach864b6092011-07-28 21:34:26 +00001354 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1355 assert(N == 1 && "Invalid number of operands!");
1356 // Munge the lsb/width into a bitfield mask.
1357 unsigned lsb = Bitfield.LSB;
1358 unsigned width = Bitfield.Width;
1359 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1360 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1361 (32 - (lsb + width)));
1362 Inst.addOperand(MCOperand::CreateImm(Mask));
1363 }
1364
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001365 void addImmOperands(MCInst &Inst, unsigned N) const {
1366 assert(N == 1 && "Invalid number of operands!");
1367 addExpr(Inst, getImm());
1368 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001369
Jim Grosbache7fbce72011-10-03 23:38:36 +00001370 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
1372 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1373 }
1374
Jim Grosbach7db8d692011-09-08 22:07:06 +00001375 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1376 assert(N == 1 && "Invalid number of operands!");
1377 // FIXME: We really want to scale the value here, but the LDRD/STRD
1378 // instruction don't encode operands that way yet.
1379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1380 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1381 }
1382
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001383 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 // The immediate is scaled by four in the encoding and is stored
1386 // in the MCInst as such. Lop off the low two bits here.
1387 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1388 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1389 }
1390
1391 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1392 assert(N == 1 && "Invalid number of operands!");
1393 // The immediate is scaled by four in the encoding and is stored
1394 // in the MCInst as such. Lop off the low two bits here.
1395 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1396 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1397 }
1398
Jim Grosbach475c6db2011-07-25 23:09:14 +00001399 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1400 assert(N == 1 && "Invalid number of operands!");
1401 // The constant encodes as the immediate-1, and we store in the instruction
1402 // the bits as encoded, so subtract off one here.
1403 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1404 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1405 }
1406
Jim Grosbach801e0a32011-07-22 23:16:18 +00001407 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1408 assert(N == 1 && "Invalid number of operands!");
1409 // The constant encodes as the immediate-1, and we store in the instruction
1410 // the bits as encoded, so subtract off one here.
1411 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1412 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1413 }
1414
Jim Grosbach46dd4132011-08-17 21:51:27 +00001415 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 1 && "Invalid number of operands!");
1417 // The constant encodes as the immediate, except for 32, which encodes as
1418 // zero.
1419 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1420 unsigned Imm = CE->getValue();
1421 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1422 }
1423
Jim Grosbach27c1e252011-07-21 17:23:04 +00001424 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1427 // the instruction as well.
1428 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1429 int Val = CE->getValue();
1430 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1431 }
1432
Jim Grosbachb009a872011-10-28 22:36:30 +00001433 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 // The operand is actually a t2_so_imm, but we have its bitwise
1436 // negation in the assembly source, so twiddle it here.
1437 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1438 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1439 }
1440
Jim Grosbach30506252011-12-08 00:31:07 +00001441 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 // The operand is actually a t2_so_imm, but we have its
1444 // negation in the assembly source, so twiddle it here.
1445 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1446 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1447 }
1448
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001449 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 // The operand is actually a so_imm, but we have its bitwise
1452 // negation in the assembly source, so twiddle it here.
1453 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1454 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1455 }
1456
Jim Grosbach30506252011-12-08 00:31:07 +00001457 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1458 assert(N == 1 && "Invalid number of operands!");
1459 // The operand is actually a so_imm, but we have its
1460 // negation in the assembly source, so twiddle it here.
1461 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1462 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1463 }
1464
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001465 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1466 assert(N == 1 && "Invalid number of operands!");
1467 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1468 }
1469
Jim Grosbachd3595712011-08-03 23:50:40 +00001470 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001472 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001473 }
1474
Jim Grosbacha95ec992011-10-11 17:29:55 +00001475 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
1477 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1478 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1479 }
1480
Jim Grosbachd3595712011-08-03 23:50:40 +00001481 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1482 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001483 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1484 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001485 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1486 // Special case for #-0
1487 if (Val == INT32_MIN) Val = 0;
1488 if (Val < 0) Val = -Val;
1489 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1490 } else {
1491 // For register offset, we encode the shift type and negation flag
1492 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001493 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1494 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001495 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001496 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1497 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001498 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001499 }
1500
Jim Grosbachcd17c122011-08-04 23:01:30 +00001501 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1502 assert(N == 2 && "Invalid number of operands!");
1503 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1504 assert(CE && "non-constant AM2OffsetImm operand!");
1505 int32_t Val = CE->getValue();
1506 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1507 // Special case for #-0
1508 if (Val == INT32_MIN) Val = 0;
1509 if (Val < 0) Val = -Val;
1510 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1511 Inst.addOperand(MCOperand::CreateReg(0));
1512 Inst.addOperand(MCOperand::CreateImm(Val));
1513 }
1514
Jim Grosbach5b96b802011-08-10 20:29:19 +00001515 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1516 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001517 // If we have an immediate that's not a constant, treat it as a label
1518 // reference needing a fixup. If it is a constant, it's something else
1519 // and we reject it.
1520 if (isImm()) {
1521 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1522 Inst.addOperand(MCOperand::CreateReg(0));
1523 Inst.addOperand(MCOperand::CreateImm(0));
1524 return;
1525 }
1526
Jim Grosbach871dff72011-10-11 15:59:20 +00001527 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1528 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001529 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1530 // Special case for #-0
1531 if (Val == INT32_MIN) Val = 0;
1532 if (Val < 0) Val = -Val;
1533 Val = ARM_AM::getAM3Opc(AddSub, Val);
1534 } else {
1535 // For register offset, we encode the shift type and negation flag
1536 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001537 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001538 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001539 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1540 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001541 Inst.addOperand(MCOperand::CreateImm(Val));
1542 }
1543
1544 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1545 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001546 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001547 int32_t Val =
1548 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1549 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1550 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001551 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001552 }
1553
1554 // Constant offset.
1555 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1556 int32_t Val = CE->getValue();
1557 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1558 // Special case for #-0
1559 if (Val == INT32_MIN) Val = 0;
1560 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001561 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001562 Inst.addOperand(MCOperand::CreateReg(0));
1563 Inst.addOperand(MCOperand::CreateImm(Val));
1564 }
1565
Jim Grosbachd3595712011-08-03 23:50:40 +00001566 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1567 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001568 // If we have an immediate that's not a constant, treat it as a label
1569 // reference needing a fixup. If it is a constant, it's something else
1570 // and we reject it.
1571 if (isImm()) {
1572 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1573 Inst.addOperand(MCOperand::CreateImm(0));
1574 return;
1575 }
1576
Jim Grosbachd3595712011-08-03 23:50:40 +00001577 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001578 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001579 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1580 // Special case for #-0
1581 if (Val == INT32_MIN) Val = 0;
1582 if (Val < 0) Val = -Val;
1583 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001584 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001585 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001586 }
1587
Jim Grosbach7db8d692011-09-08 22:07:06 +00001588 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00001590 // If we have an immediate that's not a constant, treat it as a label
1591 // reference needing a fixup. If it is a constant, it's something else
1592 // and we reject it.
1593 if (isImm()) {
1594 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1595 Inst.addOperand(MCOperand::CreateImm(0));
1596 return;
1597 }
1598
Jim Grosbach871dff72011-10-11 15:59:20 +00001599 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1600 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001601 Inst.addOperand(MCOperand::CreateImm(Val));
1602 }
1603
Jim Grosbacha05627e2011-09-09 18:37:27 +00001604 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1605 assert(N == 2 && "Invalid number of operands!");
1606 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001607 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1608 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001609 Inst.addOperand(MCOperand::CreateImm(Val));
1610 }
1611
Jim Grosbachd3595712011-08-03 23:50:40 +00001612 void addMemImm8OffsetOperands(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() : 0;
1615 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001616 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001617 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001618
Jim Grosbach2392c532011-09-07 23:39:14 +00001619 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1620 addMemImm8OffsetOperands(Inst, N);
1621 }
1622
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001623 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001624 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001625 }
1626
1627 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1628 assert(N == 2 && "Invalid number of operands!");
1629 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001630 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001631 addExpr(Inst, getImm());
1632 Inst.addOperand(MCOperand::CreateImm(0));
1633 return;
1634 }
1635
1636 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001637 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1638 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001639 Inst.addOperand(MCOperand::CreateImm(Val));
1640 }
1641
Jim Grosbachd3595712011-08-03 23:50:40 +00001642 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1643 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001644 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001645 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001646 addExpr(Inst, getImm());
1647 Inst.addOperand(MCOperand::CreateImm(0));
1648 return;
1649 }
1650
1651 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001652 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1653 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001654 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001655 }
Bill Wendling811c9362010-11-30 07:44:32 +00001656
Jim Grosbach05541f42011-09-19 22:21:13 +00001657 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1658 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001659 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1660 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001661 }
1662
1663 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001665 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1666 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001667 }
1668
Jim Grosbachd3595712011-08-03 23:50:40 +00001669 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1670 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001671 unsigned Val =
1672 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1673 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001674 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1675 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001676 Inst.addOperand(MCOperand::CreateImm(Val));
1677 }
1678
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001679 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1680 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001681 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1682 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1683 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001684 }
1685
Jim Grosbachd3595712011-08-03 23:50:40 +00001686 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1687 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001688 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1689 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001690 }
1691
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001692 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1693 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001694 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1695 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001696 Inst.addOperand(MCOperand::CreateImm(Val));
1697 }
1698
Jim Grosbach26d35872011-08-19 18:55:51 +00001699 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1700 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001701 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1702 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001703 Inst.addOperand(MCOperand::CreateImm(Val));
1704 }
1705
Jim Grosbacha32c7532011-08-19 18:49:59 +00001706 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1707 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001708 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1709 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001710 Inst.addOperand(MCOperand::CreateImm(Val));
1711 }
1712
Jim Grosbach23983d62011-08-19 18:13:48 +00001713 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1714 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001715 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1716 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001717 Inst.addOperand(MCOperand::CreateImm(Val));
1718 }
1719
Jim Grosbachd3595712011-08-03 23:50:40 +00001720 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1721 assert(N == 1 && "Invalid number of operands!");
1722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1723 assert(CE && "non-constant post-idx-imm8 operand!");
1724 int Imm = CE->getValue();
1725 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001726 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001727 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1728 Inst.addOperand(MCOperand::CreateImm(Imm));
1729 }
1730
Jim Grosbach93981412011-10-11 21:55:36 +00001731 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1732 assert(N == 1 && "Invalid number of operands!");
1733 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1734 assert(CE && "non-constant post-idx-imm8s4 operand!");
1735 int Imm = CE->getValue();
1736 bool isAdd = Imm >= 0;
1737 if (Imm == INT32_MIN) Imm = 0;
1738 // Immediate is scaled by 4.
1739 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1740 Inst.addOperand(MCOperand::CreateImm(Imm));
1741 }
1742
Jim Grosbachd3595712011-08-03 23:50:40 +00001743 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1744 assert(N == 2 && "Invalid number of operands!");
1745 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001746 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1747 }
1748
1749 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1750 assert(N == 2 && "Invalid number of operands!");
1751 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1752 // The sign, shift type, and shift amount are encoded in a single operand
1753 // using the AM2 encoding helpers.
1754 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1755 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1756 PostIdxReg.ShiftTy);
1757 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001758 }
1759
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001760 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1761 assert(N == 1 && "Invalid number of operands!");
1762 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1763 }
1764
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001765 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1766 assert(N == 1 && "Invalid number of operands!");
1767 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1768 }
1769
Jim Grosbach182b6a02011-11-29 23:51:09 +00001770 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001771 assert(N == 1 && "Invalid number of operands!");
1772 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1773 }
1774
Jim Grosbach04945c42011-12-02 00:35:16 +00001775 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1776 assert(N == 2 && "Invalid number of operands!");
1777 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1778 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1779 }
1780
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001781 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1782 assert(N == 1 && "Invalid number of operands!");
1783 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1784 }
1785
1786 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1787 assert(N == 1 && "Invalid number of operands!");
1788 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1789 }
1790
1791 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1792 assert(N == 1 && "Invalid number of operands!");
1793 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1794 }
1795
Jim Grosbach741cd732011-10-17 22:26:03 +00001796 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1797 assert(N == 1 && "Invalid number of operands!");
1798 // The immediate encodes the type of constant as well as the value.
1799 // Mask in that this is an i8 splat.
1800 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1801 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1802 }
1803
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001804 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1805 assert(N == 1 && "Invalid number of operands!");
1806 // The immediate encodes the type of constant as well as the value.
1807 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1808 unsigned Value = CE->getValue();
1809 if (Value >= 256)
1810 Value = (Value >> 8) | 0xa00;
1811 else
1812 Value |= 0x800;
1813 Inst.addOperand(MCOperand::CreateImm(Value));
1814 }
1815
Jim Grosbach8211c052011-10-18 00:22:00 +00001816 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1817 assert(N == 1 && "Invalid number of operands!");
1818 // The immediate encodes the type of constant as well as the value.
1819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1820 unsigned Value = CE->getValue();
1821 if (Value >= 256 && Value <= 0xff00)
1822 Value = (Value >> 8) | 0x200;
1823 else if (Value > 0xffff && Value <= 0xff0000)
1824 Value = (Value >> 16) | 0x400;
1825 else if (Value > 0xffffff)
1826 Value = (Value >> 24) | 0x600;
1827 Inst.addOperand(MCOperand::CreateImm(Value));
1828 }
1829
1830 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1831 assert(N == 1 && "Invalid number of operands!");
1832 // The immediate encodes the type of constant as well as the value.
1833 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1834 unsigned Value = CE->getValue();
1835 if (Value >= 256 && Value <= 0xffff)
1836 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1837 else if (Value > 0xffff && Value <= 0xffffff)
1838 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1839 else if (Value > 0xffffff)
1840 Value = (Value >> 24) | 0x600;
1841 Inst.addOperand(MCOperand::CreateImm(Value));
1842 }
1843
Jim Grosbach045b6c72011-12-19 23:51:07 +00001844 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1845 assert(N == 1 && "Invalid number of operands!");
1846 // The immediate encodes the type of constant as well as the value.
1847 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1848 unsigned Value = ~CE->getValue();
1849 if (Value >= 256 && Value <= 0xffff)
1850 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1851 else if (Value > 0xffff && Value <= 0xffffff)
1852 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1853 else if (Value > 0xffffff)
1854 Value = (Value >> 24) | 0x600;
1855 Inst.addOperand(MCOperand::CreateImm(Value));
1856 }
1857
Jim Grosbache4454e02011-10-18 16:18:11 +00001858 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 1 && "Invalid number of operands!");
1860 // The immediate encodes the type of constant as well as the value.
1861 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1862 uint64_t Value = CE->getValue();
1863 unsigned Imm = 0;
1864 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1865 Imm |= (Value & 1) << i;
1866 }
1867 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1868 }
1869
Jim Grosbach602aa902011-07-13 15:34:57 +00001870 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001871
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001872 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001873 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001874 Op->ITMask.Mask = Mask;
1875 Op->StartLoc = S;
1876 Op->EndLoc = S;
1877 return Op;
1878 }
1879
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001880 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001881 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001882 Op->CC.Val = CC;
1883 Op->StartLoc = S;
1884 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001885 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001886 }
1887
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001888 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001889 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001890 Op->Cop.Val = CopVal;
1891 Op->StartLoc = S;
1892 Op->EndLoc = S;
1893 return Op;
1894 }
1895
1896 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001897 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001898 Op->Cop.Val = CopVal;
1899 Op->StartLoc = S;
1900 Op->EndLoc = S;
1901 return Op;
1902 }
1903
Jim Grosbach48399582011-10-12 17:34:41 +00001904 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1905 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1906 Op->Cop.Val = Val;
1907 Op->StartLoc = S;
1908 Op->EndLoc = E;
1909 return Op;
1910 }
1911
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001912 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001913 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001914 Op->Reg.RegNum = RegNum;
1915 Op->StartLoc = S;
1916 Op->EndLoc = S;
1917 return Op;
1918 }
1919
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001920 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001921 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001922 Op->Tok.Data = Str.data();
1923 Op->Tok.Length = Str.size();
1924 Op->StartLoc = S;
1925 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001926 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001927 }
1928
Bill Wendling2063b842010-11-18 23:43:05 +00001929 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001930 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001931 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001932 Op->StartLoc = S;
1933 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001934 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001935 }
1936
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001937 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1938 unsigned SrcReg,
1939 unsigned ShiftReg,
1940 unsigned ShiftImm,
1941 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001942 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001943 Op->RegShiftedReg.ShiftTy = ShTy;
1944 Op->RegShiftedReg.SrcReg = SrcReg;
1945 Op->RegShiftedReg.ShiftReg = ShiftReg;
1946 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001947 Op->StartLoc = S;
1948 Op->EndLoc = E;
1949 return Op;
1950 }
1951
Owen Andersonb595ed02011-07-21 18:54:16 +00001952 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1953 unsigned SrcReg,
1954 unsigned ShiftImm,
1955 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001956 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001957 Op->RegShiftedImm.ShiftTy = ShTy;
1958 Op->RegShiftedImm.SrcReg = SrcReg;
1959 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001960 Op->StartLoc = S;
1961 Op->EndLoc = E;
1962 return Op;
1963 }
1964
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001965 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001966 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001967 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001968 Op->ShifterImm.isASR = isASR;
1969 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001970 Op->StartLoc = S;
1971 Op->EndLoc = E;
1972 return Op;
1973 }
1974
Jim Grosbach833b9d32011-07-27 20:15:40 +00001975 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001976 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001977 Op->RotImm.Imm = Imm;
1978 Op->StartLoc = S;
1979 Op->EndLoc = E;
1980 return Op;
1981 }
1982
Jim Grosbach864b6092011-07-28 21:34:26 +00001983 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1984 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001985 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001986 Op->Bitfield.LSB = LSB;
1987 Op->Bitfield.Width = Width;
1988 Op->StartLoc = S;
1989 Op->EndLoc = E;
1990 return Op;
1991 }
1992
Bill Wendling2cae3272010-11-09 22:44:22 +00001993 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001994 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001995 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001996 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001997
Jim Grosbach75461af2011-09-13 22:56:44 +00001998 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001999 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002000 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00002001 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002002 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002003
2004 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00002005 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002006 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00002007 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00002008 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002009 Op->StartLoc = StartLoc;
2010 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002011 return Op;
2012 }
2013
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002014 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00002015 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002016 ARMOperand *Op = new ARMOperand(k_VectorList);
2017 Op->VectorList.RegNum = RegNum;
2018 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002019 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002020 Op->StartLoc = S;
2021 Op->EndLoc = E;
2022 return Op;
2023 }
2024
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002025 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
2026 SMLoc S, SMLoc E) {
2027 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2028 Op->VectorList.RegNum = RegNum;
2029 Op->VectorList.Count = Count;
2030 Op->StartLoc = S;
2031 Op->EndLoc = E;
2032 return Op;
2033 }
2034
Jim Grosbach04945c42011-12-02 00:35:16 +00002035 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
2036 unsigned Index, SMLoc S, SMLoc E) {
2037 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2038 Op->VectorList.RegNum = RegNum;
2039 Op->VectorList.Count = Count;
2040 Op->VectorList.LaneIndex = Index;
2041 Op->StartLoc = S;
2042 Op->EndLoc = E;
2043 return Op;
2044 }
2045
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002046 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2047 MCContext &Ctx) {
2048 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2049 Op->VectorIndex.Val = Idx;
2050 Op->StartLoc = S;
2051 Op->EndLoc = E;
2052 return Op;
2053 }
2054
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002055 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002056 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002057 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002058 Op->StartLoc = S;
2059 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002060 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002061 }
2062
Jim Grosbache7fbce72011-10-03 23:38:36 +00002063 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002064 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00002065 Op->FPImm.Val = Val;
2066 Op->StartLoc = S;
2067 Op->EndLoc = S;
2068 return Op;
2069 }
2070
Jim Grosbachd3595712011-08-03 23:50:40 +00002071 static ARMOperand *CreateMem(unsigned BaseRegNum,
2072 const MCConstantExpr *OffsetImm,
2073 unsigned OffsetRegNum,
2074 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002075 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002076 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002077 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002078 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002079 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002080 Op->Memory.BaseRegNum = BaseRegNum;
2081 Op->Memory.OffsetImm = OffsetImm;
2082 Op->Memory.OffsetRegNum = OffsetRegNum;
2083 Op->Memory.ShiftType = ShiftType;
2084 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002085 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002086 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002087 Op->StartLoc = S;
2088 Op->EndLoc = E;
2089 return Op;
2090 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002091
Jim Grosbachc320c852011-08-05 21:28:30 +00002092 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2093 ARM_AM::ShiftOpc ShiftTy,
2094 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002095 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002096 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002097 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002098 Op->PostIdxReg.isAdd = isAdd;
2099 Op->PostIdxReg.ShiftTy = ShiftTy;
2100 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002101 Op->StartLoc = S;
2102 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002103 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002104 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002105
2106 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002107 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002108 Op->MBOpt.Val = Opt;
2109 Op->StartLoc = S;
2110 Op->EndLoc = S;
2111 return Op;
2112 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002113
2114 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002115 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002116 Op->IFlags.Val = IFlags;
2117 Op->StartLoc = S;
2118 Op->EndLoc = S;
2119 return Op;
2120 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002121
2122 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002123 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002124 Op->MMask.Val = MMask;
2125 Op->StartLoc = S;
2126 Op->EndLoc = S;
2127 return Op;
2128 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002129};
2130
2131} // end anonymous namespace.
2132
Jim Grosbach602aa902011-07-13 15:34:57 +00002133void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002134 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002135 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00002136 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2137 << ") >";
2138 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002139 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002140 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002141 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002142 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002143 OS << "<ccout " << getReg() << ">";
2144 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002145 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002146 static const char *MaskStr[] = {
2147 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2148 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2149 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002150 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2151 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2152 break;
2153 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002154 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002155 OS << "<coprocessor number: " << getCoproc() << ">";
2156 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002157 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002158 OS << "<coprocessor register: " << getCoproc() << ">";
2159 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002160 case k_CoprocOption:
2161 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2162 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002163 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002164 OS << "<mask: " << getMSRMask() << ">";
2165 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002166 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002167 getImm()->print(OS);
2168 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002169 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002170 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2171 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002172 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002173 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002174 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002175 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002176 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002177 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002178 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2179 << PostIdxReg.RegNum;
2180 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2181 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2182 << PostIdxReg.ShiftImm;
2183 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002184 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002185 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002186 OS << "<ARM_PROC::";
2187 unsigned IFlags = getProcIFlags();
2188 for (int i=2; i >= 0; --i)
2189 if (IFlags & (1 << i))
2190 OS << ARM_PROC::IFlagsToString(1 << i);
2191 OS << ">";
2192 break;
2193 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002194 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002195 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002196 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002197 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002198 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2199 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002200 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002201 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002202 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002203 << RegShiftedReg.SrcReg << " "
2204 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2205 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002206 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002207 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002208 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002209 << RegShiftedImm.SrcReg << " "
2210 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2211 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002212 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002213 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002214 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2215 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002216 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002217 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2218 << ", width: " << Bitfield.Width << ">";
2219 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002220 case k_RegisterList:
2221 case k_DPRRegisterList:
2222 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002223 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002224
Bill Wendlingbed94652010-11-09 23:28:44 +00002225 const SmallVectorImpl<unsigned> &RegList = getRegList();
2226 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002227 I = RegList.begin(), E = RegList.end(); I != E; ) {
2228 OS << *I;
2229 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002230 }
2231
2232 OS << ">";
2233 break;
2234 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002235 case k_VectorList:
2236 OS << "<vector_list " << VectorList.Count << " * "
2237 << VectorList.RegNum << ">";
2238 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002239 case k_VectorListAllLanes:
2240 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2241 << VectorList.RegNum << ">";
2242 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002243 case k_VectorListIndexed:
2244 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2245 << VectorList.Count << " * " << VectorList.RegNum << ">";
2246 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002247 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002248 OS << "'" << getToken() << "'";
2249 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002250 case k_VectorIndex:
2251 OS << "<vectorindex " << getVectorIndex() << ">";
2252 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002253 }
2254}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002255
2256/// @name Auto-generated Match Functions
2257/// {
2258
2259static unsigned MatchRegisterName(StringRef Name);
2260
2261/// }
2262
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002263bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2264 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002265 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002266 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002267 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002268
2269 return (RegNo == (unsigned)-1);
2270}
2271
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002272/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002273/// and if it is a register name the token is eaten and the register number is
2274/// returned. Otherwise return -1.
2275///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002276int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002277 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002278 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002279
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002280 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002281 unsigned RegNum = MatchRegisterName(lowerCase);
2282 if (!RegNum) {
2283 RegNum = StringSwitch<unsigned>(lowerCase)
2284 .Case("r13", ARM::SP)
2285 .Case("r14", ARM::LR)
2286 .Case("r15", ARM::PC)
2287 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002288 // Additional register name aliases for 'gas' compatibility.
2289 .Case("a1", ARM::R0)
2290 .Case("a2", ARM::R1)
2291 .Case("a3", ARM::R2)
2292 .Case("a4", ARM::R3)
2293 .Case("v1", ARM::R4)
2294 .Case("v2", ARM::R5)
2295 .Case("v3", ARM::R6)
2296 .Case("v4", ARM::R7)
2297 .Case("v5", ARM::R8)
2298 .Case("v6", ARM::R9)
2299 .Case("v7", ARM::R10)
2300 .Case("v8", ARM::R11)
2301 .Case("sb", ARM::R9)
2302 .Case("sl", ARM::R10)
2303 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002304 .Default(0);
2305 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002306 if (!RegNum) {
2307 // Check for aliases registered via .req.
2308 StringMap<unsigned>::const_iterator Entry =
2309 RegisterReqs.find(Tok.getIdentifier());
2310 // If no match, return failure.
2311 if (Entry == RegisterReqs.end())
2312 return -1;
2313 Parser.Lex(); // Eat identifier token.
2314 return Entry->getValue();
2315 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002316
Chris Lattner44e5981c2010-10-30 04:09:10 +00002317 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002318
Chris Lattner44e5981c2010-10-30 04:09:10 +00002319 return RegNum;
2320}
Jim Grosbach99710a82010-11-01 16:44:21 +00002321
Jim Grosbachbb24c592011-07-13 18:49:30 +00002322// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2323// If a recoverable error occurs, return 1. If an irrecoverable error
2324// occurs, return -1. An irrecoverable error is one where tokens have been
2325// consumed in the process of trying to parse the shifter (i.e., when it is
2326// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002327int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002328 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2329 SMLoc S = Parser.getTok().getLoc();
2330 const AsmToken &Tok = Parser.getTok();
2331 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2332
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002333 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002334 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002335 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002336 .Case("lsl", ARM_AM::lsl)
2337 .Case("lsr", ARM_AM::lsr)
2338 .Case("asr", ARM_AM::asr)
2339 .Case("ror", ARM_AM::ror)
2340 .Case("rrx", ARM_AM::rrx)
2341 .Default(ARM_AM::no_shift);
2342
2343 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002344 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002345
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002346 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002347
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002348 // The source register for the shift has already been added to the
2349 // operand list, so we need to pop it off and combine it into the shifted
2350 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002351 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002352 if (!PrevOp->isReg())
2353 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2354 int SrcReg = PrevOp->getReg();
2355 int64_t Imm = 0;
2356 int ShiftReg = 0;
2357 if (ShiftTy == ARM_AM::rrx) {
2358 // RRX Doesn't have an explicit shift amount. The encoder expects
2359 // the shift register to be the same as the source register. Seems odd,
2360 // but OK.
2361 ShiftReg = SrcReg;
2362 } else {
2363 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002364 if (Parser.getTok().is(AsmToken::Hash) ||
2365 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002366 Parser.Lex(); // Eat hash.
2367 SMLoc ImmLoc = Parser.getTok().getLoc();
2368 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002369 if (getParser().ParseExpression(ShiftExpr)) {
2370 Error(ImmLoc, "invalid immediate shift value");
2371 return -1;
2372 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002373 // The expression must be evaluatable as an immediate.
2374 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002375 if (!CE) {
2376 Error(ImmLoc, "invalid immediate shift value");
2377 return -1;
2378 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002379 // Range check the immediate.
2380 // lsl, ror: 0 <= imm <= 31
2381 // lsr, asr: 0 <= imm <= 32
2382 Imm = CE->getValue();
2383 if (Imm < 0 ||
2384 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2385 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002386 Error(ImmLoc, "immediate shift value out of range");
2387 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002388 }
2389 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002390 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002391 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002392 if (ShiftReg == -1) {
2393 Error (L, "expected immediate or register in shift operand");
2394 return -1;
2395 }
2396 } else {
2397 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002398 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002399 return -1;
2400 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002401 }
2402
Owen Andersonb595ed02011-07-21 18:54:16 +00002403 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2404 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002405 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002406 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002407 else
2408 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2409 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002410
Jim Grosbachbb24c592011-07-13 18:49:30 +00002411 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002412}
2413
2414
Bill Wendling2063b842010-11-18 23:43:05 +00002415/// Try to parse a register name. The token must be an Identifier when called.
2416/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2417/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002418///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002419/// TODO this is likely to change to allow different register types and or to
2420/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002421bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002422tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002423 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002424 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002425 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002426 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002427
Bill Wendling2063b842010-11-18 23:43:05 +00002428 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002429
Chris Lattner44e5981c2010-10-30 04:09:10 +00002430 const AsmToken &ExclaimTok = Parser.getTok();
2431 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002432 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2433 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002434 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002435 return false;
2436 }
2437
2438 // Also check for an index operand. This is only legal for vector registers,
2439 // but that'll get caught OK in operand matching, so we don't need to
2440 // explicitly filter everything else out here.
2441 if (Parser.getTok().is(AsmToken::LBrac)) {
2442 SMLoc SIdx = Parser.getTok().getLoc();
2443 Parser.Lex(); // Eat left bracket token.
2444
2445 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002446 if (getParser().ParseExpression(ImmVal))
2447 return MatchOperand_ParseFail;
2448 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2449 if (!MCE) {
2450 TokError("immediate value expected for vector index");
2451 return MatchOperand_ParseFail;
2452 }
2453
2454 SMLoc E = Parser.getTok().getLoc();
2455 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2456 Error(E, "']' expected");
2457 return MatchOperand_ParseFail;
2458 }
2459
2460 Parser.Lex(); // Eat right bracket token.
2461
2462 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2463 SIdx, E,
2464 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002465 }
2466
Bill Wendling2063b842010-11-18 23:43:05 +00002467 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002468}
2469
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002470/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2471/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2472/// "c5", ...
2473static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002474 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2475 // but efficient.
2476 switch (Name.size()) {
2477 default: break;
2478 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002479 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002480 return -1;
2481 switch (Name[1]) {
2482 default: return -1;
2483 case '0': return 0;
2484 case '1': return 1;
2485 case '2': return 2;
2486 case '3': return 3;
2487 case '4': return 4;
2488 case '5': return 5;
2489 case '6': return 6;
2490 case '7': return 7;
2491 case '8': return 8;
2492 case '9': return 9;
2493 }
2494 break;
2495 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002496 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002497 return -1;
2498 switch (Name[2]) {
2499 default: return -1;
2500 case '0': return 10;
2501 case '1': return 11;
2502 case '2': return 12;
2503 case '3': return 13;
2504 case '4': return 14;
2505 case '5': return 15;
2506 }
2507 break;
2508 }
2509
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002510 return -1;
2511}
2512
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002513/// parseITCondCode - Try to parse a condition code for an IT instruction.
2514ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2515parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2516 SMLoc S = Parser.getTok().getLoc();
2517 const AsmToken &Tok = Parser.getTok();
2518 if (!Tok.is(AsmToken::Identifier))
2519 return MatchOperand_NoMatch;
2520 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2521 .Case("eq", ARMCC::EQ)
2522 .Case("ne", ARMCC::NE)
2523 .Case("hs", ARMCC::HS)
2524 .Case("cs", ARMCC::HS)
2525 .Case("lo", ARMCC::LO)
2526 .Case("cc", ARMCC::LO)
2527 .Case("mi", ARMCC::MI)
2528 .Case("pl", ARMCC::PL)
2529 .Case("vs", ARMCC::VS)
2530 .Case("vc", ARMCC::VC)
2531 .Case("hi", ARMCC::HI)
2532 .Case("ls", ARMCC::LS)
2533 .Case("ge", ARMCC::GE)
2534 .Case("lt", ARMCC::LT)
2535 .Case("gt", ARMCC::GT)
2536 .Case("le", ARMCC::LE)
2537 .Case("al", ARMCC::AL)
2538 .Default(~0U);
2539 if (CC == ~0U)
2540 return MatchOperand_NoMatch;
2541 Parser.Lex(); // Eat the token.
2542
2543 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2544
2545 return MatchOperand_Success;
2546}
2547
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002548/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002549/// token must be an Identifier when called, and if it is a coprocessor
2550/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002551ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002552parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002553 SMLoc S = Parser.getTok().getLoc();
2554 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002555 if (Tok.isNot(AsmToken::Identifier))
2556 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002557
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002558 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002559 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002560 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002561
2562 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002563 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002564 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002565}
2566
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002567/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002568/// token must be an Identifier when called, and if it is a coprocessor
2569/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002570ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002571parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002572 SMLoc S = Parser.getTok().getLoc();
2573 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002574 if (Tok.isNot(AsmToken::Identifier))
2575 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002576
2577 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2578 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002579 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002580
2581 Parser.Lex(); // Eat identifier token.
2582 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002583 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002584}
2585
Jim Grosbach48399582011-10-12 17:34:41 +00002586/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2587/// coproc_option : '{' imm0_255 '}'
2588ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2589parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2590 SMLoc S = Parser.getTok().getLoc();
2591
2592 // If this isn't a '{', this isn't a coprocessor immediate operand.
2593 if (Parser.getTok().isNot(AsmToken::LCurly))
2594 return MatchOperand_NoMatch;
2595 Parser.Lex(); // Eat the '{'
2596
2597 const MCExpr *Expr;
2598 SMLoc Loc = Parser.getTok().getLoc();
2599 if (getParser().ParseExpression(Expr)) {
2600 Error(Loc, "illegal expression");
2601 return MatchOperand_ParseFail;
2602 }
2603 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2604 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2605 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2606 return MatchOperand_ParseFail;
2607 }
2608 int Val = CE->getValue();
2609
2610 // Check for and consume the closing '}'
2611 if (Parser.getTok().isNot(AsmToken::RCurly))
2612 return MatchOperand_ParseFail;
2613 SMLoc E = Parser.getTok().getLoc();
2614 Parser.Lex(); // Eat the '}'
2615
2616 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2617 return MatchOperand_Success;
2618}
2619
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002620// For register list parsing, we need to map from raw GPR register numbering
2621// to the enumeration values. The enumeration values aren't sorted by
2622// register number due to our using "sp", "lr" and "pc" as canonical names.
2623static unsigned getNextRegister(unsigned Reg) {
2624 // If this is a GPR, we need to do it manually, otherwise we can rely
2625 // on the sort ordering of the enumeration since the other reg-classes
2626 // are sane.
2627 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2628 return Reg + 1;
2629 switch(Reg) {
2630 default: assert(0 && "Invalid GPR number!");
2631 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2632 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2633 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2634 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2635 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2636 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2637 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2638 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2639 }
2640}
2641
Jim Grosbach85a23432011-11-11 21:27:40 +00002642// Return the low-subreg of a given Q register.
2643static unsigned getDRegFromQReg(unsigned QReg) {
2644 switch (QReg) {
2645 default: llvm_unreachable("expected a Q register!");
2646 case ARM::Q0: return ARM::D0;
2647 case ARM::Q1: return ARM::D2;
2648 case ARM::Q2: return ARM::D4;
2649 case ARM::Q3: return ARM::D6;
2650 case ARM::Q4: return ARM::D8;
2651 case ARM::Q5: return ARM::D10;
2652 case ARM::Q6: return ARM::D12;
2653 case ARM::Q7: return ARM::D14;
2654 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002655 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002656 case ARM::Q10: return ARM::D20;
2657 case ARM::Q11: return ARM::D22;
2658 case ARM::Q12: return ARM::D24;
2659 case ARM::Q13: return ARM::D26;
2660 case ARM::Q14: return ARM::D28;
2661 case ARM::Q15: return ARM::D30;
2662 }
2663}
2664
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002665/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002666bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002667parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002668 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002669 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002670 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002671 Parser.Lex(); // Eat '{' token.
2672 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002673
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002674 // Check the first register in the list to see what register class
2675 // this is a list of.
2676 int Reg = tryParseRegister();
2677 if (Reg == -1)
2678 return Error(RegLoc, "register expected");
2679
Jim Grosbach85a23432011-11-11 21:27:40 +00002680 // The reglist instructions have at most 16 registers, so reserve
2681 // space for that many.
2682 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2683
2684 // Allow Q regs and just interpret them as the two D sub-registers.
2685 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2686 Reg = getDRegFromQReg(Reg);
2687 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2688 ++Reg;
2689 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002690 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002691 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2692 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2693 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2694 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2695 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2696 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2697 else
2698 return Error(RegLoc, "invalid register in register list");
2699
Jim Grosbach85a23432011-11-11 21:27:40 +00002700 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002701 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002702
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002703 // This starts immediately after the first register token in the list,
2704 // so we can see either a comma or a minus (range separator) as a legal
2705 // next token.
2706 while (Parser.getTok().is(AsmToken::Comma) ||
2707 Parser.getTok().is(AsmToken::Minus)) {
2708 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002709 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002710 SMLoc EndLoc = Parser.getTok().getLoc();
2711 int EndReg = tryParseRegister();
2712 if (EndReg == -1)
2713 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002714 // Allow Q regs and just interpret them as the two D sub-registers.
2715 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2716 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002717 // If the register is the same as the start reg, there's nothing
2718 // more to do.
2719 if (Reg == EndReg)
2720 continue;
2721 // The register must be in the same register class as the first.
2722 if (!RC->contains(EndReg))
2723 return Error(EndLoc, "invalid register in register list");
2724 // Ranges must go from low to high.
2725 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2726 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002727
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002728 // Add all the registers in the range to the register list.
2729 while (Reg != EndReg) {
2730 Reg = getNextRegister(Reg);
2731 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2732 }
2733 continue;
2734 }
2735 Parser.Lex(); // Eat the comma.
2736 RegLoc = Parser.getTok().getLoc();
2737 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002738 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002739 Reg = tryParseRegister();
2740 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002741 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002742 // Allow Q regs and just interpret them as the two D sub-registers.
2743 bool isQReg = false;
2744 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2745 Reg = getDRegFromQReg(Reg);
2746 isQReg = true;
2747 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002748 // The register must be in the same register class as the first.
2749 if (!RC->contains(Reg))
2750 return Error(RegLoc, "invalid register in register list");
2751 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002752 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002753 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002754 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2755 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2756 ") in register list");
2757 continue;
2758 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002759 // VFP register lists must also be contiguous.
2760 // It's OK to use the enumeration values directly here rather, as the
2761 // VFP register classes have the enum sorted properly.
2762 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2763 Reg != OldReg + 1)
2764 return Error(RegLoc, "non-contiguous register range");
2765 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002766 if (isQReg)
2767 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002768 }
2769
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002770 SMLoc E = Parser.getTok().getLoc();
2771 if (Parser.getTok().isNot(AsmToken::RCurly))
2772 return Error(E, "'}' expected");
2773 Parser.Lex(); // Eat '}' token.
2774
Jim Grosbach18bf3632011-12-13 21:48:29 +00002775 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002776 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002777
2778 // The ARM system instruction variants for LDM/STM have a '^' token here.
2779 if (Parser.getTok().is(AsmToken::Caret)) {
2780 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2781 Parser.Lex(); // Eat '^' token.
2782 }
2783
Bill Wendling2063b842010-11-18 23:43:05 +00002784 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002785}
2786
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002787// Helper function to parse the lane index for vector lists.
2788ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002789parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2790 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002791 if (Parser.getTok().is(AsmToken::LBrac)) {
2792 Parser.Lex(); // Eat the '['.
2793 if (Parser.getTok().is(AsmToken::RBrac)) {
2794 // "Dn[]" is the 'all lanes' syntax.
2795 LaneKind = AllLanes;
2796 Parser.Lex(); // Eat the ']'.
2797 return MatchOperand_Success;
2798 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002799 if (Parser.getTok().is(AsmToken::Integer)) {
2800 int64_t Val = Parser.getTok().getIntVal();
2801 // Make this range check context sensitive for .8, .16, .32.
2802 if (Val < 0 && Val > 7)
2803 Error(Parser.getTok().getLoc(), "lane index out of range");
2804 Index = Val;
2805 LaneKind = IndexedLane;
2806 Parser.Lex(); // Eat the token;
2807 if (Parser.getTok().isNot(AsmToken::RBrac))
2808 Error(Parser.getTok().getLoc(), "']' expected");
2809 Parser.Lex(); // Eat the ']'.
2810 return MatchOperand_Success;
2811 }
2812 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002813 return MatchOperand_ParseFail;
2814 }
2815 LaneKind = NoLanes;
2816 return MatchOperand_Success;
2817}
2818
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002819// parse a vector register list
2820ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2821parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002822 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002823 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002824 SMLoc S = Parser.getTok().getLoc();
2825 // As an extension (to match gas), support a plain D register or Q register
2826 // (without encosing curly braces) as a single or double entry list,
2827 // respectively.
2828 if (Parser.getTok().is(AsmToken::Identifier)) {
2829 int Reg = tryParseRegister();
2830 if (Reg == -1)
2831 return MatchOperand_NoMatch;
2832 SMLoc E = Parser.getTok().getLoc();
2833 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002834 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002835 if (Res != MatchOperand_Success)
2836 return Res;
2837 switch (LaneKind) {
2838 default:
2839 assert(0 && "unexpected lane kind!");
2840 case NoLanes:
2841 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002842 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002843 break;
2844 case AllLanes:
2845 E = Parser.getTok().getLoc();
2846 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2847 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002848 case IndexedLane:
2849 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2850 LaneIndex, S,E));
2851 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002852 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002853 return MatchOperand_Success;
2854 }
2855 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2856 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002857 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002858 if (Res != MatchOperand_Success)
2859 return Res;
2860 switch (LaneKind) {
2861 default:
2862 assert(0 && "unexpected lane kind!");
2863 case NoLanes:
2864 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002865 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002866 break;
2867 case AllLanes:
2868 E = Parser.getTok().getLoc();
2869 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2870 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002871 case IndexedLane:
2872 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2873 LaneIndex, S,E));
2874 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002875 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002876 return MatchOperand_Success;
2877 }
2878 Error(S, "vector register expected");
2879 return MatchOperand_ParseFail;
2880 }
2881
2882 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002883 return MatchOperand_NoMatch;
2884
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002885 Parser.Lex(); // Eat '{' token.
2886 SMLoc RegLoc = Parser.getTok().getLoc();
2887
2888 int Reg = tryParseRegister();
2889 if (Reg == -1) {
2890 Error(RegLoc, "register expected");
2891 return MatchOperand_ParseFail;
2892 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002893 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00002894 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00002895 unsigned FirstReg = Reg;
2896 // The list is of D registers, but we also allow Q regs and just interpret
2897 // them as the two D sub-registers.
2898 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2899 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002900 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2901 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00002902 ++Reg;
2903 ++Count;
2904 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002905 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002906 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002907
Jim Grosbache891fe82011-11-15 23:19:15 +00002908 while (Parser.getTok().is(AsmToken::Comma) ||
2909 Parser.getTok().is(AsmToken::Minus)) {
2910 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002911 if (!Spacing)
2912 Spacing = 1; // Register range implies a single spaced list.
2913 else if (Spacing == 2) {
2914 Error(Parser.getTok().getLoc(),
2915 "sequential registers in double spaced list");
2916 return MatchOperand_ParseFail;
2917 }
Jim Grosbache891fe82011-11-15 23:19:15 +00002918 Parser.Lex(); // Eat the minus.
2919 SMLoc EndLoc = Parser.getTok().getLoc();
2920 int EndReg = tryParseRegister();
2921 if (EndReg == -1) {
2922 Error(EndLoc, "register expected");
2923 return MatchOperand_ParseFail;
2924 }
2925 // Allow Q regs and just interpret them as the two D sub-registers.
2926 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2927 EndReg = getDRegFromQReg(EndReg) + 1;
2928 // If the register is the same as the start reg, there's nothing
2929 // more to do.
2930 if (Reg == EndReg)
2931 continue;
2932 // The register must be in the same register class as the first.
2933 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2934 Error(EndLoc, "invalid register in register list");
2935 return MatchOperand_ParseFail;
2936 }
2937 // Ranges must go from low to high.
2938 if (Reg > EndReg) {
2939 Error(EndLoc, "bad range in register list");
2940 return MatchOperand_ParseFail;
2941 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002942 // Parse the lane specifier if present.
2943 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002944 unsigned NextLaneIndex;
2945 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002946 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002947 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002948 Error(EndLoc, "mismatched lane index in register list");
2949 return MatchOperand_ParseFail;
2950 }
2951 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002952
2953 // Add all the registers in the range to the register list.
2954 Count += EndReg - Reg;
2955 Reg = EndReg;
2956 continue;
2957 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002958 Parser.Lex(); // Eat the comma.
2959 RegLoc = Parser.getTok().getLoc();
2960 int OldReg = Reg;
2961 Reg = tryParseRegister();
2962 if (Reg == -1) {
2963 Error(RegLoc, "register expected");
2964 return MatchOperand_ParseFail;
2965 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002966 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002967 // It's OK to use the enumeration values directly here rather, as the
2968 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002969 //
2970 // The list is of D registers, but we also allow Q regs and just interpret
2971 // them as the two D sub-registers.
2972 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002973 if (!Spacing)
2974 Spacing = 1; // Register range implies a single spaced list.
2975 else if (Spacing == 2) {
2976 Error(RegLoc,
2977 "invalid register in double-spaced list (must be 'D' register')");
2978 return MatchOperand_ParseFail;
2979 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002980 Reg = getDRegFromQReg(Reg);
2981 if (Reg != OldReg + 1) {
2982 Error(RegLoc, "non-contiguous register range");
2983 return MatchOperand_ParseFail;
2984 }
2985 ++Reg;
2986 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002987 // Parse the lane specifier if present.
2988 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002989 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002990 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002991 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002992 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002993 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002994 Error(EndLoc, "mismatched lane index in register list");
2995 return MatchOperand_ParseFail;
2996 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002997 continue;
2998 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00002999 // Normal D register.
3000 // Figure out the register spacing (single or double) of the list if
3001 // we don't know it already.
3002 if (!Spacing)
3003 Spacing = 1 + (Reg == OldReg + 2);
3004
3005 // Just check that it's contiguous and keep going.
3006 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003007 Error(RegLoc, "non-contiguous register range");
3008 return MatchOperand_ParseFail;
3009 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003010 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003011 // Parse the lane specifier if present.
3012 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003013 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003014 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00003015 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003016 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003017 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003018 Error(EndLoc, "mismatched lane index in register list");
3019 return MatchOperand_ParseFail;
3020 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003021 if (Spacing == 2 && LaneKind != NoLanes) {
3022 Error(EndLoc,
3023 "lane index specfier invalid in double spaced register list");
3024 return MatchOperand_ParseFail;
3025 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003026 }
3027
3028 SMLoc E = Parser.getTok().getLoc();
3029 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3030 Error(E, "'}' expected");
3031 return MatchOperand_ParseFail;
3032 }
3033 Parser.Lex(); // Eat '}' token.
3034
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003035 switch (LaneKind) {
3036 default:
3037 assert(0 && "unexpected lane kind in register list.");
3038 case NoLanes:
Jim Grosbach2f50e922011-12-15 21:44:33 +00003039 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3040 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003041 break;
3042 case AllLanes:
3043 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
3044 S, E));
3045 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003046 case IndexedLane:
3047 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
3048 LaneIndex, S, E));
3049 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003050 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003051 return MatchOperand_Success;
3052}
3053
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003054/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003055ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003056parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003057 SMLoc S = Parser.getTok().getLoc();
3058 const AsmToken &Tok = Parser.getTok();
3059 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3060 StringRef OptStr = Tok.getString();
3061
3062 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3063 .Case("sy", ARM_MB::SY)
3064 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003065 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003066 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003067 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003068 .Case("ishst", ARM_MB::ISHST)
3069 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003070 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003071 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003072 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003073 .Case("osh", ARM_MB::OSH)
3074 .Case("oshst", ARM_MB::OSHST)
3075 .Default(~0U);
3076
3077 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003078 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003079
3080 Parser.Lex(); // Eat identifier token.
3081 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003082 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003083}
3084
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003085/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003086ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003087parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003088 SMLoc S = Parser.getTok().getLoc();
3089 const AsmToken &Tok = Parser.getTok();
3090 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3091 StringRef IFlagsStr = Tok.getString();
3092
Owen Anderson10c5b122011-10-05 17:16:40 +00003093 // An iflags string of "none" is interpreted to mean that none of the AIF
3094 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003095 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003096 if (IFlagsStr != "none") {
3097 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3098 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3099 .Case("a", ARM_PROC::A)
3100 .Case("i", ARM_PROC::I)
3101 .Case("f", ARM_PROC::F)
3102 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003103
Owen Anderson10c5b122011-10-05 17:16:40 +00003104 // If some specific iflag is already set, it means that some letter is
3105 // present more than once, this is not acceptable.
3106 if (Flag == ~0U || (IFlags & Flag))
3107 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003108
Owen Anderson10c5b122011-10-05 17:16:40 +00003109 IFlags |= Flag;
3110 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003111 }
3112
3113 Parser.Lex(); // Eat identifier token.
3114 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3115 return MatchOperand_Success;
3116}
3117
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003118/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003119ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003120parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003121 SMLoc S = Parser.getTok().getLoc();
3122 const AsmToken &Tok = Parser.getTok();
3123 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3124 StringRef Mask = Tok.getString();
3125
James Molloy21efa7d2011-09-28 14:21:38 +00003126 if (isMClass()) {
3127 // See ARMv6-M 10.1.1
3128 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3129 .Case("apsr", 0)
3130 .Case("iapsr", 1)
3131 .Case("eapsr", 2)
3132 .Case("xpsr", 3)
3133 .Case("ipsr", 5)
3134 .Case("epsr", 6)
3135 .Case("iepsr", 7)
3136 .Case("msp", 8)
3137 .Case("psp", 9)
3138 .Case("primask", 16)
3139 .Case("basepri", 17)
3140 .Case("basepri_max", 18)
3141 .Case("faultmask", 19)
3142 .Case("control", 20)
3143 .Default(~0U);
3144
3145 if (FlagsVal == ~0U)
3146 return MatchOperand_NoMatch;
3147
3148 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3149 // basepri, basepri_max and faultmask only valid for V7m.
3150 return MatchOperand_NoMatch;
3151
3152 Parser.Lex(); // Eat identifier token.
3153 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3154 return MatchOperand_Success;
3155 }
3156
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003157 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3158 size_t Start = 0, Next = Mask.find('_');
3159 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003160 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003161 if (Next != StringRef::npos)
3162 Flags = Mask.slice(Next+1, Mask.size());
3163
3164 // FlagsVal contains the complete mask:
3165 // 3-0: Mask
3166 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3167 unsigned FlagsVal = 0;
3168
3169 if (SpecReg == "apsr") {
3170 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003171 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003172 .Case("g", 0x4) // same as CPSR_s
3173 .Case("nzcvqg", 0xc) // same as CPSR_fs
3174 .Default(~0U);
3175
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003176 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003177 if (!Flags.empty())
3178 return MatchOperand_NoMatch;
3179 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003180 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003181 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003182 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003183 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3184 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003185 for (int i = 0, e = Flags.size(); i != e; ++i) {
3186 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3187 .Case("c", 1)
3188 .Case("x", 2)
3189 .Case("s", 4)
3190 .Case("f", 8)
3191 .Default(~0U);
3192
3193 // If some specific flag is already set, it means that some letter is
3194 // present more than once, this is not acceptable.
3195 if (FlagsVal == ~0U || (FlagsVal & Flag))
3196 return MatchOperand_NoMatch;
3197 FlagsVal |= Flag;
3198 }
3199 } else // No match for special register.
3200 return MatchOperand_NoMatch;
3201
Owen Anderson03a173e2011-10-21 18:43:28 +00003202 // Special register without flags is NOT equivalent to "fc" flags.
3203 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3204 // two lines would enable gas compatibility at the expense of breaking
3205 // round-tripping.
3206 //
3207 // if (!FlagsVal)
3208 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003209
3210 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3211 if (SpecReg == "spsr")
3212 FlagsVal |= 16;
3213
3214 Parser.Lex(); // Eat identifier token.
3215 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3216 return MatchOperand_Success;
3217}
3218
Jim Grosbach27c1e252011-07-21 17:23:04 +00003219ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3220parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3221 int Low, int High) {
3222 const AsmToken &Tok = Parser.getTok();
3223 if (Tok.isNot(AsmToken::Identifier)) {
3224 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3225 return MatchOperand_ParseFail;
3226 }
3227 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003228 std::string LowerOp = Op.lower();
3229 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003230 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3231 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3232 return MatchOperand_ParseFail;
3233 }
3234 Parser.Lex(); // Eat shift type token.
3235
3236 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003237 if (Parser.getTok().isNot(AsmToken::Hash) &&
3238 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003239 Error(Parser.getTok().getLoc(), "'#' expected");
3240 return MatchOperand_ParseFail;
3241 }
3242 Parser.Lex(); // Eat hash token.
3243
3244 const MCExpr *ShiftAmount;
3245 SMLoc Loc = Parser.getTok().getLoc();
3246 if (getParser().ParseExpression(ShiftAmount)) {
3247 Error(Loc, "illegal expression");
3248 return MatchOperand_ParseFail;
3249 }
3250 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3251 if (!CE) {
3252 Error(Loc, "constant expression expected");
3253 return MatchOperand_ParseFail;
3254 }
3255 int Val = CE->getValue();
3256 if (Val < Low || Val > High) {
3257 Error(Loc, "immediate value out of range");
3258 return MatchOperand_ParseFail;
3259 }
3260
3261 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3262
3263 return MatchOperand_Success;
3264}
3265
Jim Grosbach0a547702011-07-22 17:44:50 +00003266ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3267parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3268 const AsmToken &Tok = Parser.getTok();
3269 SMLoc S = Tok.getLoc();
3270 if (Tok.isNot(AsmToken::Identifier)) {
3271 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3272 return MatchOperand_ParseFail;
3273 }
3274 int Val = StringSwitch<int>(Tok.getString())
3275 .Case("be", 1)
3276 .Case("le", 0)
3277 .Default(-1);
3278 Parser.Lex(); // Eat the token.
3279
3280 if (Val == -1) {
3281 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3282 return MatchOperand_ParseFail;
3283 }
3284 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3285 getContext()),
3286 S, Parser.getTok().getLoc()));
3287 return MatchOperand_Success;
3288}
3289
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003290/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3291/// instructions. Legal values are:
3292/// lsl #n 'n' in [0,31]
3293/// asr #n 'n' in [1,32]
3294/// n == 32 encoded as n == 0.
3295ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3296parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3297 const AsmToken &Tok = Parser.getTok();
3298 SMLoc S = Tok.getLoc();
3299 if (Tok.isNot(AsmToken::Identifier)) {
3300 Error(S, "shift operator 'asr' or 'lsl' expected");
3301 return MatchOperand_ParseFail;
3302 }
3303 StringRef ShiftName = Tok.getString();
3304 bool isASR;
3305 if (ShiftName == "lsl" || ShiftName == "LSL")
3306 isASR = false;
3307 else if (ShiftName == "asr" || ShiftName == "ASR")
3308 isASR = true;
3309 else {
3310 Error(S, "shift operator 'asr' or 'lsl' expected");
3311 return MatchOperand_ParseFail;
3312 }
3313 Parser.Lex(); // Eat the operator.
3314
3315 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003316 if (Parser.getTok().isNot(AsmToken::Hash) &&
3317 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003318 Error(Parser.getTok().getLoc(), "'#' expected");
3319 return MatchOperand_ParseFail;
3320 }
3321 Parser.Lex(); // Eat hash token.
3322
3323 const MCExpr *ShiftAmount;
3324 SMLoc E = Parser.getTok().getLoc();
3325 if (getParser().ParseExpression(ShiftAmount)) {
3326 Error(E, "malformed shift expression");
3327 return MatchOperand_ParseFail;
3328 }
3329 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3330 if (!CE) {
3331 Error(E, "shift amount must be an immediate");
3332 return MatchOperand_ParseFail;
3333 }
3334
3335 int64_t Val = CE->getValue();
3336 if (isASR) {
3337 // Shift amount must be in [1,32]
3338 if (Val < 1 || Val > 32) {
3339 Error(E, "'asr' shift amount must be in range [1,32]");
3340 return MatchOperand_ParseFail;
3341 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003342 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3343 if (isThumb() && Val == 32) {
3344 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3345 return MatchOperand_ParseFail;
3346 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003347 if (Val == 32) Val = 0;
3348 } else {
3349 // Shift amount must be in [1,32]
3350 if (Val < 0 || Val > 31) {
3351 Error(E, "'lsr' shift amount must be in range [0,31]");
3352 return MatchOperand_ParseFail;
3353 }
3354 }
3355
3356 E = Parser.getTok().getLoc();
3357 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3358
3359 return MatchOperand_Success;
3360}
3361
Jim Grosbach833b9d32011-07-27 20:15:40 +00003362/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3363/// of instructions. Legal values are:
3364/// ror #n 'n' in {0, 8, 16, 24}
3365ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3366parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3367 const AsmToken &Tok = Parser.getTok();
3368 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003369 if (Tok.isNot(AsmToken::Identifier))
3370 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003371 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003372 if (ShiftName != "ror" && ShiftName != "ROR")
3373 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003374 Parser.Lex(); // Eat the operator.
3375
3376 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003377 if (Parser.getTok().isNot(AsmToken::Hash) &&
3378 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003379 Error(Parser.getTok().getLoc(), "'#' expected");
3380 return MatchOperand_ParseFail;
3381 }
3382 Parser.Lex(); // Eat hash token.
3383
3384 const MCExpr *ShiftAmount;
3385 SMLoc E = Parser.getTok().getLoc();
3386 if (getParser().ParseExpression(ShiftAmount)) {
3387 Error(E, "malformed rotate expression");
3388 return MatchOperand_ParseFail;
3389 }
3390 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3391 if (!CE) {
3392 Error(E, "rotate amount must be an immediate");
3393 return MatchOperand_ParseFail;
3394 }
3395
3396 int64_t Val = CE->getValue();
3397 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3398 // normally, zero is represented in asm by omitting the rotate operand
3399 // entirely.
3400 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3401 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3402 return MatchOperand_ParseFail;
3403 }
3404
3405 E = Parser.getTok().getLoc();
3406 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3407
3408 return MatchOperand_Success;
3409}
3410
Jim Grosbach864b6092011-07-28 21:34:26 +00003411ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3412parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3413 SMLoc S = Parser.getTok().getLoc();
3414 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003415 if (Parser.getTok().isNot(AsmToken::Hash) &&
3416 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003417 Error(Parser.getTok().getLoc(), "'#' expected");
3418 return MatchOperand_ParseFail;
3419 }
3420 Parser.Lex(); // Eat hash token.
3421
3422 const MCExpr *LSBExpr;
3423 SMLoc E = Parser.getTok().getLoc();
3424 if (getParser().ParseExpression(LSBExpr)) {
3425 Error(E, "malformed immediate expression");
3426 return MatchOperand_ParseFail;
3427 }
3428 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3429 if (!CE) {
3430 Error(E, "'lsb' operand must be an immediate");
3431 return MatchOperand_ParseFail;
3432 }
3433
3434 int64_t LSB = CE->getValue();
3435 // The LSB must be in the range [0,31]
3436 if (LSB < 0 || LSB > 31) {
3437 Error(E, "'lsb' operand must be in the range [0,31]");
3438 return MatchOperand_ParseFail;
3439 }
3440 E = Parser.getTok().getLoc();
3441
3442 // Expect another immediate operand.
3443 if (Parser.getTok().isNot(AsmToken::Comma)) {
3444 Error(Parser.getTok().getLoc(), "too few operands");
3445 return MatchOperand_ParseFail;
3446 }
3447 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003448 if (Parser.getTok().isNot(AsmToken::Hash) &&
3449 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003450 Error(Parser.getTok().getLoc(), "'#' expected");
3451 return MatchOperand_ParseFail;
3452 }
3453 Parser.Lex(); // Eat hash token.
3454
3455 const MCExpr *WidthExpr;
3456 if (getParser().ParseExpression(WidthExpr)) {
3457 Error(E, "malformed immediate expression");
3458 return MatchOperand_ParseFail;
3459 }
3460 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3461 if (!CE) {
3462 Error(E, "'width' operand must be an immediate");
3463 return MatchOperand_ParseFail;
3464 }
3465
3466 int64_t Width = CE->getValue();
3467 // The LSB must be in the range [1,32-lsb]
3468 if (Width < 1 || Width > 32 - LSB) {
3469 Error(E, "'width' operand must be in the range [1,32-lsb]");
3470 return MatchOperand_ParseFail;
3471 }
3472 E = Parser.getTok().getLoc();
3473
3474 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3475
3476 return MatchOperand_Success;
3477}
3478
Jim Grosbachd3595712011-08-03 23:50:40 +00003479ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3480parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3481 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003482 // postidx_reg := '+' register {, shift}
3483 // | '-' register {, shift}
3484 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003485
3486 // This method must return MatchOperand_NoMatch without consuming any tokens
3487 // in the case where there is no match, as other alternatives take other
3488 // parse methods.
3489 AsmToken Tok = Parser.getTok();
3490 SMLoc S = Tok.getLoc();
3491 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003492 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003493 int Reg = -1;
3494 if (Tok.is(AsmToken::Plus)) {
3495 Parser.Lex(); // Eat the '+' token.
3496 haveEaten = true;
3497 } else if (Tok.is(AsmToken::Minus)) {
3498 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003499 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003500 haveEaten = true;
3501 }
3502 if (Parser.getTok().is(AsmToken::Identifier))
3503 Reg = tryParseRegister();
3504 if (Reg == -1) {
3505 if (!haveEaten)
3506 return MatchOperand_NoMatch;
3507 Error(Parser.getTok().getLoc(), "register expected");
3508 return MatchOperand_ParseFail;
3509 }
3510 SMLoc E = Parser.getTok().getLoc();
3511
Jim Grosbachc320c852011-08-05 21:28:30 +00003512 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3513 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003514 if (Parser.getTok().is(AsmToken::Comma)) {
3515 Parser.Lex(); // Eat the ','.
3516 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3517 return MatchOperand_ParseFail;
3518 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003519
3520 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3521 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003522
3523 return MatchOperand_Success;
3524}
3525
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003526ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3527parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3528 // Check for a post-index addressing register operand. Specifically:
3529 // am3offset := '+' register
3530 // | '-' register
3531 // | register
3532 // | # imm
3533 // | # + imm
3534 // | # - imm
3535
3536 // This method must return MatchOperand_NoMatch without consuming any tokens
3537 // in the case where there is no match, as other alternatives take other
3538 // parse methods.
3539 AsmToken Tok = Parser.getTok();
3540 SMLoc S = Tok.getLoc();
3541
3542 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003543 if (Parser.getTok().is(AsmToken::Hash) ||
3544 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003545 Parser.Lex(); // Eat the '#'.
3546 // Explicitly look for a '-', as we need to encode negative zero
3547 // differently.
3548 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3549 const MCExpr *Offset;
3550 if (getParser().ParseExpression(Offset))
3551 return MatchOperand_ParseFail;
3552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3553 if (!CE) {
3554 Error(S, "constant expression expected");
3555 return MatchOperand_ParseFail;
3556 }
3557 SMLoc E = Tok.getLoc();
3558 // Negative zero is encoded as the flag value INT32_MIN.
3559 int32_t Val = CE->getValue();
3560 if (isNegative && Val == 0)
3561 Val = INT32_MIN;
3562
3563 Operands.push_back(
3564 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3565
3566 return MatchOperand_Success;
3567 }
3568
3569
3570 bool haveEaten = false;
3571 bool isAdd = true;
3572 int Reg = -1;
3573 if (Tok.is(AsmToken::Plus)) {
3574 Parser.Lex(); // Eat the '+' token.
3575 haveEaten = true;
3576 } else if (Tok.is(AsmToken::Minus)) {
3577 Parser.Lex(); // Eat the '-' token.
3578 isAdd = false;
3579 haveEaten = true;
3580 }
3581 if (Parser.getTok().is(AsmToken::Identifier))
3582 Reg = tryParseRegister();
3583 if (Reg == -1) {
3584 if (!haveEaten)
3585 return MatchOperand_NoMatch;
3586 Error(Parser.getTok().getLoc(), "register expected");
3587 return MatchOperand_ParseFail;
3588 }
3589 SMLoc E = Parser.getTok().getLoc();
3590
3591 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3592 0, S, E));
3593
3594 return MatchOperand_Success;
3595}
3596
Jim Grosbach7db8d692011-09-08 22:07:06 +00003597/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3598/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3599/// when they refer multiple MIOperands inside a single one.
3600bool ARMAsmParser::
3601cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3602 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3603 // Rt, Rt2
3604 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3605 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3606 // Create a writeback register dummy placeholder.
3607 Inst.addOperand(MCOperand::CreateReg(0));
3608 // addr
3609 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3610 // pred
3611 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3612 return true;
3613}
3614
3615/// cvtT2StrdPre - Convert parsed operands to MCInst.
3616/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3617/// when they refer multiple MIOperands inside a single one.
3618bool ARMAsmParser::
3619cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3620 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3621 // Create a writeback register dummy placeholder.
3622 Inst.addOperand(MCOperand::CreateReg(0));
3623 // Rt, Rt2
3624 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3625 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3626 // addr
3627 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3628 // pred
3629 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3630 return true;
3631}
3632
Jim Grosbachc086f682011-09-08 00:39:19 +00003633/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3634/// 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::
3637cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3638 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3639 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3640
3641 // Create a writeback register dummy placeholder.
3642 Inst.addOperand(MCOperand::CreateImm(0));
3643
3644 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3645 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3646 return true;
3647}
3648
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003649/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3650/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3651/// when they refer multiple MIOperands inside a single one.
3652bool ARMAsmParser::
3653cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3654 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3655 // Create a writeback register dummy placeholder.
3656 Inst.addOperand(MCOperand::CreateImm(0));
3657 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3658 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3659 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3660 return true;
3661}
3662
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003663/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003664/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3665/// when they refer multiple MIOperands inside a single one.
3666bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003667cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003668 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3669 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3670
3671 // Create a writeback register dummy placeholder.
3672 Inst.addOperand(MCOperand::CreateImm(0));
3673
Jim Grosbachd3595712011-08-03 23:50:40 +00003674 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003675 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3676 return true;
3677}
3678
Owen Anderson16d33f32011-08-26 20:43:14 +00003679/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3680/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3681/// when they refer multiple MIOperands inside a single one.
3682bool ARMAsmParser::
3683cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3684 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3685 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3686
3687 // Create a writeback register dummy placeholder.
3688 Inst.addOperand(MCOperand::CreateImm(0));
3689
3690 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3691 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3692 return true;
3693}
3694
3695
Jim Grosbachd564bf32011-08-11 19:22:40 +00003696/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3697/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3698/// when they refer multiple MIOperands inside a single one.
3699bool ARMAsmParser::
3700cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3701 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3702 // Create a writeback register dummy placeholder.
3703 Inst.addOperand(MCOperand::CreateImm(0));
3704 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3705 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3706 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3707 return true;
3708}
3709
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003710/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003711/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3712/// when they refer multiple MIOperands inside a single one.
3713bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003714cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003715 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3716 // Create a writeback register dummy placeholder.
3717 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003718 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3719 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3720 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003721 return true;
3722}
3723
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003724/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3725/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3726/// when they refer multiple MIOperands inside a single one.
3727bool ARMAsmParser::
3728cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3729 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3730 // Create a writeback register dummy placeholder.
3731 Inst.addOperand(MCOperand::CreateImm(0));
3732 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3733 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3734 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3735 return true;
3736}
3737
Jim Grosbachd3595712011-08-03 23:50:40 +00003738/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3739/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3740/// when they refer multiple MIOperands inside a single one.
3741bool ARMAsmParser::
3742cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3743 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3744 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003745 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003746 // Create a writeback register dummy placeholder.
3747 Inst.addOperand(MCOperand::CreateImm(0));
3748 // addr
3749 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3750 // offset
3751 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3752 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003753 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3754 return true;
3755}
3756
Jim Grosbachd3595712011-08-03 23:50:40 +00003757/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003758/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3759/// when they refer multiple MIOperands inside a single one.
3760bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003761cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3762 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3763 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003764 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003765 // Create a writeback register dummy placeholder.
3766 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003767 // addr
3768 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3769 // offset
3770 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3771 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003772 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3773 return true;
3774}
3775
Jim Grosbachd3595712011-08-03 23:50:40 +00003776/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003777/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3778/// when they refer multiple MIOperands inside a single one.
3779bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003780cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3781 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003782 // Create a writeback register dummy placeholder.
3783 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003784 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003785 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003786 // addr
3787 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3788 // offset
3789 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3790 // pred
3791 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3792 return true;
3793}
3794
3795/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3796/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3797/// when they refer multiple MIOperands inside a single one.
3798bool ARMAsmParser::
3799cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3800 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3801 // Create a writeback register dummy placeholder.
3802 Inst.addOperand(MCOperand::CreateImm(0));
3803 // Rt
3804 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3805 // addr
3806 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3807 // offset
3808 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3809 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003810 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3811 return true;
3812}
3813
Jim Grosbach5b96b802011-08-10 20:29:19 +00003814/// cvtLdrdPre - Convert parsed operands to MCInst.
3815/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3816/// when they refer multiple MIOperands inside a single one.
3817bool ARMAsmParser::
3818cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3819 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3820 // Rt, Rt2
3821 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3822 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3823 // Create a writeback register dummy placeholder.
3824 Inst.addOperand(MCOperand::CreateImm(0));
3825 // addr
3826 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3827 // pred
3828 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3829 return true;
3830}
3831
Jim Grosbacheb09f492011-08-11 20:28:23 +00003832/// cvtStrdPre - Convert parsed operands to MCInst.
3833/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3834/// when they refer multiple MIOperands inside a single one.
3835bool ARMAsmParser::
3836cvtStrdPre(MCInst &Inst, unsigned Opcode,
3837 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3838 // Create a writeback register dummy placeholder.
3839 Inst.addOperand(MCOperand::CreateImm(0));
3840 // Rt, Rt2
3841 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3842 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3843 // addr
3844 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3845 // pred
3846 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3847 return true;
3848}
3849
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003850/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3851/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3852/// when they refer multiple MIOperands inside a single one.
3853bool ARMAsmParser::
3854cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3855 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3856 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3857 // Create a writeback register dummy placeholder.
3858 Inst.addOperand(MCOperand::CreateImm(0));
3859 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3860 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3861 return true;
3862}
3863
Jim Grosbach8e048492011-08-19 22:07:46 +00003864/// cvtThumbMultiple- Convert parsed operands to MCInst.
3865/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3866/// when they refer multiple MIOperands inside a single one.
3867bool ARMAsmParser::
3868cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3869 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3870 // The second source operand must be the same register as the destination
3871 // operand.
3872 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003873 (((ARMOperand*)Operands[3])->getReg() !=
3874 ((ARMOperand*)Operands[5])->getReg()) &&
3875 (((ARMOperand*)Operands[3])->getReg() !=
3876 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003877 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003878 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003879 return false;
3880 }
3881 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3882 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003883 // If we have a three-operand form, make sure to set Rn to be the operand
3884 // that isn't the same as Rd.
3885 unsigned RegOp = 4;
3886 if (Operands.size() == 6 &&
3887 ((ARMOperand*)Operands[4])->getReg() ==
3888 ((ARMOperand*)Operands[3])->getReg())
3889 RegOp = 5;
3890 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3891 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003892 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3893
3894 return true;
3895}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003896
Jim Grosbach3ea06572011-10-24 22:16:58 +00003897bool ARMAsmParser::
3898cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3899 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3900 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003901 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003902 // Create a writeback register dummy placeholder.
3903 Inst.addOperand(MCOperand::CreateImm(0));
3904 // Vn
3905 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3906 // pred
3907 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3908 return true;
3909}
3910
3911bool ARMAsmParser::
3912cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3913 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3914 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003915 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003916 // Create a writeback register dummy placeholder.
3917 Inst.addOperand(MCOperand::CreateImm(0));
3918 // Vn
3919 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3920 // Vm
3921 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3922 // pred
3923 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3924 return true;
3925}
3926
Jim Grosbach05df4602011-10-31 21:50:31 +00003927bool ARMAsmParser::
3928cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3929 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3930 // Create a writeback register dummy placeholder.
3931 Inst.addOperand(MCOperand::CreateImm(0));
3932 // Vn
3933 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3934 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003935 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003936 // pred
3937 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3938 return true;
3939}
3940
3941bool ARMAsmParser::
3942cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3943 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3944 // Create a writeback register dummy placeholder.
3945 Inst.addOperand(MCOperand::CreateImm(0));
3946 // Vn
3947 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3948 // Vm
3949 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3950 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003951 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003952 // pred
3953 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3954 return true;
3955}
3956
Bill Wendlinge18980a2010-11-06 22:36:58 +00003957/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003958/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003959bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003960parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003961 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003962 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003963 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003964 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003965 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003966
Sean Callanan936b0d32010-01-19 21:44:56 +00003967 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003968 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003969 if (BaseRegNum == -1)
3970 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003971
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003972 // The next token must either be a comma or a closing bracket.
3973 const AsmToken &Tok = Parser.getTok();
3974 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003975 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003976
Jim Grosbachd3595712011-08-03 23:50:40 +00003977 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003978 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003979 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003980
Jim Grosbachd3595712011-08-03 23:50:40 +00003981 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003982 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003983
Jim Grosbach40700e02011-09-19 18:42:21 +00003984 // If there's a pre-indexing writeback marker, '!', just add it as a token
3985 // operand. It's rather odd, but syntactically valid.
3986 if (Parser.getTok().is(AsmToken::Exclaim)) {
3987 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3988 Parser.Lex(); // Eat the '!'.
3989 }
3990
Jim Grosbachd3595712011-08-03 23:50:40 +00003991 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003992 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003993
Jim Grosbachd3595712011-08-03 23:50:40 +00003994 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3995 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003996
Jim Grosbacha95ec992011-10-11 17:29:55 +00003997 // If we have a ':', it's an alignment specifier.
3998 if (Parser.getTok().is(AsmToken::Colon)) {
3999 Parser.Lex(); // Eat the ':'.
4000 E = Parser.getTok().getLoc();
4001
4002 const MCExpr *Expr;
4003 if (getParser().ParseExpression(Expr))
4004 return true;
4005
4006 // The expression has to be a constant. Memory references with relocations
4007 // don't come through here, as they use the <label> forms of the relevant
4008 // instructions.
4009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4010 if (!CE)
4011 return Error (E, "constant expression expected");
4012
4013 unsigned Align = 0;
4014 switch (CE->getValue()) {
4015 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004016 return Error(E,
4017 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4018 case 16: Align = 2; break;
4019 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004020 case 64: Align = 8; break;
4021 case 128: Align = 16; break;
4022 case 256: Align = 32; break;
4023 }
4024
4025 // Now we should have the closing ']'
4026 E = Parser.getTok().getLoc();
4027 if (Parser.getTok().isNot(AsmToken::RBrac))
4028 return Error(E, "']' expected");
4029 Parser.Lex(); // Eat right bracket token.
4030
4031 // Don't worry about range checking the value here. That's handled by
4032 // the is*() predicates.
4033 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4034 ARM_AM::no_shift, 0, Align,
4035 false, S, E));
4036
4037 // If there's a pre-indexing writeback marker, '!', just add it as a token
4038 // operand.
4039 if (Parser.getTok().is(AsmToken::Exclaim)) {
4040 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4041 Parser.Lex(); // Eat the '!'.
4042 }
4043
4044 return false;
4045 }
4046
4047 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004048 // offset. Be friendly and also accept a plain integer (without a leading
4049 // hash) for gas compatibility.
4050 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004051 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004052 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004053 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00004054 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004055 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004056
Owen Anderson967674d2011-08-29 19:36:44 +00004057 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004058 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004059 if (getParser().ParseExpression(Offset))
4060 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004061
4062 // The expression has to be a constant. Memory references with relocations
4063 // don't come through here, as they use the <label> forms of the relevant
4064 // instructions.
4065 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4066 if (!CE)
4067 return Error (E, "constant expression expected");
4068
Owen Anderson967674d2011-08-29 19:36:44 +00004069 // If the constant was #-0, represent it as INT32_MIN.
4070 int32_t Val = CE->getValue();
4071 if (isNegative && Val == 0)
4072 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4073
Jim Grosbachd3595712011-08-03 23:50:40 +00004074 // Now we should have the closing ']'
4075 E = Parser.getTok().getLoc();
4076 if (Parser.getTok().isNot(AsmToken::RBrac))
4077 return Error(E, "']' expected");
4078 Parser.Lex(); // Eat right bracket token.
4079
4080 // Don't worry about range checking the value here. That's handled by
4081 // the is*() predicates.
4082 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004083 ARM_AM::no_shift, 0, 0,
4084 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004085
4086 // If there's a pre-indexing writeback marker, '!', just add it as a token
4087 // operand.
4088 if (Parser.getTok().is(AsmToken::Exclaim)) {
4089 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4090 Parser.Lex(); // Eat the '!'.
4091 }
4092
4093 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004094 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004095
4096 // The register offset is optionally preceded by a '+' or '-'
4097 bool isNegative = false;
4098 if (Parser.getTok().is(AsmToken::Minus)) {
4099 isNegative = true;
4100 Parser.Lex(); // Eat the '-'.
4101 } else if (Parser.getTok().is(AsmToken::Plus)) {
4102 // Nothing to do.
4103 Parser.Lex(); // Eat the '+'.
4104 }
4105
4106 E = Parser.getTok().getLoc();
4107 int OffsetRegNum = tryParseRegister();
4108 if (OffsetRegNum == -1)
4109 return Error(E, "register expected");
4110
4111 // If there's a shift operator, handle it.
4112 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004113 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004114 if (Parser.getTok().is(AsmToken::Comma)) {
4115 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004116 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004117 return true;
4118 }
4119
4120 // Now we should have the closing ']'
4121 E = Parser.getTok().getLoc();
4122 if (Parser.getTok().isNot(AsmToken::RBrac))
4123 return Error(E, "']' expected");
4124 Parser.Lex(); // Eat right bracket token.
4125
4126 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004127 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004128 S, E));
4129
Jim Grosbachc320c852011-08-05 21:28:30 +00004130 // If there's a pre-indexing writeback marker, '!', just add it as a token
4131 // operand.
4132 if (Parser.getTok().is(AsmToken::Exclaim)) {
4133 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4134 Parser.Lex(); // Eat the '!'.
4135 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004136
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004137 return false;
4138}
4139
Jim Grosbachd3595712011-08-03 23:50:40 +00004140/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004141/// ( lsl | lsr | asr | ror ) , # shift_amount
4142/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004143/// return true if it parses a shift otherwise it returns false.
4144bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4145 unsigned &Amount) {
4146 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004147 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004148 if (Tok.isNot(AsmToken::Identifier))
4149 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004150 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004151 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4152 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004153 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004154 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004155 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004156 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004157 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004158 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004159 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004160 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004161 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004162 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004163 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004164 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004165
Jim Grosbachd3595712011-08-03 23:50:40 +00004166 // rrx stands alone.
4167 Amount = 0;
4168 if (St != ARM_AM::rrx) {
4169 Loc = Parser.getTok().getLoc();
4170 // A '#' and a shift amount.
4171 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004172 if (HashTok.isNot(AsmToken::Hash) &&
4173 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004174 return Error(HashTok.getLoc(), "'#' expected");
4175 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004176
Jim Grosbachd3595712011-08-03 23:50:40 +00004177 const MCExpr *Expr;
4178 if (getParser().ParseExpression(Expr))
4179 return true;
4180 // Range check the immediate.
4181 // lsl, ror: 0 <= imm <= 31
4182 // lsr, asr: 0 <= imm <= 32
4183 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4184 if (!CE)
4185 return Error(Loc, "shift amount must be an immediate");
4186 int64_t Imm = CE->getValue();
4187 if (Imm < 0 ||
4188 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4189 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4190 return Error(Loc, "immediate shift value out of range");
4191 Amount = Imm;
4192 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004193
4194 return false;
4195}
4196
Jim Grosbache7fbce72011-10-03 23:38:36 +00004197/// parseFPImm - A floating point immediate expression operand.
4198ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4199parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4200 SMLoc S = Parser.getTok().getLoc();
4201
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004202 if (Parser.getTok().isNot(AsmToken::Hash) &&
4203 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004204 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004205
4206 // Disambiguate the VMOV forms that can accept an FP immediate.
4207 // vmov.f32 <sreg>, #imm
4208 // vmov.f64 <dreg>, #imm
4209 // vmov.f32 <dreg>, #imm @ vector f32x2
4210 // vmov.f32 <qreg>, #imm @ vector f32x4
4211 //
4212 // There are also the NEON VMOV instructions which expect an
4213 // integer constant. Make sure we don't try to parse an FPImm
4214 // for these:
4215 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4216 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4217 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4218 TyOp->getToken() != ".f64"))
4219 return MatchOperand_NoMatch;
4220
Jim Grosbache7fbce72011-10-03 23:38:36 +00004221 Parser.Lex(); // Eat the '#'.
4222
4223 // Handle negation, as that still comes through as a separate token.
4224 bool isNegative = false;
4225 if (Parser.getTok().is(AsmToken::Minus)) {
4226 isNegative = true;
4227 Parser.Lex();
4228 }
4229 const AsmToken &Tok = Parser.getTok();
4230 if (Tok.is(AsmToken::Real)) {
4231 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4232 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4233 // If we had a '-' in front, toggle the sign bit.
4234 IntVal ^= (uint64_t)isNegative << 63;
4235 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4236 Parser.Lex(); // Eat the token.
4237 if (Val == -1) {
4238 TokError("floating point value out of range");
4239 return MatchOperand_ParseFail;
4240 }
4241 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4242 return MatchOperand_Success;
4243 }
4244 if (Tok.is(AsmToken::Integer)) {
4245 int64_t Val = Tok.getIntVal();
4246 Parser.Lex(); // Eat the token.
4247 if (Val > 255 || Val < 0) {
4248 TokError("encoded floating point value out of range");
4249 return MatchOperand_ParseFail;
4250 }
4251 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4252 return MatchOperand_Success;
4253 }
4254
4255 TokError("invalid floating point immediate");
4256 return MatchOperand_ParseFail;
4257}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004258/// Parse a arm instruction operand. For now this parses the operand regardless
4259/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004260bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004261 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004262 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004263
4264 // Check if the current operand has a custom associated parser, if so, try to
4265 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004266 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4267 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004268 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004269 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4270 // there was a match, but an error occurred, in which case, just return that
4271 // the operand parsing failed.
4272 if (ResTy == MatchOperand_ParseFail)
4273 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004274
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004275 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004276 default:
4277 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004278 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004279 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004280 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004281 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004282 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004283 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004284 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004285 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004286 else if (Res == -1) // irrecoverable error
4287 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004288 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4289 S = Parser.getTok().getLoc();
4290 Parser.Lex();
4291 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4292 return false;
4293 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004294
4295 // Fall though for the Identifier case that is not a register or a
4296 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004297 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004298 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004299 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004300 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004301 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004302 // This was not a register so parse other operands that start with an
4303 // identifier (like labels) as expressions and create them as immediates.
4304 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004305 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004306 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004307 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004308 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004309 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4310 return false;
4311 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004312 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004313 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004314 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004315 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004316 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004317 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004318 // #42 -> immediate.
4319 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004320 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004321 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004322 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004323 const MCExpr *ImmVal;
4324 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004325 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004326 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004327 if (CE) {
4328 int32_t Val = CE->getValue();
4329 if (isNegative && Val == 0)
4330 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004331 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004332 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004333 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4334 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004335 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004336 case AsmToken::Colon: {
4337 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004338 // FIXME: Check it's an expression prefix,
4339 // e.g. (FOO - :lower16:BAR) isn't legal.
4340 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004341 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004342 return true;
4343
Evan Cheng965b3c72011-01-13 07:58:56 +00004344 const MCExpr *SubExprVal;
4345 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004346 return true;
4347
Evan Cheng965b3c72011-01-13 07:58:56 +00004348 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4349 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004350 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004351 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004352 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004353 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004354 }
4355}
4356
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004357// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004358// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004359bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004360 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004361
4362 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004363 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004364 Parser.Lex(); // Eat ':'
4365
4366 if (getLexer().isNot(AsmToken::Identifier)) {
4367 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4368 return true;
4369 }
4370
4371 StringRef IDVal = Parser.getTok().getIdentifier();
4372 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004373 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004374 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004375 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004376 } else {
4377 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4378 return true;
4379 }
4380 Parser.Lex();
4381
4382 if (getLexer().isNot(AsmToken::Colon)) {
4383 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4384 return true;
4385 }
4386 Parser.Lex(); // Eat the last ':'
4387 return false;
4388}
4389
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004390/// \brief Given a mnemonic, split out possible predication code and carry
4391/// setting letters to form a canonical mnemonic and flags.
4392//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004393// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004394// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004395StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004396 unsigned &PredicationCode,
4397 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004398 unsigned &ProcessorIMod,
4399 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004400 PredicationCode = ARMCC::AL;
4401 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004402 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004403
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004404 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004405 //
4406 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004407 if ((Mnemonic == "movs" && isThumb()) ||
4408 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4409 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4410 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4411 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4412 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4413 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004414 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4415 Mnemonic == "fmuls")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004416 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004417
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004418 // First, split out any predication code. Ignore mnemonics we know aren't
4419 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004420 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004421 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004422 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004423 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004424 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4425 .Case("eq", ARMCC::EQ)
4426 .Case("ne", ARMCC::NE)
4427 .Case("hs", ARMCC::HS)
4428 .Case("cs", ARMCC::HS)
4429 .Case("lo", ARMCC::LO)
4430 .Case("cc", ARMCC::LO)
4431 .Case("mi", ARMCC::MI)
4432 .Case("pl", ARMCC::PL)
4433 .Case("vs", ARMCC::VS)
4434 .Case("vc", ARMCC::VC)
4435 .Case("hi", ARMCC::HI)
4436 .Case("ls", ARMCC::LS)
4437 .Case("ge", ARMCC::GE)
4438 .Case("lt", ARMCC::LT)
4439 .Case("gt", ARMCC::GT)
4440 .Case("le", ARMCC::LE)
4441 .Case("al", ARMCC::AL)
4442 .Default(~0U);
4443 if (CC != ~0U) {
4444 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4445 PredicationCode = CC;
4446 }
Bill Wendling193961b2010-10-29 23:50:21 +00004447 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004448
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004449 // Next, determine if we have a carry setting bit. We explicitly ignore all
4450 // the instructions we know end in 's'.
4451 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004452 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004453 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4454 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4455 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004456 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004457 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00004458 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00004459 Mnemonic == "fmuls" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004460 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004461 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4462 CarrySetting = true;
4463 }
4464
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004465 // The "cps" instruction can have a interrupt mode operand which is glued into
4466 // the mnemonic. Check if this is the case, split it and parse the imod op
4467 if (Mnemonic.startswith("cps")) {
4468 // Split out any imod code.
4469 unsigned IMod =
4470 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4471 .Case("ie", ARM_PROC::IE)
4472 .Case("id", ARM_PROC::ID)
4473 .Default(~0U);
4474 if (IMod != ~0U) {
4475 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4476 ProcessorIMod = IMod;
4477 }
4478 }
4479
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004480 // The "it" instruction has the condition mask on the end of the mnemonic.
4481 if (Mnemonic.startswith("it")) {
4482 ITMask = Mnemonic.slice(2, Mnemonic.size());
4483 Mnemonic = Mnemonic.slice(0, 2);
4484 }
4485
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004486 return Mnemonic;
4487}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004488
4489/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4490/// inclusion of carry set or predication code operands.
4491//
4492// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004493void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004494getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004495 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004496 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4497 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004498 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004499 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004500 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004501 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004502 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004503 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004504 Mnemonic == "mla" || Mnemonic == "smlal" ||
4505 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004506 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004507 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004508 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004509
Daniel Dunbar09264122011-01-11 19:06:29 +00004510 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4511 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4512 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4513 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004514 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4515 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004516 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004517 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4518 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4519 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004520 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4521 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004522 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004523 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004524 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004525 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004526
Jim Grosbach6c45b752011-09-16 16:39:25 +00004527 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004528 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004529 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004530 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004531 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004532}
4533
Jim Grosbach7283da92011-08-16 21:12:37 +00004534bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4535 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004536 // FIXME: This is all horribly hacky. We really need a better way to deal
4537 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004538
4539 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4540 // another does not. Specifically, the MOVW instruction does not. So we
4541 // special case it here and remove the defaulted (non-setting) cc_out
4542 // operand if that's the instruction we're trying to match.
4543 //
4544 // We do this as post-processing of the explicit operands rather than just
4545 // conditionally adding the cc_out in the first place because we need
4546 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004547 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004548 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4549 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4550 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4551 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004552
4553 // Register-register 'add' for thumb does not have a cc_out operand
4554 // when there are only two register operands.
4555 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4556 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4557 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4558 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4559 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004560 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004561 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4562 // have to check the immediate range here since Thumb2 has a variant
4563 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004564 if (((isThumb() && Mnemonic == "add") ||
4565 (isThumbTwo() && Mnemonic == "sub")) &&
4566 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004567 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4568 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4569 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004570 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4571 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4572 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004573 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004574 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4575 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004576 // selecting via the generic "add" mnemonic, so to know that we
4577 // should remove the cc_out operand, we have to explicitly check that
4578 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004579 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4580 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004581 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4582 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4583 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4584 // Nest conditions rather than one big 'if' statement for readability.
4585 //
4586 // If either register is a high reg, it's either one of the SP
4587 // variants (handled above) or a 32-bit encoding, so we just
4588 // check against T3.
4589 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4590 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4591 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4592 return false;
4593 // If both registers are low, we're in an IT block, and the immediate is
4594 // in range, we should use encoding T1 instead, which has a cc_out.
4595 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004596 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004597 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4598 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4599 return false;
4600
4601 // Otherwise, we use encoding T4, which does not have a cc_out
4602 // operand.
4603 return true;
4604 }
4605
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004606 // The thumb2 multiply instruction doesn't have a CCOut register, so
4607 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4608 // use the 16-bit encoding or not.
4609 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4610 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4611 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4612 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4613 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4614 // If the registers aren't low regs, the destination reg isn't the
4615 // same as one of the source regs, or the cc_out operand is zero
4616 // outside of an IT block, we have to use the 32-bit encoding, so
4617 // remove the cc_out operand.
4618 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4619 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004620 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004621 !inITBlock() ||
4622 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4623 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4624 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4625 static_cast<ARMOperand*>(Operands[4])->getReg())))
4626 return true;
4627
Jim Grosbachefa7e952011-11-15 19:55:16 +00004628 // Also check the 'mul' syntax variant that doesn't specify an explicit
4629 // destination register.
4630 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4631 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4632 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4633 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4634 // If the registers aren't low regs or the cc_out operand is zero
4635 // outside of an IT block, we have to use the 32-bit encoding, so
4636 // remove the cc_out operand.
4637 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4638 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4639 !inITBlock()))
4640 return true;
4641
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004642
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004643
Jim Grosbach4b701af2011-08-24 21:42:27 +00004644 // Register-register 'add/sub' for thumb does not have a cc_out operand
4645 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4646 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4647 // right, this will result in better diagnostics (which operand is off)
4648 // anyway.
4649 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4650 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004651 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4652 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4653 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4654 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004655
Jim Grosbach7283da92011-08-16 21:12:37 +00004656 return false;
4657}
4658
Jim Grosbach12952fe2011-11-11 23:08:10 +00004659static bool isDataTypeToken(StringRef Tok) {
4660 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4661 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4662 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4663 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4664 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4665 Tok == ".f" || Tok == ".d";
4666}
4667
4668// FIXME: This bit should probably be handled via an explicit match class
4669// in the .td files that matches the suffix instead of having it be
4670// a literal string token the way it is now.
4671static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4672 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4673}
4674
Jim Grosbach8be2f652011-12-09 23:34:09 +00004675static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004676/// Parse an arm instruction mnemonic followed by its operands.
4677bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4678 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004679 // Apply mnemonic aliases before doing anything else, as the destination
4680 // mnemnonic may include suffices and we want to handle them normally.
4681 // The generic tblgen'erated code does this later, at the start of
4682 // MatchInstructionImpl(), but that's too late for aliases that include
4683 // any sort of suffix.
4684 unsigned AvailableFeatures = getAvailableFeatures();
4685 applyMnemonicAliases(Name, AvailableFeatures);
4686
Jim Grosbachab5830e2011-12-14 02:16:11 +00004687 // First check for the ARM-specific .req directive.
4688 if (Parser.getTok().is(AsmToken::Identifier) &&
4689 Parser.getTok().getIdentifier() == ".req") {
4690 parseDirectiveReq(Name, NameLoc);
4691 // We always return 'error' for this, as we're done with this
4692 // statement and don't need to match the 'instruction."
4693 return true;
4694 }
4695
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004696 // Create the leading tokens for the mnemonic, split by '.' characters.
4697 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004698 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004699
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004700 // Split out the predication code and carry setting flag from the mnemonic.
4701 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004702 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004703 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004704 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004705 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004706 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004707
Jim Grosbach1c171b12011-08-25 17:23:55 +00004708 // In Thumb1, only the branch (B) instruction can be predicated.
4709 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4710 Parser.EatToEndOfStatement();
4711 return Error(NameLoc, "conditional execution not supported in Thumb1");
4712 }
4713
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004714 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4715
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004716 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4717 // is the mask as it will be for the IT encoding if the conditional
4718 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4719 // where the conditional bit0 is zero, the instruction post-processing
4720 // will adjust the mask accordingly.
4721 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004722 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4723 if (ITMask.size() > 3) {
4724 Parser.EatToEndOfStatement();
4725 return Error(Loc, "too many conditions on IT instruction");
4726 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004727 unsigned Mask = 8;
4728 for (unsigned i = ITMask.size(); i != 0; --i) {
4729 char pos = ITMask[i - 1];
4730 if (pos != 't' && pos != 'e') {
4731 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004732 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004733 }
4734 Mask >>= 1;
4735 if (ITMask[i - 1] == 't')
4736 Mask |= 8;
4737 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004738 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004739 }
4740
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004741 // FIXME: This is all a pretty gross hack. We should automatically handle
4742 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004743
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004744 // Next, add the CCOut and ConditionCode operands, if needed.
4745 //
4746 // For mnemonics which can ever incorporate a carry setting bit or predication
4747 // code, our matching model involves us always generating CCOut and
4748 // ConditionCode operands to match the mnemonic "as written" and then we let
4749 // the matcher deal with finding the right instruction or generating an
4750 // appropriate error.
4751 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004752 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004753
Jim Grosbach03a8a162011-07-14 22:04:21 +00004754 // If we had a carry-set on an instruction that can't do that, issue an
4755 // error.
4756 if (!CanAcceptCarrySet && CarrySetting) {
4757 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004758 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004759 "' can not set flags, but 's' suffix specified");
4760 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004761 // If we had a predication code on an instruction that can't do that, issue an
4762 // error.
4763 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4764 Parser.EatToEndOfStatement();
4765 return Error(NameLoc, "instruction '" + Mnemonic +
4766 "' is not predicable, but condition code specified");
4767 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004768
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004769 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004770 if (CanAcceptCarrySet) {
4771 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004772 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004773 Loc));
4774 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004775
4776 // Add the predication code operand, if necessary.
4777 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004778 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4779 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004780 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004781 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004782 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004783
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004784 // Add the processor imod operand, if necessary.
4785 if (ProcessorIMod) {
4786 Operands.push_back(ARMOperand::CreateImm(
4787 MCConstantExpr::Create(ProcessorIMod, getContext()),
4788 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004789 }
4790
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004791 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004792 while (Next != StringRef::npos) {
4793 Start = Next;
4794 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004795 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004796
Jim Grosbach12952fe2011-11-11 23:08:10 +00004797 // Some NEON instructions have an optional datatype suffix that is
4798 // completely ignored. Check for that.
4799 if (isDataTypeToken(ExtraToken) &&
4800 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4801 continue;
4802
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004803 if (ExtraToken != ".n") {
4804 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4805 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4806 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004807 }
4808
4809 // Read the remaining operands.
4810 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004811 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004812 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004813 Parser.EatToEndOfStatement();
4814 return true;
4815 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004816
4817 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004818 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004819
4820 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004821 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004822 Parser.EatToEndOfStatement();
4823 return true;
4824 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004825 }
4826 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004827
Chris Lattnera2a9d162010-09-11 16:18:25 +00004828 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004829 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004830 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004831 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004832 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004833
Chris Lattner91689c12010-09-08 05:10:46 +00004834 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004835
Jim Grosbach7283da92011-08-16 21:12:37 +00004836 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4837 // do and don't have a cc_out optional-def operand. With some spot-checks
4838 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004839 // parse and adjust accordingly before actually matching. We shouldn't ever
4840 // try to remove a cc_out operand that was explicitly set on the the
4841 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4842 // table driven matcher doesn't fit well with the ARM instruction set.
4843 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004844 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4845 Operands.erase(Operands.begin() + 1);
4846 delete Op;
4847 }
4848
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004849 // ARM mode 'blx' need special handling, as the register operand version
4850 // is predicable, but the label operand version is not. So, we can't rely
4851 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004852 // a k_CondCode operand in the list. If we're trying to match the label
4853 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004854 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4855 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4856 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4857 Operands.erase(Operands.begin() + 1);
4858 delete Op;
4859 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004860
4861 // The vector-compare-to-zero instructions have a literal token "#0" at
4862 // the end that comes to here as an immediate operand. Convert it to a
4863 // token to play nicely with the matcher.
4864 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4865 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4866 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4867 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4868 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4869 if (CE && CE->getValue() == 0) {
4870 Operands.erase(Operands.begin() + 5);
4871 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4872 delete Op;
4873 }
4874 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004875 // VCMP{E} does the same thing, but with a different operand count.
4876 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4877 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4878 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4880 if (CE && CE->getValue() == 0) {
4881 Operands.erase(Operands.begin() + 4);
4882 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4883 delete Op;
4884 }
4885 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004886 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004887 // end. Convert it to a token here. Take care not to convert those
4888 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004889 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004890 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4891 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004892 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4893 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4894 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004895 if (CE && CE->getValue() == 0 &&
4896 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00004897 // The cc_out operand matches the IT block.
4898 ((inITBlock() != CarrySetting) &&
4899 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004900 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00004901 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004902 Operands.erase(Operands.begin() + 5);
4903 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4904 delete Op;
4905 }
4906 }
4907
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004908 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004909}
4910
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004911// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004912
4913// return 'true' if register list contains non-low GPR registers,
4914// 'false' otherwise. If Reg is in the register list or is HiReg, set
4915// 'containsReg' to true.
4916static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4917 unsigned HiReg, bool &containsReg) {
4918 containsReg = false;
4919 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4920 unsigned OpReg = Inst.getOperand(i).getReg();
4921 if (OpReg == Reg)
4922 containsReg = true;
4923 // Anything other than a low register isn't legal here.
4924 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4925 return true;
4926 }
4927 return false;
4928}
4929
Jim Grosbacha31f2232011-09-07 18:05:34 +00004930// Check if the specified regisgter is in the register list of the inst,
4931// starting at the indicated operand number.
4932static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4933 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4934 unsigned OpReg = Inst.getOperand(i).getReg();
4935 if (OpReg == Reg)
4936 return true;
4937 }
4938 return false;
4939}
4940
Jim Grosbached16ec42011-08-29 22:24:09 +00004941// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4942// the ARMInsts array) instead. Getting that here requires awkward
4943// API changes, though. Better way?
4944namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004945extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004946}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004947static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004948 return ARMInsts[Opcode];
4949}
4950
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004951// FIXME: We would really like to be able to tablegen'erate this.
4952bool ARMAsmParser::
4953validateInstruction(MCInst &Inst,
4954 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004955 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004956 SMLoc Loc = Operands[0]->getStartLoc();
4957 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004958 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4959 // being allowed in IT blocks, but not being predicable. It just always
4960 // executes.
4961 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004962 unsigned bit = 1;
4963 if (ITState.FirstCond)
4964 ITState.FirstCond = false;
4965 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004966 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004967 // The instruction must be predicable.
4968 if (!MCID.isPredicable())
4969 return Error(Loc, "instructions in IT block must be predicable");
4970 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4971 unsigned ITCond = bit ? ITState.Cond :
4972 ARMCC::getOppositeCondition(ITState.Cond);
4973 if (Cond != ITCond) {
4974 // Find the condition code Operand to get its SMLoc information.
4975 SMLoc CondLoc;
4976 for (unsigned i = 1; i < Operands.size(); ++i)
4977 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4978 CondLoc = Operands[i]->getStartLoc();
4979 return Error(CondLoc, "incorrect condition in IT block; got '" +
4980 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4981 "', but expected '" +
4982 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4983 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004984 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004985 } else if (isThumbTwo() && MCID.isPredicable() &&
4986 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004987 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4988 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004989 return Error(Loc, "predicated instructions must be in IT block");
4990
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004991 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004992 case ARM::LDRD:
4993 case ARM::LDRD_PRE:
4994 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004995 case ARM::LDREXD: {
4996 // Rt2 must be Rt + 1.
4997 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4998 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4999 if (Rt2 != Rt + 1)
5000 return Error(Operands[3]->getStartLoc(),
5001 "destination operands must be sequential");
5002 return false;
5003 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005004 case ARM::STRD: {
5005 // Rt2 must be Rt + 1.
5006 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5007 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5008 if (Rt2 != Rt + 1)
5009 return Error(Operands[3]->getStartLoc(),
5010 "source operands must be sequential");
5011 return false;
5012 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005013 case ARM::STRD_PRE:
5014 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005015 case ARM::STREXD: {
5016 // Rt2 must be Rt + 1.
5017 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5018 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5019 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005020 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005021 "source operands must be sequential");
5022 return false;
5023 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005024 case ARM::SBFX:
5025 case ARM::UBFX: {
5026 // width must be in range [1, 32-lsb]
5027 unsigned lsb = Inst.getOperand(2).getImm();
5028 unsigned widthm1 = Inst.getOperand(3).getImm();
5029 if (widthm1 >= 32 - lsb)
5030 return Error(Operands[5]->getStartLoc(),
5031 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005032 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005033 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00005034 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005035 // If we're parsing Thumb2, the .w variant is available and handles
5036 // most cases that are normally illegal for a Thumb1 LDM
5037 // instruction. We'll make the transformation in processInstruction()
5038 // if necessary.
5039 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00005040 // Thumb LDM instructions are writeback iff the base register is not
5041 // in the register list.
5042 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00005043 bool hasWritebackToken =
5044 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5045 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00005046 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005047 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005048 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5049 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005050 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005051 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005052 return Error(Operands[2]->getStartLoc(),
5053 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005054 // If we should not have writeback, there must not be a '!'. This is
5055 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005056 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005057 return Error(Operands[3]->getStartLoc(),
5058 "writeback operator '!' not allowed when base register "
5059 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005060
5061 break;
5062 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00005063 case ARM::t2LDMIA_UPD: {
5064 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5065 return Error(Operands[4]->getStartLoc(),
5066 "writeback operator '!' not allowed when base register "
5067 "in register list");
5068 break;
5069 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005070 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5071 // so only issue a diagnostic for thumb1. The instructions will be
5072 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005073 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005074 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005075 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5076 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005077 return Error(Operands[2]->getStartLoc(),
5078 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005079 break;
5080 }
5081 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005082 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005083 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5084 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005085 return Error(Operands[2]->getStartLoc(),
5086 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005087 break;
5088 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005089 case ARM::tSTMIA_UPD: {
5090 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005091 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005092 return Error(Operands[4]->getStartLoc(),
5093 "registers must be in range r0-r7");
5094 break;
5095 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005096 }
5097
5098 return false;
5099}
5100
Jim Grosbacheb538222011-12-02 22:34:51 +00005101static unsigned getRealVSTLNOpcode(unsigned Opc) {
5102 switch(Opc) {
5103 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005104 // VST1LN
5105 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5106 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5107 case ARM::VST1LNdWB_fixed_Asm_U8:
5108 return ARM::VST1LNd8_UPD;
5109 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5110 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5111 case ARM::VST1LNdWB_fixed_Asm_U16:
5112 return ARM::VST1LNd16_UPD;
5113 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5114 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5115 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
5116 return ARM::VST1LNd32_UPD;
5117 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5118 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5119 case ARM::VST1LNdWB_register_Asm_U8:
5120 return ARM::VST1LNd8_UPD;
5121 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5122 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5123 case ARM::VST1LNdWB_register_Asm_U16:
5124 return ARM::VST1LNd16_UPD;
5125 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5126 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5127 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
5128 return ARM::VST1LNd32_UPD;
5129 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5130 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5131 case ARM::VST1LNdAsm_U8:
5132 return ARM::VST1LNd8;
5133 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5134 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5135 case ARM::VST1LNdAsm_U16:
5136 return ARM::VST1LNd16;
5137 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5138 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5139 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
5140 return ARM::VST1LNd32;
5141
5142 // VST2LN
5143 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5144 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5145 case ARM::VST2LNdWB_fixed_Asm_U8:
5146 return ARM::VST2LNd8_UPD;
5147 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5148 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5149 case ARM::VST2LNdWB_fixed_Asm_U16:
5150 return ARM::VST2LNd16_UPD;
5151 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5152 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5153 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5154 return ARM::VST2LNd32_UPD;
5155 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5156 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5157 case ARM::VST2LNdWB_register_Asm_U8:
5158 return ARM::VST2LNd8_UPD;
5159 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5160 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5161 case ARM::VST2LNdWB_register_Asm_U16:
5162 return ARM::VST2LNd16_UPD;
5163 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5164 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5165 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5166 return ARM::VST2LNd32_UPD;
5167 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5168 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5169 case ARM::VST2LNdAsm_U8:
5170 return ARM::VST2LNd8;
5171 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5172 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5173 case ARM::VST2LNdAsm_U16:
5174 return ARM::VST2LNd16;
5175 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5176 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5177 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
5178 return ARM::VST2LNd32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005179 }
5180}
5181
5182static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005183 switch(Opc) {
5184 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005185 // VLD1LN
5186 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5187 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5188 case ARM::VLD1LNdWB_fixed_Asm_U8:
5189 return ARM::VLD1LNd8_UPD;
5190 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5191 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5192 case ARM::VLD1LNdWB_fixed_Asm_U16:
5193 return ARM::VLD1LNd16_UPD;
5194 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5195 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5196 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
5197 return ARM::VLD1LNd32_UPD;
5198 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5199 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5200 case ARM::VLD1LNdWB_register_Asm_U8:
5201 return ARM::VLD1LNd8_UPD;
5202 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5203 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5204 case ARM::VLD1LNdWB_register_Asm_U16:
5205 return ARM::VLD1LNd16_UPD;
5206 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5207 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5208 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
5209 return ARM::VLD1LNd32_UPD;
5210 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5211 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5212 case ARM::VLD1LNdAsm_U8:
5213 return ARM::VLD1LNd8;
5214 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5215 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5216 case ARM::VLD1LNdAsm_U16:
5217 return ARM::VLD1LNd16;
5218 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5219 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5220 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
5221 return ARM::VLD1LNd32;
5222
5223 // VLD2LN
5224 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5225 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5226 case ARM::VLD2LNdWB_fixed_Asm_U8:
5227 return ARM::VLD2LNd8_UPD;
5228 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5229 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5230 case ARM::VLD2LNdWB_fixed_Asm_U16:
5231 return ARM::VLD2LNd16_UPD;
5232 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5233 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5234 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
5235 return ARM::VLD2LNd32_UPD;
5236 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5237 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5238 case ARM::VLD2LNdWB_register_Asm_U8:
5239 return ARM::VLD2LNd8_UPD;
5240 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5241 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5242 case ARM::VLD2LNdWB_register_Asm_U16:
5243 return ARM::VLD2LNd16_UPD;
5244 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5245 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5246 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
5247 return ARM::VLD2LNd32_UPD;
5248 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5249 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5250 case ARM::VLD2LNdAsm_U8:
5251 return ARM::VLD2LNd8;
5252 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5253 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5254 case ARM::VLD2LNdAsm_U16:
5255 return ARM::VLD2LNd16;
5256 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5257 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5258 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
5259 return ARM::VLD2LNd32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005260 }
5261}
5262
Jim Grosbachafad0532011-11-10 23:42:14 +00005263bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005264processInstruction(MCInst &Inst,
5265 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5266 switch (Inst.getOpcode()) {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005267 // Handle NEON VST complex aliases.
5268 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5269 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5270 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5271 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5272 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5273 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5274 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5275 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005276 MCInst TmpInst;
5277 // Shuffle the operands around so the lane index operand is in the
5278 // right place.
5279 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5280 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5281 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5282 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5283 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5284 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5285 TmpInst.addOperand(Inst.getOperand(1)); // lane
5286 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5287 TmpInst.addOperand(Inst.getOperand(6));
5288 Inst = TmpInst;
5289 return true;
5290 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005291
5292 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5293 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5294 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
5295 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5296 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
5297 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5298 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5299 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32: {
5300 MCInst TmpInst;
5301 // Shuffle the operands around so the lane index operand is in the
5302 // right place.
5303 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5304 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5305 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5306 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5307 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5308 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5309 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5310 TmpInst.addOperand(Inst.getOperand(1)); // lane
5311 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5312 TmpInst.addOperand(Inst.getOperand(6));
5313 Inst = TmpInst;
5314 return true;
5315 }
5316 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5317 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5318 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5319 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5320 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5321 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5322 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5323 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005324 MCInst TmpInst;
5325 // Shuffle the operands around so the lane index operand is in the
5326 // right place.
5327 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5328 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5329 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5330 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5331 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5332 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5333 TmpInst.addOperand(Inst.getOperand(1)); // lane
5334 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5335 TmpInst.addOperand(Inst.getOperand(5));
5336 Inst = TmpInst;
5337 return true;
5338 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005339
5340 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5341 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5342 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
5343 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5344 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
5345 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5346 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5347 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32: {
5348 MCInst TmpInst;
5349 // Shuffle the operands around so the lane index operand is in the
5350 // right place.
5351 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5352 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5353 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5354 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5355 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5356 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5357 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5358 TmpInst.addOperand(Inst.getOperand(1)); // lane
5359 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5360 TmpInst.addOperand(Inst.getOperand(5));
5361 Inst = TmpInst;
5362 return true;
5363 }
5364 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5365 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5366 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5367 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5368 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbacheb538222011-12-02 22:34:51 +00005369 case ARM::VST1LNdAsm_U32: {
5370 MCInst TmpInst;
5371 // Shuffle the operands around so the lane index operand is in the
5372 // right place.
5373 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5374 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5375 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5376 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5377 TmpInst.addOperand(Inst.getOperand(1)); // lane
5378 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5379 TmpInst.addOperand(Inst.getOperand(5));
5380 Inst = TmpInst;
5381 return true;
5382 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005383
5384 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5385 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
5386 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5387 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5388 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
5389 case ARM::VST2LNdAsm_U32: {
5390 MCInst TmpInst;
5391 // Shuffle the operands around so the lane index operand is in the
5392 // right place.
5393 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5394 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5395 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5396 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5397 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5398 TmpInst.addOperand(Inst.getOperand(1)); // lane
5399 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5400 TmpInst.addOperand(Inst.getOperand(5));
5401 Inst = TmpInst;
5402 return true;
5403 }
5404 // Handle NEON VLD complex aliases.
5405 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5406 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5407 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5408 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5409 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5410 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5411 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5412 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005413 MCInst TmpInst;
5414 // Shuffle the operands around so the lane index operand is in the
5415 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005416 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005417 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5418 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5419 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5420 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5421 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5422 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5423 TmpInst.addOperand(Inst.getOperand(1)); // lane
5424 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5425 TmpInst.addOperand(Inst.getOperand(6));
5426 Inst = TmpInst;
5427 return true;
5428 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005429
5430 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5431 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5432 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
5433 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5434 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
5435 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5436 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5437 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32: {
5438 MCInst TmpInst;
5439 // Shuffle the operands around so the lane index operand is in the
5440 // right place.
5441 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5442 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5443 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5444 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5445 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5446 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5447 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5448 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5449 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5450 TmpInst.addOperand(Inst.getOperand(1)); // lane
5451 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5452 TmpInst.addOperand(Inst.getOperand(6));
5453 Inst = TmpInst;
5454 return true;
5455 }
5456
5457 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5458 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5459 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5460 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5461 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5462 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5463 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5464 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005465 MCInst TmpInst;
5466 // Shuffle the operands around so the lane index operand is in the
5467 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005468 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005469 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5470 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5471 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5472 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5473 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5474 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5475 TmpInst.addOperand(Inst.getOperand(1)); // lane
5476 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5477 TmpInst.addOperand(Inst.getOperand(5));
5478 Inst = TmpInst;
5479 return true;
5480 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005481
5482 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5483 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5484 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
5485 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5486 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
5487 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5488 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5489 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32: {
5490 MCInst TmpInst;
5491 // Shuffle the operands around so the lane index operand is in the
5492 // right place.
5493 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5494 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5495 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5496 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5497 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5498 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5499 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5500 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5501 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5502 TmpInst.addOperand(Inst.getOperand(1)); // lane
5503 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5504 TmpInst.addOperand(Inst.getOperand(5));
5505 Inst = TmpInst;
5506 return true;
5507 }
5508
5509 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5510 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
5511 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5512 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5513 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005514 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005515 MCInst TmpInst;
5516 // Shuffle the operands around so the lane index operand is in the
5517 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005518 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach04945c42011-12-02 00:35:16 +00005519 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5520 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5521 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5522 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5523 TmpInst.addOperand(Inst.getOperand(1)); // lane
5524 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5525 TmpInst.addOperand(Inst.getOperand(5));
5526 Inst = TmpInst;
5527 return true;
5528 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005529
5530 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5531 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
5532 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5533 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5534 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
5535 case ARM::VLD2LNdAsm_U32: {
5536 MCInst TmpInst;
5537 // Shuffle the operands around so the lane index operand is in the
5538 // right place.
5539 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5540 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5541 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5542 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5543 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5544 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5545 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5546 TmpInst.addOperand(Inst.getOperand(1)); // lane
5547 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5548 TmpInst.addOperand(Inst.getOperand(5));
5549 Inst = TmpInst;
5550 return true;
5551 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005552 // Handle the Thumb2 mode MOV complex aliases.
5553 case ARM::t2MOVsi:
5554 case ARM::t2MOVSsi: {
5555 // Which instruction to expand to depends on the CCOut operand and
5556 // whether we're in an IT block if the register operands are low
5557 // registers.
5558 bool isNarrow = false;
5559 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5560 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5561 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5562 isNarrow = true;
5563 MCInst TmpInst;
5564 unsigned newOpc;
5565 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5566 default: llvm_unreachable("unexpected opcode!");
5567 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5568 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5569 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5570 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5571 }
5572 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5573 if (Ammount == 32) Ammount = 0;
5574 TmpInst.setOpcode(newOpc);
5575 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5576 if (isNarrow)
5577 TmpInst.addOperand(MCOperand::CreateReg(
5578 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5579 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5580 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5581 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5582 TmpInst.addOperand(Inst.getOperand(4));
5583 if (!isNarrow)
5584 TmpInst.addOperand(MCOperand::CreateReg(
5585 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5586 Inst = TmpInst;
5587 return true;
5588 }
5589 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005590 case ARM::ASRr:
5591 case ARM::LSRr:
5592 case ARM::LSLr:
5593 case ARM::RORr: {
5594 ARM_AM::ShiftOpc ShiftTy;
5595 switch(Inst.getOpcode()) {
5596 default: llvm_unreachable("unexpected opcode!");
5597 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5598 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5599 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5600 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5601 }
5602 // A shift by zero is a plain MOVr, not a MOVsi.
5603 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5604 MCInst TmpInst;
5605 TmpInst.setOpcode(ARM::MOVsr);
5606 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5607 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5608 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5609 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5610 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5611 TmpInst.addOperand(Inst.getOperand(4));
5612 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5613 Inst = TmpInst;
5614 return true;
5615 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005616 case ARM::ASRi:
5617 case ARM::LSRi:
5618 case ARM::LSLi:
5619 case ARM::RORi: {
5620 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005621 switch(Inst.getOpcode()) {
5622 default: llvm_unreachable("unexpected opcode!");
5623 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5624 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5625 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5626 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5627 }
5628 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005629 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005630 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5631 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005632 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005633 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005634 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5635 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005636 if (Opc == ARM::MOVsi)
5637 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005638 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5639 TmpInst.addOperand(Inst.getOperand(4));
5640 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5641 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005642 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005643 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005644 case ARM::RRXi: {
5645 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5646 MCInst TmpInst;
5647 TmpInst.setOpcode(ARM::MOVsi);
5648 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5649 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5650 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5651 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5652 TmpInst.addOperand(Inst.getOperand(3));
5653 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5654 Inst = TmpInst;
5655 return true;
5656 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005657 case ARM::t2LDMIA_UPD: {
5658 // If this is a load of a single register, then we should use
5659 // a post-indexed LDR instruction instead, per the ARM ARM.
5660 if (Inst.getNumOperands() != 5)
5661 return false;
5662 MCInst TmpInst;
5663 TmpInst.setOpcode(ARM::t2LDR_POST);
5664 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5665 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5666 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5667 TmpInst.addOperand(MCOperand::CreateImm(4));
5668 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5669 TmpInst.addOperand(Inst.getOperand(3));
5670 Inst = TmpInst;
5671 return true;
5672 }
5673 case ARM::t2STMDB_UPD: {
5674 // If this is a store of a single register, then we should use
5675 // a pre-indexed STR instruction instead, per the ARM ARM.
5676 if (Inst.getNumOperands() != 5)
5677 return false;
5678 MCInst TmpInst;
5679 TmpInst.setOpcode(ARM::t2STR_PRE);
5680 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5681 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5682 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5683 TmpInst.addOperand(MCOperand::CreateImm(-4));
5684 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5685 TmpInst.addOperand(Inst.getOperand(3));
5686 Inst = TmpInst;
5687 return true;
5688 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005689 case ARM::LDMIA_UPD:
5690 // If this is a load of a single register via a 'pop', then we should use
5691 // a post-indexed LDR instruction instead, per the ARM ARM.
5692 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5693 Inst.getNumOperands() == 5) {
5694 MCInst TmpInst;
5695 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5696 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5697 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5698 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5699 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5700 TmpInst.addOperand(MCOperand::CreateImm(4));
5701 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5702 TmpInst.addOperand(Inst.getOperand(3));
5703 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005704 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005705 }
5706 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005707 case ARM::STMDB_UPD:
5708 // If this is a store of a single register via a 'push', then we should use
5709 // a pre-indexed STR instruction instead, per the ARM ARM.
5710 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5711 Inst.getNumOperands() == 5) {
5712 MCInst TmpInst;
5713 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5714 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5715 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5716 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5717 TmpInst.addOperand(MCOperand::CreateImm(-4));
5718 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5719 TmpInst.addOperand(Inst.getOperand(3));
5720 Inst = TmpInst;
5721 }
5722 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005723 case ARM::t2ADDri12:
5724 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5725 // mnemonic was used (not "addw"), encoding T3 is preferred.
5726 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5727 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5728 break;
5729 Inst.setOpcode(ARM::t2ADDri);
5730 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5731 break;
5732 case ARM::t2SUBri12:
5733 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5734 // mnemonic was used (not "subw"), encoding T3 is preferred.
5735 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5736 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5737 break;
5738 Inst.setOpcode(ARM::t2SUBri);
5739 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5740 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005741 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005742 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5743 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5744 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5745 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005746 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005747 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005748 return true;
5749 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005750 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005751 case ARM::tSUBi8:
5752 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5753 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5754 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5755 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005756 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005757 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005758 return true;
5759 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005760 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00005761 case ARM::t2ADDrr: {
5762 // If the destination and first source operand are the same, and
5763 // there's no setting of the flags, use encoding T2 instead of T3.
5764 // Note that this is only for ADD, not SUB. This mirrors the system
5765 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5766 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5767 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00005768 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5769 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00005770 break;
5771 MCInst TmpInst;
5772 TmpInst.setOpcode(ARM::tADDhirr);
5773 TmpInst.addOperand(Inst.getOperand(0));
5774 TmpInst.addOperand(Inst.getOperand(0));
5775 TmpInst.addOperand(Inst.getOperand(2));
5776 TmpInst.addOperand(Inst.getOperand(3));
5777 TmpInst.addOperand(Inst.getOperand(4));
5778 Inst = TmpInst;
5779 return true;
5780 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005781 case ARM::tB:
5782 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005783 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005784 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005785 return true;
5786 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005787 break;
5788 case ARM::t2B:
5789 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005790 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005791 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005792 return true;
5793 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005794 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00005795 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005796 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00005797 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00005798 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00005799 return true;
5800 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00005801 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005802 case ARM::tBcc:
5803 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00005804 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005805 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00005806 return true;
5807 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00005808 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005809 case ARM::tLDMIA: {
5810 // If the register list contains any high registers, or if the writeback
5811 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5812 // instead if we're in Thumb2. Otherwise, this should have generated
5813 // an error in validateInstruction().
5814 unsigned Rn = Inst.getOperand(0).getReg();
5815 bool hasWritebackToken =
5816 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5817 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5818 bool listContainsBase;
5819 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5820 (!listContainsBase && !hasWritebackToken) ||
5821 (listContainsBase && hasWritebackToken)) {
5822 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5823 assert (isThumbTwo());
5824 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5825 // If we're switching to the updating version, we need to insert
5826 // the writeback tied operand.
5827 if (hasWritebackToken)
5828 Inst.insert(Inst.begin(),
5829 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00005830 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005831 }
5832 break;
5833 }
Jim Grosbach099c9762011-09-16 20:50:13 +00005834 case ARM::tSTMIA_UPD: {
5835 // If the register list contains any high registers, we need to use
5836 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5837 // should have generated an error in validateInstruction().
5838 unsigned Rn = Inst.getOperand(0).getReg();
5839 bool listContainsBase;
5840 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5841 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5842 assert (isThumbTwo());
5843 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00005844 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00005845 }
5846 break;
5847 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005848 case ARM::tPOP: {
5849 bool listContainsBase;
5850 // If the register list contains any high registers, we need to use
5851 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5852 // should have generated an error in validateInstruction().
5853 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005854 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005855 assert (isThumbTwo());
5856 Inst.setOpcode(ARM::t2LDMIA_UPD);
5857 // Add the base register and writeback operands.
5858 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5859 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005860 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005861 }
5862 case ARM::tPUSH: {
5863 bool listContainsBase;
5864 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005865 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005866 assert (isThumbTwo());
5867 Inst.setOpcode(ARM::t2STMDB_UPD);
5868 // Add the base register and writeback operands.
5869 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5870 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005871 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005872 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005873 case ARM::t2MOVi: {
5874 // If we can use the 16-bit encoding and the user didn't explicitly
5875 // request the 32-bit variant, transform it here.
5876 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5877 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00005878 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5879 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5880 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005881 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5882 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5883 // The operands aren't in the same order for tMOVi8...
5884 MCInst TmpInst;
5885 TmpInst.setOpcode(ARM::tMOVi8);
5886 TmpInst.addOperand(Inst.getOperand(0));
5887 TmpInst.addOperand(Inst.getOperand(4));
5888 TmpInst.addOperand(Inst.getOperand(1));
5889 TmpInst.addOperand(Inst.getOperand(2));
5890 TmpInst.addOperand(Inst.getOperand(3));
5891 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005892 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005893 }
5894 break;
5895 }
5896 case ARM::t2MOVr: {
5897 // If we can use the 16-bit encoding and the user didn't explicitly
5898 // request the 32-bit variant, transform it here.
5899 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5900 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5901 Inst.getOperand(2).getImm() == ARMCC::AL &&
5902 Inst.getOperand(4).getReg() == ARM::CPSR &&
5903 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5904 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5905 // The operands aren't the same for tMOV[S]r... (no cc_out)
5906 MCInst TmpInst;
5907 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5908 TmpInst.addOperand(Inst.getOperand(0));
5909 TmpInst.addOperand(Inst.getOperand(1));
5910 TmpInst.addOperand(Inst.getOperand(2));
5911 TmpInst.addOperand(Inst.getOperand(3));
5912 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005913 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005914 }
5915 break;
5916 }
Jim Grosbach82213192011-09-19 20:29:33 +00005917 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00005918 case ARM::t2SXTB:
5919 case ARM::t2UXTH:
5920 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00005921 // If we can use the 16-bit encoding and the user didn't explicitly
5922 // request the 32-bit variant, transform it here.
5923 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5924 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5925 Inst.getOperand(2).getImm() == 0 &&
5926 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5927 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00005928 unsigned NewOpc;
5929 switch (Inst.getOpcode()) {
5930 default: llvm_unreachable("Illegal opcode!");
5931 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5932 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5933 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5934 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5935 }
Jim Grosbach82213192011-09-19 20:29:33 +00005936 // The operands aren't the same for thumb1 (no rotate operand).
5937 MCInst TmpInst;
5938 TmpInst.setOpcode(NewOpc);
5939 TmpInst.addOperand(Inst.getOperand(0));
5940 TmpInst.addOperand(Inst.getOperand(1));
5941 TmpInst.addOperand(Inst.getOperand(3));
5942 TmpInst.addOperand(Inst.getOperand(4));
5943 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005944 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00005945 }
5946 break;
5947 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00005948 case ARM::MOVsi: {
5949 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
5950 if (SOpc == ARM_AM::rrx) return false;
5951 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
5952 // Shifting by zero is accepted as a vanilla 'MOVr'
5953 MCInst TmpInst;
5954 TmpInst.setOpcode(ARM::MOVr);
5955 TmpInst.addOperand(Inst.getOperand(0));
5956 TmpInst.addOperand(Inst.getOperand(1));
5957 TmpInst.addOperand(Inst.getOperand(3));
5958 TmpInst.addOperand(Inst.getOperand(4));
5959 TmpInst.addOperand(Inst.getOperand(5));
5960 Inst = TmpInst;
5961 return true;
5962 }
5963 return false;
5964 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005965 case ARM::t2IT: {
5966 // The mask bits for all but the first condition are represented as
5967 // the low bit of the condition code value implies 't'. We currently
5968 // always have 1 implies 't', so XOR toggle the bits if the low bit
5969 // of the condition code is zero. The encoding also expects the low
5970 // bit of the condition to be encoded as bit 4 of the mask operand,
5971 // so mask that in if needed
5972 MCOperand &MO = Inst.getOperand(1);
5973 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00005974 unsigned OrigMask = Mask;
5975 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005976 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005977 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5978 for (unsigned i = 3; i != TZ; --i)
5979 Mask ^= 1 << i;
5980 } else
5981 Mask |= 0x10;
5982 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00005983
5984 // Set up the IT block state according to the IT instruction we just
5985 // matched.
5986 assert(!inITBlock() && "nested IT blocks?!");
5987 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5988 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5989 ITState.CurPosition = 0;
5990 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005991 break;
5992 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005993 }
Jim Grosbachafad0532011-11-10 23:42:14 +00005994 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005995}
5996
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005997unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5998 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5999 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006000 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00006001 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006002 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6003 assert(MCID.hasOptionalDef() &&
6004 "optionally flag setting instruction missing optional def operand");
6005 assert(MCID.NumOperands == Inst.getNumOperands() &&
6006 "operand count mismatch!");
6007 // Find the optional-def operand (cc_out).
6008 unsigned OpNo;
6009 for (OpNo = 0;
6010 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6011 ++OpNo)
6012 ;
6013 // If we're parsing Thumb1, reject it completely.
6014 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6015 return Match_MnemonicFail;
6016 // If we're parsing Thumb2, which form is legal depends on whether we're
6017 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00006018 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6019 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006020 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00006021 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6022 inITBlock())
6023 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006024 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006025 // Some high-register supporting Thumb1 encodings only allow both registers
6026 // to be from r0-r7 when in Thumb2.
6027 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6028 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6029 isARMLowRegister(Inst.getOperand(2).getReg()))
6030 return Match_RequiresThumb2;
6031 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00006032 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006033 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6034 isARMLowRegister(Inst.getOperand(1).getReg()))
6035 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006036 return Match_Success;
6037}
6038
Chris Lattner9487de62010-10-28 21:28:01 +00006039bool ARMAsmParser::
6040MatchAndEmitInstruction(SMLoc IDLoc,
6041 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6042 MCStreamer &Out) {
6043 MCInst Inst;
6044 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00006045 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00006046 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00006047 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00006048 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006049 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006050 // Context sensitive operand constraints aren't handled by the matcher,
6051 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006052 if (validateInstruction(Inst, Operands)) {
6053 // Still progress the IT block, otherwise one wrong condition causes
6054 // nasty cascading errors.
6055 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006056 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006057 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006058
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006059 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00006060 // encoding is selected. Loop on it while changes happen so the
6061 // individual transformations can chain off each other. E.g.,
6062 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6063 while (processInstruction(Inst, Operands))
6064 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006065
Jim Grosbacha0d34d32011-09-02 23:22:08 +00006066 // Only move forward at the very end so that everything in validate
6067 // and process gets a consistent answer about whether we're in an IT
6068 // block.
6069 forwardITPosition();
6070
Chris Lattner9487de62010-10-28 21:28:01 +00006071 Out.EmitInstruction(Inst);
6072 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006073 case Match_MissingFeature:
6074 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6075 return true;
6076 case Match_InvalidOperand: {
6077 SMLoc ErrorLoc = IDLoc;
6078 if (ErrorInfo != ~0U) {
6079 if (ErrorInfo >= Operands.size())
6080 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00006081
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006082 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6083 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6084 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006085
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006086 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00006087 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006088 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006089 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00006090 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00006091 // The converter function will have already emited a diagnostic.
6092 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00006093 case Match_RequiresNotITBlock:
6094 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006095 case Match_RequiresITBlock:
6096 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006097 case Match_RequiresV6:
6098 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6099 case Match_RequiresThumb2:
6100 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006101 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006102
Eric Christopher91d7b902010-10-29 09:26:59 +00006103 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00006104 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00006105}
6106
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006107/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00006108bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6109 StringRef IDVal = DirectiveID.getIdentifier();
6110 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006111 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006112 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006113 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00006114 else if (IDVal == ".arm")
6115 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006116 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006117 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006118 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006119 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006120 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006121 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00006122 else if (IDVal == ".unreq")
6123 return parseDirectiveUnreq(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00006124 return true;
6125}
6126
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006127/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00006128/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006129bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00006130 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6131 for (;;) {
6132 const MCExpr *Value;
6133 if (getParser().ParseExpression(Value))
6134 return true;
6135
Chris Lattnerc35681b2010-01-19 19:46:13 +00006136 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00006137
6138 if (getLexer().is(AsmToken::EndOfStatement))
6139 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00006140
Kevin Enderbyccab3172009-09-15 00:27:25 +00006141 // FIXME: Improve diagnostic.
6142 if (getLexer().isNot(AsmToken::Comma))
6143 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006144 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006145 }
6146 }
6147
Sean Callanana83fd7d2010-01-19 20:27:46 +00006148 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006149 return false;
6150}
6151
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006152/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00006153/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006154bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00006155 if (getLexer().isNot(AsmToken::EndOfStatement))
6156 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006157 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006158
Jim Grosbach7f882392011-12-07 18:04:19 +00006159 if (!isThumb())
6160 SwitchMode();
6161 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6162 return false;
6163}
6164
6165/// parseDirectiveARM
6166/// ::= .arm
6167bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6168 if (getLexer().isNot(AsmToken::EndOfStatement))
6169 return Error(L, "unexpected token in directive");
6170 Parser.Lex();
6171
6172 if (isThumb())
6173 SwitchMode();
6174 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006175 return false;
6176}
6177
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006178/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00006179/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006180bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006181 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6182 bool isMachO = MAI.hasSubsectionsViaSymbols();
6183 StringRef Name;
6184
6185 // Darwin asm has function name after .thumb_func direction
6186 // ELF doesn't
6187 if (isMachO) {
6188 const AsmToken &Tok = Parser.getTok();
6189 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6190 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00006191 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006192 Parser.Lex(); // Consume the identifier token.
6193 }
6194
Jim Grosbach42ba6282011-11-10 20:48:53 +00006195 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00006196 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006197 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006198
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006199 // FIXME: assuming function name will be the line following .thumb_func
6200 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00006201 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006202 }
6203
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00006204 // Mark symbol as a thumb symbol.
6205 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6206 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006207 return false;
6208}
6209
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006210/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00006211/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006212bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006213 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006214 if (Tok.isNot(AsmToken::Identifier))
6215 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00006216 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00006217 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00006218 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006219 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00006220 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00006221 else
6222 return Error(L, "unrecognized syntax mode in .syntax directive");
6223
6224 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006225 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006226 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006227
6228 // TODO tell the MC streamer the mode
6229 // getParser().getStreamer().Emit???();
6230 return false;
6231}
6232
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006233/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00006234/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006235bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006236 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006237 if (Tok.isNot(AsmToken::Integer))
6238 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00006239 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00006240 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006241 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006242 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006243 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006244 else
6245 return Error(L, "invalid operand to .code directive");
6246
6247 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006248 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006249 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006250
Evan Cheng284b4672011-07-08 22:36:29 +00006251 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006252 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006253 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006254 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00006255 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006256 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006257 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006258 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00006259 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00006260
Kevin Enderby146dcf22009-10-15 20:48:48 +00006261 return false;
6262}
6263
Jim Grosbachab5830e2011-12-14 02:16:11 +00006264/// parseDirectiveReq
6265/// ::= name .req registername
6266bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6267 Parser.Lex(); // Eat the '.req' token.
6268 unsigned Reg;
6269 SMLoc SRegLoc, ERegLoc;
6270 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6271 Parser.EatToEndOfStatement();
6272 return Error(SRegLoc, "register name expected");
6273 }
6274
6275 // Shouldn't be anything else.
6276 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6277 Parser.EatToEndOfStatement();
6278 return Error(Parser.getTok().getLoc(),
6279 "unexpected input in .req directive.");
6280 }
6281
6282 Parser.Lex(); // Consume the EndOfStatement
6283
6284 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6285 return Error(SRegLoc, "redefinition of '" + Name +
6286 "' does not match original.");
6287
6288 return false;
6289}
6290
6291/// parseDirectiveUneq
6292/// ::= .unreq registername
6293bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6294 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6295 Parser.EatToEndOfStatement();
6296 return Error(L, "unexpected input in .unreq directive.");
6297 }
6298 RegisterReqs.erase(Parser.getTok().getIdentifier());
6299 Parser.Lex(); // Eat the identifier.
6300 return false;
6301}
6302
Sean Callanan643a5572010-04-07 20:29:34 +00006303extern "C" void LLVMInitializeARMAsmLexer();
6304
Kevin Enderby8be42bd2009-10-30 22:55:57 +00006305/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00006306extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00006307 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6308 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00006309 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006310}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006311
Chris Lattner3e4582a2010-09-06 19:11:01 +00006312#define GET_REGISTER_MATCHER
6313#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006314#include "ARMGenAsmMatcher.inc"