blob: 7251df96f1edb8c8d9ffaca0fca351001ce6fbed [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
364 // n = alignment in bytes (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 Grosbacha95ec992011-10-11 17:29:55 +0000883 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000884 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000885 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000886 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000887 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000888 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000889 if (!Memory.OffsetImm) return true;
890 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000891 return Val > -256 && Val < 256;
892 }
893 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000894 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000895 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000896 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000897 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
898 // Immediate offset in range [-255, 255].
899 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
900 if (!CE) return false;
901 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000902 // Special case, #-0 is INT32_MIN.
903 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000904 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000905 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000906 // If we have an immediate that's not a constant, treat it as a label
907 // reference needing a fixup. If it is a constant, it's something else
908 // and we reject it.
909 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
910 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000911 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000912 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000913 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000914 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000915 if (!Memory.OffsetImm) return true;
916 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000917 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000918 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000919 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000920 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000921 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000922 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000923 return false;
924 return true;
925 }
926 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000927 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000928 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
929 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000930 return false;
931 return true;
932 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000933 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000935 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000936 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000937 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000938 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000939 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
940 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000941 return false;
942 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000943 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000944 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000945 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000946 return false;
947 return true;
948 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000949 bool isMemThumbRR() const {
950 // Thumb reg+reg addressing is simple. Just two registers, a base and
951 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000952 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000953 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000954 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000955 return isARMLowRegister(Memory.BaseRegNum) &&
956 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000957 }
958 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000959 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000960 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000961 return false;
962 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000963 if (!Memory.OffsetImm) return true;
964 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000965 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
966 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000967 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000968 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000969 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000970 return false;
971 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000972 if (!Memory.OffsetImm) return true;
973 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000974 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
975 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000976 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000977 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000978 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000979 return false;
980 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000981 if (!Memory.OffsetImm) return true;
982 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000983 return Val >= 0 && Val <= 31;
984 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000985 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000986 if (!isMemory() || Memory.OffsetRegNum != 0 ||
987 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000988 return false;
989 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000990 if (!Memory.OffsetImm) return true;
991 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000992 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000993 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000994 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000995 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000996 return false;
997 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000998 if (!Memory.OffsetImm) return true;
999 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +00001000 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1001 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001002 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001003 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001004 return false;
1005 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001006 if (!Memory.OffsetImm) return true;
1007 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001008 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1009 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001010 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001011 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001012 return false;
1013 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001014 if (!Memory.OffsetImm) return true;
1015 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001016 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001017 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001018 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001019 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001020 return false;
1021 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001022 if (!Memory.OffsetImm) return true;
1023 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001024 return Val >= 0 && Val < 256;
1025 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001026 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001027 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001028 return false;
1029 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001030 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001031 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001032 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001033 }
1034 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001035 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001036 return false;
1037 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001038 if (!Memory.OffsetImm) return true;
1039 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001040 return (Val >= 0 && Val < 4096);
1041 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001042 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001043 // If we have an immediate that's not a constant, treat it as a label
1044 // reference needing a fixup. If it is a constant, it's something else
1045 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001046 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001047 return true;
1048
Jim Grosbacha95ec992011-10-11 17:29:55 +00001049 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001050 return false;
1051 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001052 if (!Memory.OffsetImm) return true;
1053 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001054 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001055 }
1056 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001057 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +00001058 return false;
1059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1060 if (!CE) return false;
1061 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001062 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001063 }
Jim Grosbach93981412011-10-11 21:55:36 +00001064 bool isPostIdxImm8s4() const {
1065 if (Kind != k_Immediate)
1066 return false;
1067 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1068 if (!CE) return false;
1069 int64_t Val = CE->getValue();
1070 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1071 (Val == INT32_MIN);
1072 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001073
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001074 bool isMSRMask() const { return Kind == k_MSRMask; }
1075 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001076
Jim Grosbach741cd732011-10-17 22:26:03 +00001077 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001078 bool isSingleSpacedVectorList() const {
1079 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1080 }
1081 bool isDoubleSpacedVectorList() const {
1082 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1083 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001084 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001085 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001086 return VectorList.Count == 1;
1087 }
1088
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001089 bool isVecListTwoD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001090 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001091 return VectorList.Count == 2;
1092 }
1093
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001094 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001095 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001096 return VectorList.Count == 3;
1097 }
1098
Jim Grosbach846bcff2011-10-21 20:35:01 +00001099 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001100 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001101 return VectorList.Count == 4;
1102 }
1103
Jim Grosbach118b38c2011-10-21 22:21:10 +00001104 bool isVecListTwoQ() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001105 if (!isDoubleSpacedVectorList()) return false;
1106 return VectorList.Count == 2;
Jim Grosbach118b38c2011-10-21 22:21:10 +00001107 }
1108
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001109 bool isVecListOneDAllLanes() const {
1110 if (Kind != k_VectorListAllLanes) return false;
1111 return VectorList.Count == 1;
1112 }
1113
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001114 bool isVecListTwoDAllLanes() const {
1115 if (Kind != k_VectorListAllLanes) return false;
1116 return VectorList.Count == 2;
1117 }
1118
Jim Grosbach04945c42011-12-02 00:35:16 +00001119 bool isVecListOneDByteIndexed() const {
1120 if (Kind != k_VectorListIndexed) return false;
1121 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1122 }
1123
Jim Grosbachda511042011-12-14 23:35:06 +00001124 bool isVecListOneDHWordIndexed() const {
1125 if (Kind != k_VectorListIndexed) return false;
1126 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1127 }
1128
1129 bool isVecListOneDWordIndexed() const {
1130 if (Kind != k_VectorListIndexed) return false;
1131 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1132 }
1133
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001134 bool isVecListTwoDByteIndexed() const {
1135 if (Kind != k_VectorListIndexed) return false;
1136 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1137 }
1138
Jim Grosbachda511042011-12-14 23:35:06 +00001139 bool isVecListTwoDHWordIndexed() const {
1140 if (Kind != k_VectorListIndexed) return false;
1141 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1142 }
1143
1144 bool isVecListTwoDWordIndexed() const {
1145 if (Kind != k_VectorListIndexed) return false;
1146 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1147 }
1148
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001149 bool isVectorIndex8() const {
1150 if (Kind != k_VectorIndex) return false;
1151 return VectorIndex.Val < 8;
1152 }
1153 bool isVectorIndex16() const {
1154 if (Kind != k_VectorIndex) return false;
1155 return VectorIndex.Val < 4;
1156 }
1157 bool isVectorIndex32() const {
1158 if (Kind != k_VectorIndex) return false;
1159 return VectorIndex.Val < 2;
1160 }
1161
Jim Grosbach741cd732011-10-17 22:26:03 +00001162 bool isNEONi8splat() const {
1163 if (Kind != k_Immediate)
1164 return false;
1165 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1166 // Must be a constant.
1167 if (!CE) return false;
1168 int64_t Value = CE->getValue();
1169 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1170 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001171 return Value >= 0 && Value < 256;
1172 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001173
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001174 bool isNEONi16splat() const {
1175 if (Kind != k_Immediate)
1176 return false;
1177 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1178 // Must be a constant.
1179 if (!CE) return false;
1180 int64_t Value = CE->getValue();
1181 // i16 value in the range [0,255] or [0x0100, 0xff00]
1182 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1183 }
1184
Jim Grosbach8211c052011-10-18 00:22:00 +00001185 bool isNEONi32splat() const {
1186 if (Kind != k_Immediate)
1187 return false;
1188 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1189 // Must be a constant.
1190 if (!CE) return false;
1191 int64_t Value = CE->getValue();
1192 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1193 return (Value >= 0 && Value < 256) ||
1194 (Value >= 0x0100 && Value <= 0xff00) ||
1195 (Value >= 0x010000 && Value <= 0xff0000) ||
1196 (Value >= 0x01000000 && Value <= 0xff000000);
1197 }
1198
1199 bool isNEONi32vmov() const {
1200 if (Kind != k_Immediate)
1201 return false;
1202 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1203 // Must be a constant.
1204 if (!CE) return false;
1205 int64_t Value = CE->getValue();
1206 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1207 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1208 return (Value >= 0 && Value < 256) ||
1209 (Value >= 0x0100 && Value <= 0xff00) ||
1210 (Value >= 0x010000 && Value <= 0xff0000) ||
1211 (Value >= 0x01000000 && Value <= 0xff000000) ||
1212 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1213 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1214 }
1215
Jim Grosbache4454e02011-10-18 16:18:11 +00001216 bool isNEONi64splat() const {
1217 if (Kind != k_Immediate)
1218 return false;
1219 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1220 // Must be a constant.
1221 if (!CE) return false;
1222 uint64_t Value = CE->getValue();
1223 // i64 value with each byte being either 0 or 0xff.
1224 for (unsigned i = 0; i < 8; ++i)
1225 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1226 return true;
1227 }
1228
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001229 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001230 // Add as immediates when possible. Null MCExpr = 0.
1231 if (Expr == 0)
1232 Inst.addOperand(MCOperand::CreateImm(0));
1233 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001234 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1235 else
1236 Inst.addOperand(MCOperand::CreateExpr(Expr));
1237 }
1238
Daniel Dunbard8042b72010-08-11 06:36:53 +00001239 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001240 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001241 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001242 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1243 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001244 }
1245
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001246 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
1248 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1249 }
1250
Jim Grosbach48399582011-10-12 17:34:41 +00001251 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1254 }
1255
1256 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1257 assert(N == 1 && "Invalid number of operands!");
1258 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1259 }
1260
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001261 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1264 }
1265
1266 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1269 }
1270
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001271 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 Inst.addOperand(MCOperand::CreateReg(getReg()));
1274 }
1275
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001276 void addRegOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 Inst.addOperand(MCOperand::CreateReg(getReg()));
1279 }
1280
Jim Grosbachac798e12011-07-25 20:49:51 +00001281 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001282 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001283 assert(isRegShiftedReg() &&
1284 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001285 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1286 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001287 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001288 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001289 }
1290
Jim Grosbachac798e12011-07-25 20:49:51 +00001291 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001292 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001293 assert(isRegShiftedImm() &&
1294 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001295 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001296 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001297 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001298 }
1299
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001300 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001301 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001302 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1303 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001304 }
1305
Bill Wendling8d2aa032010-11-08 23:49:57 +00001306 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001307 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001308 const SmallVectorImpl<unsigned> &RegList = getRegList();
1309 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001310 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1311 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001312 }
1313
Bill Wendling9898ac92010-11-17 04:32:08 +00001314 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1315 addRegListOperands(Inst, N);
1316 }
1317
1318 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1319 addRegListOperands(Inst, N);
1320 }
1321
Jim Grosbach833b9d32011-07-27 20:15:40 +00001322 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
1324 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1325 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1326 }
1327
Jim Grosbach864b6092011-07-28 21:34:26 +00001328 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
1330 // Munge the lsb/width into a bitfield mask.
1331 unsigned lsb = Bitfield.LSB;
1332 unsigned width = Bitfield.Width;
1333 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1334 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1335 (32 - (lsb + width)));
1336 Inst.addOperand(MCOperand::CreateImm(Mask));
1337 }
1338
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001339 void addImmOperands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
1341 addExpr(Inst, getImm());
1342 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001343
Jim Grosbache7fbce72011-10-03 23:38:36 +00001344 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1345 assert(N == 1 && "Invalid number of operands!");
1346 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1347 }
1348
Jim Grosbach7db8d692011-09-08 22:07:06 +00001349 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1350 assert(N == 1 && "Invalid number of operands!");
1351 // FIXME: We really want to scale the value here, but the LDRD/STRD
1352 // instruction don't encode operands that way yet.
1353 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1354 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1355 }
1356
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001357 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 1 && "Invalid number of operands!");
1359 // The immediate is scaled by four in the encoding and is stored
1360 // in the MCInst as such. Lop off the low two bits here.
1361 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1362 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1363 }
1364
1365 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1366 assert(N == 1 && "Invalid number of operands!");
1367 // The immediate is scaled by four in the encoding and is stored
1368 // in the MCInst as such. Lop off the low two bits here.
1369 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1370 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1371 }
1372
Jim Grosbach475c6db2011-07-25 23:09:14 +00001373 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
1375 // The constant encodes as the immediate-1, and we store in the instruction
1376 // the bits as encoded, so subtract off one here.
1377 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1378 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1379 }
1380
Jim Grosbach801e0a32011-07-22 23:16:18 +00001381 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 1 && "Invalid number of operands!");
1383 // The constant encodes as the immediate-1, and we store in the instruction
1384 // the bits as encoded, so subtract off one here.
1385 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1386 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1387 }
1388
Jim Grosbach46dd4132011-08-17 21:51:27 +00001389 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 1 && "Invalid number of operands!");
1391 // The constant encodes as the immediate, except for 32, which encodes as
1392 // zero.
1393 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1394 unsigned Imm = CE->getValue();
1395 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1396 }
1397
Jim Grosbach27c1e252011-07-21 17:23:04 +00001398 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1399 assert(N == 1 && "Invalid number of operands!");
1400 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1401 // the instruction as well.
1402 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1403 int Val = CE->getValue();
1404 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1405 }
1406
Jim Grosbachb009a872011-10-28 22:36:30 +00001407 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1408 assert(N == 1 && "Invalid number of operands!");
1409 // The operand is actually a t2_so_imm, but we have its bitwise
1410 // negation in the assembly source, so twiddle it here.
1411 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1412 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1413 }
1414
Jim Grosbach30506252011-12-08 00:31:07 +00001415 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1416 assert(N == 1 && "Invalid number of operands!");
1417 // The operand is actually a t2_so_imm, but we have its
1418 // negation in the assembly source, so twiddle it here.
1419 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1420 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1421 }
1422
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001423 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1424 assert(N == 1 && "Invalid number of operands!");
1425 // The operand is actually a so_imm, but we have its bitwise
1426 // negation in the assembly source, so twiddle it here.
1427 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1428 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1429 }
1430
Jim Grosbach30506252011-12-08 00:31:07 +00001431 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1432 assert(N == 1 && "Invalid number of operands!");
1433 // The operand is actually a so_imm, but we have its
1434 // negation in the assembly source, so twiddle it here.
1435 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1436 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1437 }
1438
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001439 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1442 }
1443
Jim Grosbachd3595712011-08-03 23:50:40 +00001444 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001446 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001447 }
1448
Jim Grosbacha95ec992011-10-11 17:29:55 +00001449 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 2 && "Invalid number of operands!");
1451 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1452 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1453 }
1454
Jim Grosbachd3595712011-08-03 23:50:40 +00001455 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001457 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1458 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001459 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1460 // Special case for #-0
1461 if (Val == INT32_MIN) Val = 0;
1462 if (Val < 0) Val = -Val;
1463 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1464 } else {
1465 // For register offset, we encode the shift type and negation flag
1466 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001467 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1468 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001469 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001470 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1471 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001472 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001473 }
1474
Jim Grosbachcd17c122011-08-04 23:01:30 +00001475 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 2 && "Invalid number of operands!");
1477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1478 assert(CE && "non-constant AM2OffsetImm operand!");
1479 int32_t Val = CE->getValue();
1480 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1481 // Special case for #-0
1482 if (Val == INT32_MIN) Val = 0;
1483 if (Val < 0) Val = -Val;
1484 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1485 Inst.addOperand(MCOperand::CreateReg(0));
1486 Inst.addOperand(MCOperand::CreateImm(Val));
1487 }
1488
Jim Grosbach5b96b802011-08-10 20:29:19 +00001489 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001491 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1492 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001493 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1494 // Special case for #-0
1495 if (Val == INT32_MIN) Val = 0;
1496 if (Val < 0) Val = -Val;
1497 Val = ARM_AM::getAM3Opc(AddSub, Val);
1498 } else {
1499 // For register offset, we encode the shift type and negation flag
1500 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001501 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001502 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001503 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1504 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001505 Inst.addOperand(MCOperand::CreateImm(Val));
1506 }
1507
1508 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1509 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001510 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001511 int32_t Val =
1512 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1513 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1514 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001515 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001516 }
1517
1518 // Constant offset.
1519 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1520 int32_t Val = CE->getValue();
1521 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1522 // Special case for #-0
1523 if (Val == INT32_MIN) Val = 0;
1524 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001525 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001526 Inst.addOperand(MCOperand::CreateReg(0));
1527 Inst.addOperand(MCOperand::CreateImm(Val));
1528 }
1529
Jim Grosbachd3595712011-08-03 23:50:40 +00001530 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001532 // If we have an immediate that's not a constant, treat it as a label
1533 // reference needing a fixup. If it is a constant, it's something else
1534 // and we reject it.
1535 if (isImm()) {
1536 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1537 Inst.addOperand(MCOperand::CreateImm(0));
1538 return;
1539 }
1540
Jim Grosbachd3595712011-08-03 23:50:40 +00001541 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001542 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001543 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1544 // Special case for #-0
1545 if (Val == INT32_MIN) Val = 0;
1546 if (Val < 0) Val = -Val;
1547 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001548 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001549 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001550 }
1551
Jim Grosbach7db8d692011-09-08 22:07:06 +00001552 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001554 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1555 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001556 Inst.addOperand(MCOperand::CreateImm(Val));
1557 }
1558
Jim Grosbacha05627e2011-09-09 18:37:27 +00001559 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1560 assert(N == 2 && "Invalid number of operands!");
1561 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001562 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1563 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001564 Inst.addOperand(MCOperand::CreateImm(Val));
1565 }
1566
Jim Grosbachd3595712011-08-03 23:50:40 +00001567 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1568 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001569 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1570 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001571 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001572 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001573
Jim Grosbach2392c532011-09-07 23:39:14 +00001574 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1575 addMemImm8OffsetOperands(Inst, N);
1576 }
1577
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001578 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001579 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001580 }
1581
1582 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 2 && "Invalid number of operands!");
1584 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001585 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001586 addExpr(Inst, getImm());
1587 Inst.addOperand(MCOperand::CreateImm(0));
1588 return;
1589 }
1590
1591 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001592 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1593 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001594 Inst.addOperand(MCOperand::CreateImm(Val));
1595 }
1596
Jim Grosbachd3595712011-08-03 23:50:40 +00001597 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1598 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001599 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001600 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001601 addExpr(Inst, getImm());
1602 Inst.addOperand(MCOperand::CreateImm(0));
1603 return;
1604 }
1605
1606 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001607 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1608 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001609 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001610 }
Bill Wendling811c9362010-11-30 07:44:32 +00001611
Jim Grosbach05541f42011-09-19 22:21:13 +00001612 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001614 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1615 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001616 }
1617
1618 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1619 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001620 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1621 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001622 }
1623
Jim Grosbachd3595712011-08-03 23:50:40 +00001624 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1625 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001626 unsigned Val =
1627 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1628 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001629 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1630 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001631 Inst.addOperand(MCOperand::CreateImm(Val));
1632 }
1633
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001634 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1635 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001636 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1637 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1638 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001639 }
1640
Jim Grosbachd3595712011-08-03 23:50:40 +00001641 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1642 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001643 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1644 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001645 }
1646
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001647 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1648 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001649 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1650 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001651 Inst.addOperand(MCOperand::CreateImm(Val));
1652 }
1653
Jim Grosbach26d35872011-08-19 18:55:51 +00001654 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1655 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001656 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1657 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001658 Inst.addOperand(MCOperand::CreateImm(Val));
1659 }
1660
Jim Grosbacha32c7532011-08-19 18:49:59 +00001661 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1662 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001663 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1664 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001665 Inst.addOperand(MCOperand::CreateImm(Val));
1666 }
1667
Jim Grosbach23983d62011-08-19 18:13:48 +00001668 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1669 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001670 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1671 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001672 Inst.addOperand(MCOperand::CreateImm(Val));
1673 }
1674
Jim Grosbachd3595712011-08-03 23:50:40 +00001675 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1676 assert(N == 1 && "Invalid number of operands!");
1677 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1678 assert(CE && "non-constant post-idx-imm8 operand!");
1679 int Imm = CE->getValue();
1680 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001681 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001682 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1683 Inst.addOperand(MCOperand::CreateImm(Imm));
1684 }
1685
Jim Grosbach93981412011-10-11 21:55:36 +00001686 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1687 assert(N == 1 && "Invalid number of operands!");
1688 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1689 assert(CE && "non-constant post-idx-imm8s4 operand!");
1690 int Imm = CE->getValue();
1691 bool isAdd = Imm >= 0;
1692 if (Imm == INT32_MIN) Imm = 0;
1693 // Immediate is scaled by 4.
1694 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1695 Inst.addOperand(MCOperand::CreateImm(Imm));
1696 }
1697
Jim Grosbachd3595712011-08-03 23:50:40 +00001698 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1699 assert(N == 2 && "Invalid number of operands!");
1700 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001701 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1702 }
1703
1704 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1705 assert(N == 2 && "Invalid number of operands!");
1706 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1707 // The sign, shift type, and shift amount are encoded in a single operand
1708 // using the AM2 encoding helpers.
1709 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1710 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1711 PostIdxReg.ShiftTy);
1712 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001713 }
1714
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001715 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 1 && "Invalid number of operands!");
1717 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1718 }
1719
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001720 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1721 assert(N == 1 && "Invalid number of operands!");
1722 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1723 }
1724
Jim Grosbach182b6a02011-11-29 23:51:09 +00001725 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001726 assert(N == 1 && "Invalid number of operands!");
1727 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1728 }
1729
Jim Grosbach04945c42011-12-02 00:35:16 +00001730 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1731 assert(N == 2 && "Invalid number of operands!");
1732 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1733 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1734 }
1735
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001736 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1737 assert(N == 1 && "Invalid number of operands!");
1738 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1739 }
1740
1741 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1742 assert(N == 1 && "Invalid number of operands!");
1743 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1744 }
1745
1746 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1747 assert(N == 1 && "Invalid number of operands!");
1748 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1749 }
1750
Jim Grosbach741cd732011-10-17 22:26:03 +00001751 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1752 assert(N == 1 && "Invalid number of operands!");
1753 // The immediate encodes the type of constant as well as the value.
1754 // Mask in that this is an i8 splat.
1755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1756 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1757 }
1758
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001759 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 1 && "Invalid number of operands!");
1761 // The immediate encodes the type of constant as well as the value.
1762 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1763 unsigned Value = CE->getValue();
1764 if (Value >= 256)
1765 Value = (Value >> 8) | 0xa00;
1766 else
1767 Value |= 0x800;
1768 Inst.addOperand(MCOperand::CreateImm(Value));
1769 }
1770
Jim Grosbach8211c052011-10-18 00:22:00 +00001771 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1772 assert(N == 1 && "Invalid number of operands!");
1773 // The immediate encodes the type of constant as well as the value.
1774 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1775 unsigned Value = CE->getValue();
1776 if (Value >= 256 && Value <= 0xff00)
1777 Value = (Value >> 8) | 0x200;
1778 else if (Value > 0xffff && Value <= 0xff0000)
1779 Value = (Value >> 16) | 0x400;
1780 else if (Value > 0xffffff)
1781 Value = (Value >> 24) | 0x600;
1782 Inst.addOperand(MCOperand::CreateImm(Value));
1783 }
1784
1785 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1786 assert(N == 1 && "Invalid number of operands!");
1787 // The immediate encodes the type of constant as well as the value.
1788 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1789 unsigned Value = CE->getValue();
1790 if (Value >= 256 && Value <= 0xffff)
1791 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1792 else if (Value > 0xffff && Value <= 0xffffff)
1793 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1794 else if (Value > 0xffffff)
1795 Value = (Value >> 24) | 0x600;
1796 Inst.addOperand(MCOperand::CreateImm(Value));
1797 }
1798
Jim Grosbache4454e02011-10-18 16:18:11 +00001799 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 1 && "Invalid number of operands!");
1801 // The immediate encodes the type of constant as well as the value.
1802 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1803 uint64_t Value = CE->getValue();
1804 unsigned Imm = 0;
1805 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1806 Imm |= (Value & 1) << i;
1807 }
1808 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1809 }
1810
Jim Grosbach602aa902011-07-13 15:34:57 +00001811 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001812
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001813 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001814 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001815 Op->ITMask.Mask = Mask;
1816 Op->StartLoc = S;
1817 Op->EndLoc = S;
1818 return Op;
1819 }
1820
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001821 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001822 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001823 Op->CC.Val = CC;
1824 Op->StartLoc = S;
1825 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001826 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001827 }
1828
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001829 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001830 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001831 Op->Cop.Val = CopVal;
1832 Op->StartLoc = S;
1833 Op->EndLoc = S;
1834 return Op;
1835 }
1836
1837 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001838 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001839 Op->Cop.Val = CopVal;
1840 Op->StartLoc = S;
1841 Op->EndLoc = S;
1842 return Op;
1843 }
1844
Jim Grosbach48399582011-10-12 17:34:41 +00001845 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1846 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1847 Op->Cop.Val = Val;
1848 Op->StartLoc = S;
1849 Op->EndLoc = E;
1850 return Op;
1851 }
1852
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001853 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001854 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001855 Op->Reg.RegNum = RegNum;
1856 Op->StartLoc = S;
1857 Op->EndLoc = S;
1858 return Op;
1859 }
1860
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001861 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001862 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001863 Op->Tok.Data = Str.data();
1864 Op->Tok.Length = Str.size();
1865 Op->StartLoc = S;
1866 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001867 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001868 }
1869
Bill Wendling2063b842010-11-18 23:43:05 +00001870 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001871 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001872 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001873 Op->StartLoc = S;
1874 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001875 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001876 }
1877
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001878 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1879 unsigned SrcReg,
1880 unsigned ShiftReg,
1881 unsigned ShiftImm,
1882 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001883 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001884 Op->RegShiftedReg.ShiftTy = ShTy;
1885 Op->RegShiftedReg.SrcReg = SrcReg;
1886 Op->RegShiftedReg.ShiftReg = ShiftReg;
1887 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001888 Op->StartLoc = S;
1889 Op->EndLoc = E;
1890 return Op;
1891 }
1892
Owen Andersonb595ed02011-07-21 18:54:16 +00001893 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1894 unsigned SrcReg,
1895 unsigned ShiftImm,
1896 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001897 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001898 Op->RegShiftedImm.ShiftTy = ShTy;
1899 Op->RegShiftedImm.SrcReg = SrcReg;
1900 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001901 Op->StartLoc = S;
1902 Op->EndLoc = E;
1903 return Op;
1904 }
1905
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001906 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001907 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001908 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001909 Op->ShifterImm.isASR = isASR;
1910 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001911 Op->StartLoc = S;
1912 Op->EndLoc = E;
1913 return Op;
1914 }
1915
Jim Grosbach833b9d32011-07-27 20:15:40 +00001916 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001917 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001918 Op->RotImm.Imm = Imm;
1919 Op->StartLoc = S;
1920 Op->EndLoc = E;
1921 return Op;
1922 }
1923
Jim Grosbach864b6092011-07-28 21:34:26 +00001924 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1925 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001926 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001927 Op->Bitfield.LSB = LSB;
1928 Op->Bitfield.Width = Width;
1929 Op->StartLoc = S;
1930 Op->EndLoc = E;
1931 return Op;
1932 }
1933
Bill Wendling2cae3272010-11-09 22:44:22 +00001934 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001935 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001936 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001937 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001938
Jim Grosbach75461af2011-09-13 22:56:44 +00001939 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001940 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001941 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001942 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001943 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001944
1945 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001946 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001947 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001948 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001949 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001950 Op->StartLoc = StartLoc;
1951 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001952 return Op;
1953 }
1954
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001955 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach2f50e922011-12-15 21:44:33 +00001956 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001957 ARMOperand *Op = new ARMOperand(k_VectorList);
1958 Op->VectorList.RegNum = RegNum;
1959 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00001960 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001961 Op->StartLoc = S;
1962 Op->EndLoc = E;
1963 return Op;
1964 }
1965
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001966 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1967 SMLoc S, SMLoc E) {
1968 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1969 Op->VectorList.RegNum = RegNum;
1970 Op->VectorList.Count = Count;
1971 Op->StartLoc = S;
1972 Op->EndLoc = E;
1973 return Op;
1974 }
1975
Jim Grosbach04945c42011-12-02 00:35:16 +00001976 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1977 unsigned Index, SMLoc S, SMLoc E) {
1978 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1979 Op->VectorList.RegNum = RegNum;
1980 Op->VectorList.Count = Count;
1981 Op->VectorList.LaneIndex = Index;
1982 Op->StartLoc = S;
1983 Op->EndLoc = E;
1984 return Op;
1985 }
1986
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001987 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1988 MCContext &Ctx) {
1989 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1990 Op->VectorIndex.Val = Idx;
1991 Op->StartLoc = S;
1992 Op->EndLoc = E;
1993 return Op;
1994 }
1995
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001996 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001997 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001998 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001999 Op->StartLoc = S;
2000 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002001 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002002 }
2003
Jim Grosbache7fbce72011-10-03 23:38:36 +00002004 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002005 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00002006 Op->FPImm.Val = Val;
2007 Op->StartLoc = S;
2008 Op->EndLoc = S;
2009 return Op;
2010 }
2011
Jim Grosbachd3595712011-08-03 23:50:40 +00002012 static ARMOperand *CreateMem(unsigned BaseRegNum,
2013 const MCConstantExpr *OffsetImm,
2014 unsigned OffsetRegNum,
2015 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002016 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002017 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002018 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002019 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002020 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002021 Op->Memory.BaseRegNum = BaseRegNum;
2022 Op->Memory.OffsetImm = OffsetImm;
2023 Op->Memory.OffsetRegNum = OffsetRegNum;
2024 Op->Memory.ShiftType = ShiftType;
2025 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002026 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002027 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002028 Op->StartLoc = S;
2029 Op->EndLoc = E;
2030 return Op;
2031 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002032
Jim Grosbachc320c852011-08-05 21:28:30 +00002033 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2034 ARM_AM::ShiftOpc ShiftTy,
2035 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002036 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002037 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002038 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002039 Op->PostIdxReg.isAdd = isAdd;
2040 Op->PostIdxReg.ShiftTy = ShiftTy;
2041 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002042 Op->StartLoc = S;
2043 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002044 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002045 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002046
2047 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002048 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002049 Op->MBOpt.Val = Opt;
2050 Op->StartLoc = S;
2051 Op->EndLoc = S;
2052 return Op;
2053 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002054
2055 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002056 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002057 Op->IFlags.Val = IFlags;
2058 Op->StartLoc = S;
2059 Op->EndLoc = S;
2060 return Op;
2061 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002062
2063 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002064 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002065 Op->MMask.Val = MMask;
2066 Op->StartLoc = S;
2067 Op->EndLoc = S;
2068 return Op;
2069 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002070};
2071
2072} // end anonymous namespace.
2073
Jim Grosbach602aa902011-07-13 15:34:57 +00002074void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002075 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002076 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00002077 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2078 << ") >";
2079 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002080 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002081 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002082 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002083 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002084 OS << "<ccout " << getReg() << ">";
2085 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002086 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002087 static const char *MaskStr[] = {
2088 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2089 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2090 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002091 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2092 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2093 break;
2094 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002095 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002096 OS << "<coprocessor number: " << getCoproc() << ">";
2097 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002098 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002099 OS << "<coprocessor register: " << getCoproc() << ">";
2100 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002101 case k_CoprocOption:
2102 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2103 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002104 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002105 OS << "<mask: " << getMSRMask() << ">";
2106 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002107 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002108 getImm()->print(OS);
2109 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002110 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002111 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2112 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002113 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002114 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002115 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002116 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002117 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002118 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002119 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2120 << PostIdxReg.RegNum;
2121 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2122 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2123 << PostIdxReg.ShiftImm;
2124 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002125 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002126 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002127 OS << "<ARM_PROC::";
2128 unsigned IFlags = getProcIFlags();
2129 for (int i=2; i >= 0; --i)
2130 if (IFlags & (1 << i))
2131 OS << ARM_PROC::IFlagsToString(1 << i);
2132 OS << ">";
2133 break;
2134 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002135 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002136 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002137 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002138 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002139 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2140 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002141 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002142 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002143 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002144 << RegShiftedReg.SrcReg << " "
2145 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2146 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002147 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002148 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002149 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002150 << RegShiftedImm.SrcReg << " "
2151 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2152 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002153 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002154 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002155 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2156 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002157 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002158 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2159 << ", width: " << Bitfield.Width << ">";
2160 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002161 case k_RegisterList:
2162 case k_DPRRegisterList:
2163 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002164 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002165
Bill Wendlingbed94652010-11-09 23:28:44 +00002166 const SmallVectorImpl<unsigned> &RegList = getRegList();
2167 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002168 I = RegList.begin(), E = RegList.end(); I != E; ) {
2169 OS << *I;
2170 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002171 }
2172
2173 OS << ">";
2174 break;
2175 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002176 case k_VectorList:
2177 OS << "<vector_list " << VectorList.Count << " * "
2178 << VectorList.RegNum << ">";
2179 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002180 case k_VectorListAllLanes:
2181 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2182 << VectorList.RegNum << ">";
2183 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002184 case k_VectorListIndexed:
2185 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2186 << VectorList.Count << " * " << VectorList.RegNum << ">";
2187 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002188 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002189 OS << "'" << getToken() << "'";
2190 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002191 case k_VectorIndex:
2192 OS << "<vectorindex " << getVectorIndex() << ">";
2193 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002194 }
2195}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002196
2197/// @name Auto-generated Match Functions
2198/// {
2199
2200static unsigned MatchRegisterName(StringRef Name);
2201
2202/// }
2203
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002204bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2205 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002206 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002207 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002208 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002209
2210 return (RegNo == (unsigned)-1);
2211}
2212
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002213/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002214/// and if it is a register name the token is eaten and the register number is
2215/// returned. Otherwise return -1.
2216///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002217int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002218 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002219 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002220
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002221 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002222 unsigned RegNum = MatchRegisterName(lowerCase);
2223 if (!RegNum) {
2224 RegNum = StringSwitch<unsigned>(lowerCase)
2225 .Case("r13", ARM::SP)
2226 .Case("r14", ARM::LR)
2227 .Case("r15", ARM::PC)
2228 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002229 // Additional register name aliases for 'gas' compatibility.
2230 .Case("a1", ARM::R0)
2231 .Case("a2", ARM::R1)
2232 .Case("a3", ARM::R2)
2233 .Case("a4", ARM::R3)
2234 .Case("v1", ARM::R4)
2235 .Case("v2", ARM::R5)
2236 .Case("v3", ARM::R6)
2237 .Case("v4", ARM::R7)
2238 .Case("v5", ARM::R8)
2239 .Case("v6", ARM::R9)
2240 .Case("v7", ARM::R10)
2241 .Case("v8", ARM::R11)
2242 .Case("sb", ARM::R9)
2243 .Case("sl", ARM::R10)
2244 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002245 .Default(0);
2246 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002247 if (!RegNum) {
2248 // Check for aliases registered via .req.
2249 StringMap<unsigned>::const_iterator Entry =
2250 RegisterReqs.find(Tok.getIdentifier());
2251 // If no match, return failure.
2252 if (Entry == RegisterReqs.end())
2253 return -1;
2254 Parser.Lex(); // Eat identifier token.
2255 return Entry->getValue();
2256 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002257
Chris Lattner44e5981c2010-10-30 04:09:10 +00002258 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002259
Chris Lattner44e5981c2010-10-30 04:09:10 +00002260 return RegNum;
2261}
Jim Grosbach99710a82010-11-01 16:44:21 +00002262
Jim Grosbachbb24c592011-07-13 18:49:30 +00002263// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2264// If a recoverable error occurs, return 1. If an irrecoverable error
2265// occurs, return -1. An irrecoverable error is one where tokens have been
2266// consumed in the process of trying to parse the shifter (i.e., when it is
2267// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002268int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002269 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2270 SMLoc S = Parser.getTok().getLoc();
2271 const AsmToken &Tok = Parser.getTok();
2272 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2273
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002274 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002275 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002276 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002277 .Case("lsl", ARM_AM::lsl)
2278 .Case("lsr", ARM_AM::lsr)
2279 .Case("asr", ARM_AM::asr)
2280 .Case("ror", ARM_AM::ror)
2281 .Case("rrx", ARM_AM::rrx)
2282 .Default(ARM_AM::no_shift);
2283
2284 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002285 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002286
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002287 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002288
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002289 // The source register for the shift has already been added to the
2290 // operand list, so we need to pop it off and combine it into the shifted
2291 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002292 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002293 if (!PrevOp->isReg())
2294 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2295 int SrcReg = PrevOp->getReg();
2296 int64_t Imm = 0;
2297 int ShiftReg = 0;
2298 if (ShiftTy == ARM_AM::rrx) {
2299 // RRX Doesn't have an explicit shift amount. The encoder expects
2300 // the shift register to be the same as the source register. Seems odd,
2301 // but OK.
2302 ShiftReg = SrcReg;
2303 } else {
2304 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002305 if (Parser.getTok().is(AsmToken::Hash) ||
2306 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002307 Parser.Lex(); // Eat hash.
2308 SMLoc ImmLoc = Parser.getTok().getLoc();
2309 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002310 if (getParser().ParseExpression(ShiftExpr)) {
2311 Error(ImmLoc, "invalid immediate shift value");
2312 return -1;
2313 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002314 // The expression must be evaluatable as an immediate.
2315 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002316 if (!CE) {
2317 Error(ImmLoc, "invalid immediate shift value");
2318 return -1;
2319 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002320 // Range check the immediate.
2321 // lsl, ror: 0 <= imm <= 31
2322 // lsr, asr: 0 <= imm <= 32
2323 Imm = CE->getValue();
2324 if (Imm < 0 ||
2325 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2326 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002327 Error(ImmLoc, "immediate shift value out of range");
2328 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002329 }
2330 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002331 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002332 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002333 if (ShiftReg == -1) {
2334 Error (L, "expected immediate or register in shift operand");
2335 return -1;
2336 }
2337 } else {
2338 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002339 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002340 return -1;
2341 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002342 }
2343
Owen Andersonb595ed02011-07-21 18:54:16 +00002344 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2345 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002346 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002347 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002348 else
2349 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2350 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002351
Jim Grosbachbb24c592011-07-13 18:49:30 +00002352 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002353}
2354
2355
Bill Wendling2063b842010-11-18 23:43:05 +00002356/// Try to parse a register name. The token must be an Identifier when called.
2357/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2358/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002359///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002360/// TODO this is likely to change to allow different register types and or to
2361/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002362bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002363tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002364 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002365 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002366 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002367 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002368
Bill Wendling2063b842010-11-18 23:43:05 +00002369 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002370
Chris Lattner44e5981c2010-10-30 04:09:10 +00002371 const AsmToken &ExclaimTok = Parser.getTok();
2372 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002373 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2374 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002375 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002376 return false;
2377 }
2378
2379 // Also check for an index operand. This is only legal for vector registers,
2380 // but that'll get caught OK in operand matching, so we don't need to
2381 // explicitly filter everything else out here.
2382 if (Parser.getTok().is(AsmToken::LBrac)) {
2383 SMLoc SIdx = Parser.getTok().getLoc();
2384 Parser.Lex(); // Eat left bracket token.
2385
2386 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002387 if (getParser().ParseExpression(ImmVal))
2388 return MatchOperand_ParseFail;
2389 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2390 if (!MCE) {
2391 TokError("immediate value expected for vector index");
2392 return MatchOperand_ParseFail;
2393 }
2394
2395 SMLoc E = Parser.getTok().getLoc();
2396 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2397 Error(E, "']' expected");
2398 return MatchOperand_ParseFail;
2399 }
2400
2401 Parser.Lex(); // Eat right bracket token.
2402
2403 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2404 SIdx, E,
2405 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002406 }
2407
Bill Wendling2063b842010-11-18 23:43:05 +00002408 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002409}
2410
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002411/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2412/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2413/// "c5", ...
2414static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002415 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2416 // but efficient.
2417 switch (Name.size()) {
2418 default: break;
2419 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002420 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002421 return -1;
2422 switch (Name[1]) {
2423 default: return -1;
2424 case '0': return 0;
2425 case '1': return 1;
2426 case '2': return 2;
2427 case '3': return 3;
2428 case '4': return 4;
2429 case '5': return 5;
2430 case '6': return 6;
2431 case '7': return 7;
2432 case '8': return 8;
2433 case '9': return 9;
2434 }
2435 break;
2436 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002437 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002438 return -1;
2439 switch (Name[2]) {
2440 default: return -1;
2441 case '0': return 10;
2442 case '1': return 11;
2443 case '2': return 12;
2444 case '3': return 13;
2445 case '4': return 14;
2446 case '5': return 15;
2447 }
2448 break;
2449 }
2450
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002451 return -1;
2452}
2453
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002454/// parseITCondCode - Try to parse a condition code for an IT instruction.
2455ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2456parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2457 SMLoc S = Parser.getTok().getLoc();
2458 const AsmToken &Tok = Parser.getTok();
2459 if (!Tok.is(AsmToken::Identifier))
2460 return MatchOperand_NoMatch;
2461 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2462 .Case("eq", ARMCC::EQ)
2463 .Case("ne", ARMCC::NE)
2464 .Case("hs", ARMCC::HS)
2465 .Case("cs", ARMCC::HS)
2466 .Case("lo", ARMCC::LO)
2467 .Case("cc", ARMCC::LO)
2468 .Case("mi", ARMCC::MI)
2469 .Case("pl", ARMCC::PL)
2470 .Case("vs", ARMCC::VS)
2471 .Case("vc", ARMCC::VC)
2472 .Case("hi", ARMCC::HI)
2473 .Case("ls", ARMCC::LS)
2474 .Case("ge", ARMCC::GE)
2475 .Case("lt", ARMCC::LT)
2476 .Case("gt", ARMCC::GT)
2477 .Case("le", ARMCC::LE)
2478 .Case("al", ARMCC::AL)
2479 .Default(~0U);
2480 if (CC == ~0U)
2481 return MatchOperand_NoMatch;
2482 Parser.Lex(); // Eat the token.
2483
2484 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2485
2486 return MatchOperand_Success;
2487}
2488
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002489/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002490/// token must be an Identifier when called, and if it is a coprocessor
2491/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002492ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002493parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002494 SMLoc S = Parser.getTok().getLoc();
2495 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002496 if (Tok.isNot(AsmToken::Identifier))
2497 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002498
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002499 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002500 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002501 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002502
2503 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002504 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002505 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002506}
2507
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002508/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002509/// token must be an Identifier when called, and if it is a coprocessor
2510/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002511ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002512parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002513 SMLoc S = Parser.getTok().getLoc();
2514 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002515 if (Tok.isNot(AsmToken::Identifier))
2516 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002517
2518 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2519 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002520 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002521
2522 Parser.Lex(); // Eat identifier token.
2523 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002524 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002525}
2526
Jim Grosbach48399582011-10-12 17:34:41 +00002527/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2528/// coproc_option : '{' imm0_255 '}'
2529ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2530parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2531 SMLoc S = Parser.getTok().getLoc();
2532
2533 // If this isn't a '{', this isn't a coprocessor immediate operand.
2534 if (Parser.getTok().isNot(AsmToken::LCurly))
2535 return MatchOperand_NoMatch;
2536 Parser.Lex(); // Eat the '{'
2537
2538 const MCExpr *Expr;
2539 SMLoc Loc = Parser.getTok().getLoc();
2540 if (getParser().ParseExpression(Expr)) {
2541 Error(Loc, "illegal expression");
2542 return MatchOperand_ParseFail;
2543 }
2544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2545 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2546 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2547 return MatchOperand_ParseFail;
2548 }
2549 int Val = CE->getValue();
2550
2551 // Check for and consume the closing '}'
2552 if (Parser.getTok().isNot(AsmToken::RCurly))
2553 return MatchOperand_ParseFail;
2554 SMLoc E = Parser.getTok().getLoc();
2555 Parser.Lex(); // Eat the '}'
2556
2557 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2558 return MatchOperand_Success;
2559}
2560
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002561// For register list parsing, we need to map from raw GPR register numbering
2562// to the enumeration values. The enumeration values aren't sorted by
2563// register number due to our using "sp", "lr" and "pc" as canonical names.
2564static unsigned getNextRegister(unsigned Reg) {
2565 // If this is a GPR, we need to do it manually, otherwise we can rely
2566 // on the sort ordering of the enumeration since the other reg-classes
2567 // are sane.
2568 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2569 return Reg + 1;
2570 switch(Reg) {
2571 default: assert(0 && "Invalid GPR number!");
2572 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2573 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2574 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2575 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2576 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2577 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2578 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2579 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2580 }
2581}
2582
Jim Grosbach85a23432011-11-11 21:27:40 +00002583// Return the low-subreg of a given Q register.
2584static unsigned getDRegFromQReg(unsigned QReg) {
2585 switch (QReg) {
2586 default: llvm_unreachable("expected a Q register!");
2587 case ARM::Q0: return ARM::D0;
2588 case ARM::Q1: return ARM::D2;
2589 case ARM::Q2: return ARM::D4;
2590 case ARM::Q3: return ARM::D6;
2591 case ARM::Q4: return ARM::D8;
2592 case ARM::Q5: return ARM::D10;
2593 case ARM::Q6: return ARM::D12;
2594 case ARM::Q7: return ARM::D14;
2595 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002596 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002597 case ARM::Q10: return ARM::D20;
2598 case ARM::Q11: return ARM::D22;
2599 case ARM::Q12: return ARM::D24;
2600 case ARM::Q13: return ARM::D26;
2601 case ARM::Q14: return ARM::D28;
2602 case ARM::Q15: return ARM::D30;
2603 }
2604}
2605
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002606/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002607bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002608parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002609 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002610 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002611 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002612 Parser.Lex(); // Eat '{' token.
2613 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002614
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002615 // Check the first register in the list to see what register class
2616 // this is a list of.
2617 int Reg = tryParseRegister();
2618 if (Reg == -1)
2619 return Error(RegLoc, "register expected");
2620
Jim Grosbach85a23432011-11-11 21:27:40 +00002621 // The reglist instructions have at most 16 registers, so reserve
2622 // space for that many.
2623 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2624
2625 // Allow Q regs and just interpret them as the two D sub-registers.
2626 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2627 Reg = getDRegFromQReg(Reg);
2628 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2629 ++Reg;
2630 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002631 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002632 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2633 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2634 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2635 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2636 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2637 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2638 else
2639 return Error(RegLoc, "invalid register in register list");
2640
Jim Grosbach85a23432011-11-11 21:27:40 +00002641 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002642 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002643
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002644 // This starts immediately after the first register token in the list,
2645 // so we can see either a comma or a minus (range separator) as a legal
2646 // next token.
2647 while (Parser.getTok().is(AsmToken::Comma) ||
2648 Parser.getTok().is(AsmToken::Minus)) {
2649 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002650 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002651 SMLoc EndLoc = Parser.getTok().getLoc();
2652 int EndReg = tryParseRegister();
2653 if (EndReg == -1)
2654 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002655 // Allow Q regs and just interpret them as the two D sub-registers.
2656 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2657 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002658 // If the register is the same as the start reg, there's nothing
2659 // more to do.
2660 if (Reg == EndReg)
2661 continue;
2662 // The register must be in the same register class as the first.
2663 if (!RC->contains(EndReg))
2664 return Error(EndLoc, "invalid register in register list");
2665 // Ranges must go from low to high.
2666 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2667 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002668
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002669 // Add all the registers in the range to the register list.
2670 while (Reg != EndReg) {
2671 Reg = getNextRegister(Reg);
2672 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2673 }
2674 continue;
2675 }
2676 Parser.Lex(); // Eat the comma.
2677 RegLoc = Parser.getTok().getLoc();
2678 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002679 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002680 Reg = tryParseRegister();
2681 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002682 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002683 // Allow Q regs and just interpret them as the two D sub-registers.
2684 bool isQReg = false;
2685 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2686 Reg = getDRegFromQReg(Reg);
2687 isQReg = true;
2688 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002689 // The register must be in the same register class as the first.
2690 if (!RC->contains(Reg))
2691 return Error(RegLoc, "invalid register in register list");
2692 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002693 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002694 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002695 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2696 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2697 ") in register list");
2698 continue;
2699 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002700 // VFP register lists must also be contiguous.
2701 // It's OK to use the enumeration values directly here rather, as the
2702 // VFP register classes have the enum sorted properly.
2703 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2704 Reg != OldReg + 1)
2705 return Error(RegLoc, "non-contiguous register range");
2706 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002707 if (isQReg)
2708 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002709 }
2710
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002711 SMLoc E = Parser.getTok().getLoc();
2712 if (Parser.getTok().isNot(AsmToken::RCurly))
2713 return Error(E, "'}' expected");
2714 Parser.Lex(); // Eat '}' token.
2715
Jim Grosbach18bf3632011-12-13 21:48:29 +00002716 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002717 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002718
2719 // The ARM system instruction variants for LDM/STM have a '^' token here.
2720 if (Parser.getTok().is(AsmToken::Caret)) {
2721 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2722 Parser.Lex(); // Eat '^' token.
2723 }
2724
Bill Wendling2063b842010-11-18 23:43:05 +00002725 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002726}
2727
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002728// Helper function to parse the lane index for vector lists.
2729ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002730parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2731 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002732 if (Parser.getTok().is(AsmToken::LBrac)) {
2733 Parser.Lex(); // Eat the '['.
2734 if (Parser.getTok().is(AsmToken::RBrac)) {
2735 // "Dn[]" is the 'all lanes' syntax.
2736 LaneKind = AllLanes;
2737 Parser.Lex(); // Eat the ']'.
2738 return MatchOperand_Success;
2739 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002740 if (Parser.getTok().is(AsmToken::Integer)) {
2741 int64_t Val = Parser.getTok().getIntVal();
2742 // Make this range check context sensitive for .8, .16, .32.
2743 if (Val < 0 && Val > 7)
2744 Error(Parser.getTok().getLoc(), "lane index out of range");
2745 Index = Val;
2746 LaneKind = IndexedLane;
2747 Parser.Lex(); // Eat the token;
2748 if (Parser.getTok().isNot(AsmToken::RBrac))
2749 Error(Parser.getTok().getLoc(), "']' expected");
2750 Parser.Lex(); // Eat the ']'.
2751 return MatchOperand_Success;
2752 }
2753 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002754 return MatchOperand_ParseFail;
2755 }
2756 LaneKind = NoLanes;
2757 return MatchOperand_Success;
2758}
2759
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002760// parse a vector register list
2761ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2762parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002763 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002764 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002765 SMLoc S = Parser.getTok().getLoc();
2766 // As an extension (to match gas), support a plain D register or Q register
2767 // (without encosing curly braces) as a single or double entry list,
2768 // respectively.
2769 if (Parser.getTok().is(AsmToken::Identifier)) {
2770 int Reg = tryParseRegister();
2771 if (Reg == -1)
2772 return MatchOperand_NoMatch;
2773 SMLoc E = Parser.getTok().getLoc();
2774 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002775 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002776 if (Res != MatchOperand_Success)
2777 return Res;
2778 switch (LaneKind) {
2779 default:
2780 assert(0 && "unexpected lane kind!");
2781 case NoLanes:
2782 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002783 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002784 break;
2785 case AllLanes:
2786 E = Parser.getTok().getLoc();
2787 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2788 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002789 case IndexedLane:
2790 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2791 LaneIndex, S,E));
2792 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002793 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002794 return MatchOperand_Success;
2795 }
2796 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2797 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002798 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002799 if (Res != MatchOperand_Success)
2800 return Res;
2801 switch (LaneKind) {
2802 default:
2803 assert(0 && "unexpected lane kind!");
2804 case NoLanes:
2805 E = Parser.getTok().getLoc();
Jim Grosbach2f50e922011-12-15 21:44:33 +00002806 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002807 break;
2808 case AllLanes:
2809 E = Parser.getTok().getLoc();
2810 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2811 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002812 case IndexedLane:
2813 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2814 LaneIndex, S,E));
2815 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002816 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002817 return MatchOperand_Success;
2818 }
2819 Error(S, "vector register expected");
2820 return MatchOperand_ParseFail;
2821 }
2822
2823 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002824 return MatchOperand_NoMatch;
2825
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002826 Parser.Lex(); // Eat '{' token.
2827 SMLoc RegLoc = Parser.getTok().getLoc();
2828
2829 int Reg = tryParseRegister();
2830 if (Reg == -1) {
2831 Error(RegLoc, "register expected");
2832 return MatchOperand_ParseFail;
2833 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002834 unsigned Count = 1;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002835 unsigned Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00002836 unsigned FirstReg = Reg;
2837 // The list is of D registers, but we also allow Q regs and just interpret
2838 // them as the two D sub-registers.
2839 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2840 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00002841 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2842 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00002843 ++Reg;
2844 ++Count;
2845 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002846 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002847 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002848
Jim Grosbache891fe82011-11-15 23:19:15 +00002849 while (Parser.getTok().is(AsmToken::Comma) ||
2850 Parser.getTok().is(AsmToken::Minus)) {
2851 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002852 if (!Spacing)
2853 Spacing = 1; // Register range implies a single spaced list.
2854 else if (Spacing == 2) {
2855 Error(Parser.getTok().getLoc(),
2856 "sequential registers in double spaced list");
2857 return MatchOperand_ParseFail;
2858 }
Jim Grosbache891fe82011-11-15 23:19:15 +00002859 Parser.Lex(); // Eat the minus.
2860 SMLoc EndLoc = Parser.getTok().getLoc();
2861 int EndReg = tryParseRegister();
2862 if (EndReg == -1) {
2863 Error(EndLoc, "register expected");
2864 return MatchOperand_ParseFail;
2865 }
2866 // Allow Q regs and just interpret them as the two D sub-registers.
2867 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2868 EndReg = getDRegFromQReg(EndReg) + 1;
2869 // If the register is the same as the start reg, there's nothing
2870 // more to do.
2871 if (Reg == EndReg)
2872 continue;
2873 // The register must be in the same register class as the first.
2874 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2875 Error(EndLoc, "invalid register in register list");
2876 return MatchOperand_ParseFail;
2877 }
2878 // Ranges must go from low to high.
2879 if (Reg > EndReg) {
2880 Error(EndLoc, "bad range in register list");
2881 return MatchOperand_ParseFail;
2882 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002883 // Parse the lane specifier if present.
2884 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002885 unsigned NextLaneIndex;
2886 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002887 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002888 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002889 Error(EndLoc, "mismatched lane index in register list");
2890 return MatchOperand_ParseFail;
2891 }
2892 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002893
2894 // Add all the registers in the range to the register list.
2895 Count += EndReg - Reg;
2896 Reg = EndReg;
2897 continue;
2898 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002899 Parser.Lex(); // Eat the comma.
2900 RegLoc = Parser.getTok().getLoc();
2901 int OldReg = Reg;
2902 Reg = tryParseRegister();
2903 if (Reg == -1) {
2904 Error(RegLoc, "register expected");
2905 return MatchOperand_ParseFail;
2906 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002907 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002908 // It's OK to use the enumeration values directly here rather, as the
2909 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002910 //
2911 // The list is of D registers, but we also allow Q regs and just interpret
2912 // them as the two D sub-registers.
2913 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00002914 if (!Spacing)
2915 Spacing = 1; // Register range implies a single spaced list.
2916 else if (Spacing == 2) {
2917 Error(RegLoc,
2918 "invalid register in double-spaced list (must be 'D' register')");
2919 return MatchOperand_ParseFail;
2920 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002921 Reg = getDRegFromQReg(Reg);
2922 if (Reg != OldReg + 1) {
2923 Error(RegLoc, "non-contiguous register range");
2924 return MatchOperand_ParseFail;
2925 }
2926 ++Reg;
2927 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002928 // Parse the lane specifier if present.
2929 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002930 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002931 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002932 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002933 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002934 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002935 Error(EndLoc, "mismatched lane index in register list");
2936 return MatchOperand_ParseFail;
2937 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002938 continue;
2939 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00002940 // Normal D register.
2941 // Figure out the register spacing (single or double) of the list if
2942 // we don't know it already.
2943 if (!Spacing)
2944 Spacing = 1 + (Reg == OldReg + 2);
2945
2946 // Just check that it's contiguous and keep going.
2947 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002948 Error(RegLoc, "non-contiguous register range");
2949 return MatchOperand_ParseFail;
2950 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002951 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002952 // Parse the lane specifier if present.
2953 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002954 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002955 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002956 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002957 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002958 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002959 Error(EndLoc, "mismatched lane index in register list");
2960 return MatchOperand_ParseFail;
2961 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00002962 if (Spacing == 2 && LaneKind != NoLanes) {
2963 Error(EndLoc,
2964 "lane index specfier invalid in double spaced register list");
2965 return MatchOperand_ParseFail;
2966 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002967 }
2968
2969 SMLoc E = Parser.getTok().getLoc();
2970 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2971 Error(E, "'}' expected");
2972 return MatchOperand_ParseFail;
2973 }
2974 Parser.Lex(); // Eat '}' token.
2975
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002976 switch (LaneKind) {
2977 default:
2978 assert(0 && "unexpected lane kind in register list.");
2979 case NoLanes:
Jim Grosbach2f50e922011-12-15 21:44:33 +00002980 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
2981 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002982 break;
2983 case AllLanes:
2984 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2985 S, E));
2986 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002987 case IndexedLane:
2988 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2989 LaneIndex, S, E));
2990 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002991 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002992 return MatchOperand_Success;
2993}
2994
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002995/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002996ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002997parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002998 SMLoc S = Parser.getTok().getLoc();
2999 const AsmToken &Tok = Parser.getTok();
3000 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3001 StringRef OptStr = Tok.getString();
3002
3003 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3004 .Case("sy", ARM_MB::SY)
3005 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003006 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003007 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003008 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003009 .Case("ishst", ARM_MB::ISHST)
3010 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003011 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003012 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00003013 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003014 .Case("osh", ARM_MB::OSH)
3015 .Case("oshst", ARM_MB::OSHST)
3016 .Default(~0U);
3017
3018 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003019 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003020
3021 Parser.Lex(); // Eat identifier token.
3022 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003023 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003024}
3025
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003026/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003027ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003028parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003029 SMLoc S = Parser.getTok().getLoc();
3030 const AsmToken &Tok = Parser.getTok();
3031 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3032 StringRef IFlagsStr = Tok.getString();
3033
Owen Anderson10c5b122011-10-05 17:16:40 +00003034 // An iflags string of "none" is interpreted to mean that none of the AIF
3035 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003036 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003037 if (IFlagsStr != "none") {
3038 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3039 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3040 .Case("a", ARM_PROC::A)
3041 .Case("i", ARM_PROC::I)
3042 .Case("f", ARM_PROC::F)
3043 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003044
Owen Anderson10c5b122011-10-05 17:16:40 +00003045 // If some specific iflag is already set, it means that some letter is
3046 // present more than once, this is not acceptable.
3047 if (Flag == ~0U || (IFlags & Flag))
3048 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003049
Owen Anderson10c5b122011-10-05 17:16:40 +00003050 IFlags |= Flag;
3051 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003052 }
3053
3054 Parser.Lex(); // Eat identifier token.
3055 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3056 return MatchOperand_Success;
3057}
3058
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003059/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003060ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003061parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003062 SMLoc S = Parser.getTok().getLoc();
3063 const AsmToken &Tok = Parser.getTok();
3064 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3065 StringRef Mask = Tok.getString();
3066
James Molloy21efa7d2011-09-28 14:21:38 +00003067 if (isMClass()) {
3068 // See ARMv6-M 10.1.1
3069 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3070 .Case("apsr", 0)
3071 .Case("iapsr", 1)
3072 .Case("eapsr", 2)
3073 .Case("xpsr", 3)
3074 .Case("ipsr", 5)
3075 .Case("epsr", 6)
3076 .Case("iepsr", 7)
3077 .Case("msp", 8)
3078 .Case("psp", 9)
3079 .Case("primask", 16)
3080 .Case("basepri", 17)
3081 .Case("basepri_max", 18)
3082 .Case("faultmask", 19)
3083 .Case("control", 20)
3084 .Default(~0U);
3085
3086 if (FlagsVal == ~0U)
3087 return MatchOperand_NoMatch;
3088
3089 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3090 // basepri, basepri_max and faultmask only valid for V7m.
3091 return MatchOperand_NoMatch;
3092
3093 Parser.Lex(); // Eat identifier token.
3094 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3095 return MatchOperand_Success;
3096 }
3097
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003098 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3099 size_t Start = 0, Next = Mask.find('_');
3100 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003101 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003102 if (Next != StringRef::npos)
3103 Flags = Mask.slice(Next+1, Mask.size());
3104
3105 // FlagsVal contains the complete mask:
3106 // 3-0: Mask
3107 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3108 unsigned FlagsVal = 0;
3109
3110 if (SpecReg == "apsr") {
3111 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003112 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003113 .Case("g", 0x4) // same as CPSR_s
3114 .Case("nzcvqg", 0xc) // same as CPSR_fs
3115 .Default(~0U);
3116
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003117 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003118 if (!Flags.empty())
3119 return MatchOperand_NoMatch;
3120 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003121 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003122 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003123 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003124 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3125 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003126 for (int i = 0, e = Flags.size(); i != e; ++i) {
3127 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3128 .Case("c", 1)
3129 .Case("x", 2)
3130 .Case("s", 4)
3131 .Case("f", 8)
3132 .Default(~0U);
3133
3134 // If some specific flag is already set, it means that some letter is
3135 // present more than once, this is not acceptable.
3136 if (FlagsVal == ~0U || (FlagsVal & Flag))
3137 return MatchOperand_NoMatch;
3138 FlagsVal |= Flag;
3139 }
3140 } else // No match for special register.
3141 return MatchOperand_NoMatch;
3142
Owen Anderson03a173e2011-10-21 18:43:28 +00003143 // Special register without flags is NOT equivalent to "fc" flags.
3144 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3145 // two lines would enable gas compatibility at the expense of breaking
3146 // round-tripping.
3147 //
3148 // if (!FlagsVal)
3149 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003150
3151 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3152 if (SpecReg == "spsr")
3153 FlagsVal |= 16;
3154
3155 Parser.Lex(); // Eat identifier token.
3156 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3157 return MatchOperand_Success;
3158}
3159
Jim Grosbach27c1e252011-07-21 17:23:04 +00003160ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3161parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3162 int Low, int High) {
3163 const AsmToken &Tok = Parser.getTok();
3164 if (Tok.isNot(AsmToken::Identifier)) {
3165 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3166 return MatchOperand_ParseFail;
3167 }
3168 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003169 std::string LowerOp = Op.lower();
3170 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003171 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3172 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3173 return MatchOperand_ParseFail;
3174 }
3175 Parser.Lex(); // Eat shift type token.
3176
3177 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003178 if (Parser.getTok().isNot(AsmToken::Hash) &&
3179 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003180 Error(Parser.getTok().getLoc(), "'#' expected");
3181 return MatchOperand_ParseFail;
3182 }
3183 Parser.Lex(); // Eat hash token.
3184
3185 const MCExpr *ShiftAmount;
3186 SMLoc Loc = Parser.getTok().getLoc();
3187 if (getParser().ParseExpression(ShiftAmount)) {
3188 Error(Loc, "illegal expression");
3189 return MatchOperand_ParseFail;
3190 }
3191 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3192 if (!CE) {
3193 Error(Loc, "constant expression expected");
3194 return MatchOperand_ParseFail;
3195 }
3196 int Val = CE->getValue();
3197 if (Val < Low || Val > High) {
3198 Error(Loc, "immediate value out of range");
3199 return MatchOperand_ParseFail;
3200 }
3201
3202 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3203
3204 return MatchOperand_Success;
3205}
3206
Jim Grosbach0a547702011-07-22 17:44:50 +00003207ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3208parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3209 const AsmToken &Tok = Parser.getTok();
3210 SMLoc S = Tok.getLoc();
3211 if (Tok.isNot(AsmToken::Identifier)) {
3212 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3213 return MatchOperand_ParseFail;
3214 }
3215 int Val = StringSwitch<int>(Tok.getString())
3216 .Case("be", 1)
3217 .Case("le", 0)
3218 .Default(-1);
3219 Parser.Lex(); // Eat the token.
3220
3221 if (Val == -1) {
3222 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3223 return MatchOperand_ParseFail;
3224 }
3225 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3226 getContext()),
3227 S, Parser.getTok().getLoc()));
3228 return MatchOperand_Success;
3229}
3230
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003231/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3232/// instructions. Legal values are:
3233/// lsl #n 'n' in [0,31]
3234/// asr #n 'n' in [1,32]
3235/// n == 32 encoded as n == 0.
3236ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3237parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3238 const AsmToken &Tok = Parser.getTok();
3239 SMLoc S = Tok.getLoc();
3240 if (Tok.isNot(AsmToken::Identifier)) {
3241 Error(S, "shift operator 'asr' or 'lsl' expected");
3242 return MatchOperand_ParseFail;
3243 }
3244 StringRef ShiftName = Tok.getString();
3245 bool isASR;
3246 if (ShiftName == "lsl" || ShiftName == "LSL")
3247 isASR = false;
3248 else if (ShiftName == "asr" || ShiftName == "ASR")
3249 isASR = true;
3250 else {
3251 Error(S, "shift operator 'asr' or 'lsl' expected");
3252 return MatchOperand_ParseFail;
3253 }
3254 Parser.Lex(); // Eat the operator.
3255
3256 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003257 if (Parser.getTok().isNot(AsmToken::Hash) &&
3258 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003259 Error(Parser.getTok().getLoc(), "'#' expected");
3260 return MatchOperand_ParseFail;
3261 }
3262 Parser.Lex(); // Eat hash token.
3263
3264 const MCExpr *ShiftAmount;
3265 SMLoc E = Parser.getTok().getLoc();
3266 if (getParser().ParseExpression(ShiftAmount)) {
3267 Error(E, "malformed shift expression");
3268 return MatchOperand_ParseFail;
3269 }
3270 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3271 if (!CE) {
3272 Error(E, "shift amount must be an immediate");
3273 return MatchOperand_ParseFail;
3274 }
3275
3276 int64_t Val = CE->getValue();
3277 if (isASR) {
3278 // Shift amount must be in [1,32]
3279 if (Val < 1 || Val > 32) {
3280 Error(E, "'asr' shift amount must be in range [1,32]");
3281 return MatchOperand_ParseFail;
3282 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003283 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3284 if (isThumb() && Val == 32) {
3285 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3286 return MatchOperand_ParseFail;
3287 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003288 if (Val == 32) Val = 0;
3289 } else {
3290 // Shift amount must be in [1,32]
3291 if (Val < 0 || Val > 31) {
3292 Error(E, "'lsr' shift amount must be in range [0,31]");
3293 return MatchOperand_ParseFail;
3294 }
3295 }
3296
3297 E = Parser.getTok().getLoc();
3298 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3299
3300 return MatchOperand_Success;
3301}
3302
Jim Grosbach833b9d32011-07-27 20:15:40 +00003303/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3304/// of instructions. Legal values are:
3305/// ror #n 'n' in {0, 8, 16, 24}
3306ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3307parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3308 const AsmToken &Tok = Parser.getTok();
3309 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003310 if (Tok.isNot(AsmToken::Identifier))
3311 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003312 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003313 if (ShiftName != "ror" && ShiftName != "ROR")
3314 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003315 Parser.Lex(); // Eat the operator.
3316
3317 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003318 if (Parser.getTok().isNot(AsmToken::Hash) &&
3319 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003320 Error(Parser.getTok().getLoc(), "'#' expected");
3321 return MatchOperand_ParseFail;
3322 }
3323 Parser.Lex(); // Eat hash token.
3324
3325 const MCExpr *ShiftAmount;
3326 SMLoc E = Parser.getTok().getLoc();
3327 if (getParser().ParseExpression(ShiftAmount)) {
3328 Error(E, "malformed rotate expression");
3329 return MatchOperand_ParseFail;
3330 }
3331 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3332 if (!CE) {
3333 Error(E, "rotate amount must be an immediate");
3334 return MatchOperand_ParseFail;
3335 }
3336
3337 int64_t Val = CE->getValue();
3338 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3339 // normally, zero is represented in asm by omitting the rotate operand
3340 // entirely.
3341 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3342 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3343 return MatchOperand_ParseFail;
3344 }
3345
3346 E = Parser.getTok().getLoc();
3347 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3348
3349 return MatchOperand_Success;
3350}
3351
Jim Grosbach864b6092011-07-28 21:34:26 +00003352ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3353parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3354 SMLoc S = Parser.getTok().getLoc();
3355 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003356 if (Parser.getTok().isNot(AsmToken::Hash) &&
3357 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003358 Error(Parser.getTok().getLoc(), "'#' expected");
3359 return MatchOperand_ParseFail;
3360 }
3361 Parser.Lex(); // Eat hash token.
3362
3363 const MCExpr *LSBExpr;
3364 SMLoc E = Parser.getTok().getLoc();
3365 if (getParser().ParseExpression(LSBExpr)) {
3366 Error(E, "malformed immediate expression");
3367 return MatchOperand_ParseFail;
3368 }
3369 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3370 if (!CE) {
3371 Error(E, "'lsb' operand must be an immediate");
3372 return MatchOperand_ParseFail;
3373 }
3374
3375 int64_t LSB = CE->getValue();
3376 // The LSB must be in the range [0,31]
3377 if (LSB < 0 || LSB > 31) {
3378 Error(E, "'lsb' operand must be in the range [0,31]");
3379 return MatchOperand_ParseFail;
3380 }
3381 E = Parser.getTok().getLoc();
3382
3383 // Expect another immediate operand.
3384 if (Parser.getTok().isNot(AsmToken::Comma)) {
3385 Error(Parser.getTok().getLoc(), "too few operands");
3386 return MatchOperand_ParseFail;
3387 }
3388 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003389 if (Parser.getTok().isNot(AsmToken::Hash) &&
3390 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003391 Error(Parser.getTok().getLoc(), "'#' expected");
3392 return MatchOperand_ParseFail;
3393 }
3394 Parser.Lex(); // Eat hash token.
3395
3396 const MCExpr *WidthExpr;
3397 if (getParser().ParseExpression(WidthExpr)) {
3398 Error(E, "malformed immediate expression");
3399 return MatchOperand_ParseFail;
3400 }
3401 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3402 if (!CE) {
3403 Error(E, "'width' operand must be an immediate");
3404 return MatchOperand_ParseFail;
3405 }
3406
3407 int64_t Width = CE->getValue();
3408 // The LSB must be in the range [1,32-lsb]
3409 if (Width < 1 || Width > 32 - LSB) {
3410 Error(E, "'width' operand must be in the range [1,32-lsb]");
3411 return MatchOperand_ParseFail;
3412 }
3413 E = Parser.getTok().getLoc();
3414
3415 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3416
3417 return MatchOperand_Success;
3418}
3419
Jim Grosbachd3595712011-08-03 23:50:40 +00003420ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3421parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3422 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003423 // postidx_reg := '+' register {, shift}
3424 // | '-' register {, shift}
3425 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003426
3427 // This method must return MatchOperand_NoMatch without consuming any tokens
3428 // in the case where there is no match, as other alternatives take other
3429 // parse methods.
3430 AsmToken Tok = Parser.getTok();
3431 SMLoc S = Tok.getLoc();
3432 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003433 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003434 int Reg = -1;
3435 if (Tok.is(AsmToken::Plus)) {
3436 Parser.Lex(); // Eat the '+' token.
3437 haveEaten = true;
3438 } else if (Tok.is(AsmToken::Minus)) {
3439 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003440 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003441 haveEaten = true;
3442 }
3443 if (Parser.getTok().is(AsmToken::Identifier))
3444 Reg = tryParseRegister();
3445 if (Reg == -1) {
3446 if (!haveEaten)
3447 return MatchOperand_NoMatch;
3448 Error(Parser.getTok().getLoc(), "register expected");
3449 return MatchOperand_ParseFail;
3450 }
3451 SMLoc E = Parser.getTok().getLoc();
3452
Jim Grosbachc320c852011-08-05 21:28:30 +00003453 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3454 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003455 if (Parser.getTok().is(AsmToken::Comma)) {
3456 Parser.Lex(); // Eat the ','.
3457 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3458 return MatchOperand_ParseFail;
3459 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003460
3461 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3462 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003463
3464 return MatchOperand_Success;
3465}
3466
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003467ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3468parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3469 // Check for a post-index addressing register operand. Specifically:
3470 // am3offset := '+' register
3471 // | '-' register
3472 // | register
3473 // | # imm
3474 // | # + imm
3475 // | # - imm
3476
3477 // This method must return MatchOperand_NoMatch without consuming any tokens
3478 // in the case where there is no match, as other alternatives take other
3479 // parse methods.
3480 AsmToken Tok = Parser.getTok();
3481 SMLoc S = Tok.getLoc();
3482
3483 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003484 if (Parser.getTok().is(AsmToken::Hash) ||
3485 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003486 Parser.Lex(); // Eat the '#'.
3487 // Explicitly look for a '-', as we need to encode negative zero
3488 // differently.
3489 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3490 const MCExpr *Offset;
3491 if (getParser().ParseExpression(Offset))
3492 return MatchOperand_ParseFail;
3493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3494 if (!CE) {
3495 Error(S, "constant expression expected");
3496 return MatchOperand_ParseFail;
3497 }
3498 SMLoc E = Tok.getLoc();
3499 // Negative zero is encoded as the flag value INT32_MIN.
3500 int32_t Val = CE->getValue();
3501 if (isNegative && Val == 0)
3502 Val = INT32_MIN;
3503
3504 Operands.push_back(
3505 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3506
3507 return MatchOperand_Success;
3508 }
3509
3510
3511 bool haveEaten = false;
3512 bool isAdd = true;
3513 int Reg = -1;
3514 if (Tok.is(AsmToken::Plus)) {
3515 Parser.Lex(); // Eat the '+' token.
3516 haveEaten = true;
3517 } else if (Tok.is(AsmToken::Minus)) {
3518 Parser.Lex(); // Eat the '-' token.
3519 isAdd = false;
3520 haveEaten = true;
3521 }
3522 if (Parser.getTok().is(AsmToken::Identifier))
3523 Reg = tryParseRegister();
3524 if (Reg == -1) {
3525 if (!haveEaten)
3526 return MatchOperand_NoMatch;
3527 Error(Parser.getTok().getLoc(), "register expected");
3528 return MatchOperand_ParseFail;
3529 }
3530 SMLoc E = Parser.getTok().getLoc();
3531
3532 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3533 0, S, E));
3534
3535 return MatchOperand_Success;
3536}
3537
Jim Grosbach7db8d692011-09-08 22:07:06 +00003538/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3539/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3540/// when they refer multiple MIOperands inside a single one.
3541bool ARMAsmParser::
3542cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3543 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3544 // Rt, Rt2
3545 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3546 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3547 // Create a writeback register dummy placeholder.
3548 Inst.addOperand(MCOperand::CreateReg(0));
3549 // addr
3550 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3551 // pred
3552 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3553 return true;
3554}
3555
3556/// cvtT2StrdPre - Convert parsed operands to MCInst.
3557/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3558/// when they refer multiple MIOperands inside a single one.
3559bool ARMAsmParser::
3560cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3561 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3562 // Create a writeback register dummy placeholder.
3563 Inst.addOperand(MCOperand::CreateReg(0));
3564 // Rt, Rt2
3565 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3566 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3567 // addr
3568 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3569 // pred
3570 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3571 return true;
3572}
3573
Jim Grosbachc086f682011-09-08 00:39:19 +00003574/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3575/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3576/// when they refer multiple MIOperands inside a single one.
3577bool ARMAsmParser::
3578cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3579 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3580 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3581
3582 // Create a writeback register dummy placeholder.
3583 Inst.addOperand(MCOperand::CreateImm(0));
3584
3585 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3586 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3587 return true;
3588}
3589
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003590/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3591/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3592/// when they refer multiple MIOperands inside a single one.
3593bool ARMAsmParser::
3594cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3595 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3596 // Create a writeback register dummy placeholder.
3597 Inst.addOperand(MCOperand::CreateImm(0));
3598 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3599 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3600 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3601 return true;
3602}
3603
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003604/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003605/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3606/// when they refer multiple MIOperands inside a single one.
3607bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003608cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003609 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3610 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3611
3612 // Create a writeback register dummy placeholder.
3613 Inst.addOperand(MCOperand::CreateImm(0));
3614
Jim Grosbachd3595712011-08-03 23:50:40 +00003615 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003616 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3617 return true;
3618}
3619
Owen Anderson16d33f32011-08-26 20:43:14 +00003620/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3621/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3622/// when they refer multiple MIOperands inside a single one.
3623bool ARMAsmParser::
3624cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3625 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3626 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3627
3628 // Create a writeback register dummy placeholder.
3629 Inst.addOperand(MCOperand::CreateImm(0));
3630
3631 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3632 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3633 return true;
3634}
3635
3636
Jim Grosbachd564bf32011-08-11 19:22:40 +00003637/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3638/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3639/// when they refer multiple MIOperands inside a single one.
3640bool ARMAsmParser::
3641cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3642 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3643 // Create a writeback register dummy placeholder.
3644 Inst.addOperand(MCOperand::CreateImm(0));
3645 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3646 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3647 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3648 return true;
3649}
3650
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003651/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003652/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3653/// when they refer multiple MIOperands inside a single one.
3654bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003655cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003656 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3657 // Create a writeback register dummy placeholder.
3658 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003659 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3660 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3661 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003662 return true;
3663}
3664
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003665/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3666/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3667/// when they refer multiple MIOperands inside a single one.
3668bool ARMAsmParser::
3669cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3670 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3671 // Create a writeback register dummy placeholder.
3672 Inst.addOperand(MCOperand::CreateImm(0));
3673 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3674 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3675 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3676 return true;
3677}
3678
Jim Grosbachd3595712011-08-03 23:50:40 +00003679/// cvtLdExtTWriteBackImm - 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::
3683cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3684 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3685 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003686 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003687 // Create a writeback register dummy placeholder.
3688 Inst.addOperand(MCOperand::CreateImm(0));
3689 // addr
3690 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3691 // offset
3692 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3693 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003694 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3695 return true;
3696}
3697
Jim Grosbachd3595712011-08-03 23:50:40 +00003698/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003699/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3700/// when they refer multiple MIOperands inside a single one.
3701bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003702cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3703 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3704 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003705 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003706 // Create a writeback register dummy placeholder.
3707 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003708 // addr
3709 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3710 // offset
3711 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3712 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003713 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3714 return true;
3715}
3716
Jim Grosbachd3595712011-08-03 23:50:40 +00003717/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003718/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3719/// when they refer multiple MIOperands inside a single one.
3720bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003721cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3722 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003723 // Create a writeback register dummy placeholder.
3724 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003725 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003726 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003727 // addr
3728 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3729 // offset
3730 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3731 // pred
3732 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3733 return true;
3734}
3735
3736/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3737/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3738/// when they refer multiple MIOperands inside a single one.
3739bool ARMAsmParser::
3740cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3741 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3742 // Create a writeback register dummy placeholder.
3743 Inst.addOperand(MCOperand::CreateImm(0));
3744 // Rt
3745 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3746 // addr
3747 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3748 // offset
3749 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3750 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003751 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3752 return true;
3753}
3754
Jim Grosbach5b96b802011-08-10 20:29:19 +00003755/// cvtLdrdPre - Convert parsed operands to MCInst.
3756/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3757/// when they refer multiple MIOperands inside a single one.
3758bool ARMAsmParser::
3759cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3760 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3761 // Rt, Rt2
3762 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3763 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3764 // Create a writeback register dummy placeholder.
3765 Inst.addOperand(MCOperand::CreateImm(0));
3766 // addr
3767 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3768 // pred
3769 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3770 return true;
3771}
3772
Jim Grosbacheb09f492011-08-11 20:28:23 +00003773/// cvtStrdPre - Convert parsed operands to MCInst.
3774/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3775/// when they refer multiple MIOperands inside a single one.
3776bool ARMAsmParser::
3777cvtStrdPre(MCInst &Inst, unsigned Opcode,
3778 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3779 // Create a writeback register dummy placeholder.
3780 Inst.addOperand(MCOperand::CreateImm(0));
3781 // Rt, Rt2
3782 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3783 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3784 // addr
3785 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3786 // pred
3787 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3788 return true;
3789}
3790
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003791/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3792/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3793/// when they refer multiple MIOperands inside a single one.
3794bool ARMAsmParser::
3795cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3796 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3797 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3798 // Create a writeback register dummy placeholder.
3799 Inst.addOperand(MCOperand::CreateImm(0));
3800 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3801 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3802 return true;
3803}
3804
Jim Grosbach8e048492011-08-19 22:07:46 +00003805/// cvtThumbMultiple- Convert parsed operands to MCInst.
3806/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3807/// when they refer multiple MIOperands inside a single one.
3808bool ARMAsmParser::
3809cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3810 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3811 // The second source operand must be the same register as the destination
3812 // operand.
3813 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003814 (((ARMOperand*)Operands[3])->getReg() !=
3815 ((ARMOperand*)Operands[5])->getReg()) &&
3816 (((ARMOperand*)Operands[3])->getReg() !=
3817 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003818 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003819 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003820 return false;
3821 }
3822 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3823 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003824 // If we have a three-operand form, make sure to set Rn to be the operand
3825 // that isn't the same as Rd.
3826 unsigned RegOp = 4;
3827 if (Operands.size() == 6 &&
3828 ((ARMOperand*)Operands[4])->getReg() ==
3829 ((ARMOperand*)Operands[3])->getReg())
3830 RegOp = 5;
3831 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3832 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003833 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3834
3835 return true;
3836}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003837
Jim Grosbach3ea06572011-10-24 22:16:58 +00003838bool ARMAsmParser::
3839cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3840 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3841 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003842 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003843 // Create a writeback register dummy placeholder.
3844 Inst.addOperand(MCOperand::CreateImm(0));
3845 // Vn
3846 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3847 // pred
3848 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3849 return true;
3850}
3851
3852bool ARMAsmParser::
3853cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3854 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3855 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003856 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003857 // Create a writeback register dummy placeholder.
3858 Inst.addOperand(MCOperand::CreateImm(0));
3859 // Vn
3860 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3861 // Vm
3862 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3863 // pred
3864 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3865 return true;
3866}
3867
Jim Grosbach05df4602011-10-31 21:50:31 +00003868bool ARMAsmParser::
3869cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3870 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3871 // Create a writeback register dummy placeholder.
3872 Inst.addOperand(MCOperand::CreateImm(0));
3873 // Vn
3874 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3875 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003876 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003877 // pred
3878 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3879 return true;
3880}
3881
3882bool ARMAsmParser::
3883cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3884 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3885 // Create a writeback register dummy placeholder.
3886 Inst.addOperand(MCOperand::CreateImm(0));
3887 // Vn
3888 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3889 // Vm
3890 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3891 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003892 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003893 // pred
3894 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3895 return true;
3896}
3897
Bill Wendlinge18980a2010-11-06 22:36:58 +00003898/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003899/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003900bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003901parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003902 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003903 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003904 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003905 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003906 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003907
Sean Callanan936b0d32010-01-19 21:44:56 +00003908 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003909 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003910 if (BaseRegNum == -1)
3911 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003912
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003913 // The next token must either be a comma or a closing bracket.
3914 const AsmToken &Tok = Parser.getTok();
3915 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003916 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003917
Jim Grosbachd3595712011-08-03 23:50:40 +00003918 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003919 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003920 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003921
Jim Grosbachd3595712011-08-03 23:50:40 +00003922 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003923 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003924
Jim Grosbach40700e02011-09-19 18:42:21 +00003925 // If there's a pre-indexing writeback marker, '!', just add it as a token
3926 // operand. It's rather odd, but syntactically valid.
3927 if (Parser.getTok().is(AsmToken::Exclaim)) {
3928 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3929 Parser.Lex(); // Eat the '!'.
3930 }
3931
Jim Grosbachd3595712011-08-03 23:50:40 +00003932 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003933 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003934
Jim Grosbachd3595712011-08-03 23:50:40 +00003935 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3936 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003937
Jim Grosbacha95ec992011-10-11 17:29:55 +00003938 // If we have a ':', it's an alignment specifier.
3939 if (Parser.getTok().is(AsmToken::Colon)) {
3940 Parser.Lex(); // Eat the ':'.
3941 E = Parser.getTok().getLoc();
3942
3943 const MCExpr *Expr;
3944 if (getParser().ParseExpression(Expr))
3945 return true;
3946
3947 // The expression has to be a constant. Memory references with relocations
3948 // don't come through here, as they use the <label> forms of the relevant
3949 // instructions.
3950 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3951 if (!CE)
3952 return Error (E, "constant expression expected");
3953
3954 unsigned Align = 0;
3955 switch (CE->getValue()) {
3956 default:
3957 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3958 case 64: Align = 8; break;
3959 case 128: Align = 16; break;
3960 case 256: Align = 32; break;
3961 }
3962
3963 // Now we should have the closing ']'
3964 E = Parser.getTok().getLoc();
3965 if (Parser.getTok().isNot(AsmToken::RBrac))
3966 return Error(E, "']' expected");
3967 Parser.Lex(); // Eat right bracket token.
3968
3969 // Don't worry about range checking the value here. That's handled by
3970 // the is*() predicates.
3971 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3972 ARM_AM::no_shift, 0, Align,
3973 false, S, E));
3974
3975 // If there's a pre-indexing writeback marker, '!', just add it as a token
3976 // operand.
3977 if (Parser.getTok().is(AsmToken::Exclaim)) {
3978 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3979 Parser.Lex(); // Eat the '!'.
3980 }
3981
3982 return false;
3983 }
3984
3985 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00003986 // offset. Be friendly and also accept a plain integer (without a leading
3987 // hash) for gas compatibility.
3988 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003989 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00003990 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003991 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00003992 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00003993 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003994
Owen Anderson967674d2011-08-29 19:36:44 +00003995 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003996 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003997 if (getParser().ParseExpression(Offset))
3998 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003999
4000 // The expression has to be a constant. Memory references with relocations
4001 // don't come through here, as they use the <label> forms of the relevant
4002 // instructions.
4003 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4004 if (!CE)
4005 return Error (E, "constant expression expected");
4006
Owen Anderson967674d2011-08-29 19:36:44 +00004007 // If the constant was #-0, represent it as INT32_MIN.
4008 int32_t Val = CE->getValue();
4009 if (isNegative && Val == 0)
4010 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4011
Jim Grosbachd3595712011-08-03 23:50:40 +00004012 // Now we should have the closing ']'
4013 E = Parser.getTok().getLoc();
4014 if (Parser.getTok().isNot(AsmToken::RBrac))
4015 return Error(E, "']' expected");
4016 Parser.Lex(); // Eat right bracket token.
4017
4018 // Don't worry about range checking the value here. That's handled by
4019 // the is*() predicates.
4020 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004021 ARM_AM::no_shift, 0, 0,
4022 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004023
4024 // If there's a pre-indexing writeback marker, '!', just add it as a token
4025 // operand.
4026 if (Parser.getTok().is(AsmToken::Exclaim)) {
4027 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4028 Parser.Lex(); // Eat the '!'.
4029 }
4030
4031 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004032 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004033
4034 // The register offset is optionally preceded by a '+' or '-'
4035 bool isNegative = false;
4036 if (Parser.getTok().is(AsmToken::Minus)) {
4037 isNegative = true;
4038 Parser.Lex(); // Eat the '-'.
4039 } else if (Parser.getTok().is(AsmToken::Plus)) {
4040 // Nothing to do.
4041 Parser.Lex(); // Eat the '+'.
4042 }
4043
4044 E = Parser.getTok().getLoc();
4045 int OffsetRegNum = tryParseRegister();
4046 if (OffsetRegNum == -1)
4047 return Error(E, "register expected");
4048
4049 // If there's a shift operator, handle it.
4050 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004051 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004052 if (Parser.getTok().is(AsmToken::Comma)) {
4053 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004054 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004055 return true;
4056 }
4057
4058 // Now we should have the closing ']'
4059 E = Parser.getTok().getLoc();
4060 if (Parser.getTok().isNot(AsmToken::RBrac))
4061 return Error(E, "']' expected");
4062 Parser.Lex(); // Eat right bracket token.
4063
4064 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004065 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004066 S, E));
4067
Jim Grosbachc320c852011-08-05 21:28:30 +00004068 // If there's a pre-indexing writeback marker, '!', just add it as a token
4069 // operand.
4070 if (Parser.getTok().is(AsmToken::Exclaim)) {
4071 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4072 Parser.Lex(); // Eat the '!'.
4073 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004074
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004075 return false;
4076}
4077
Jim Grosbachd3595712011-08-03 23:50:40 +00004078/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004079/// ( lsl | lsr | asr | ror ) , # shift_amount
4080/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004081/// return true if it parses a shift otherwise it returns false.
4082bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4083 unsigned &Amount) {
4084 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004085 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004086 if (Tok.isNot(AsmToken::Identifier))
4087 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004088 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004089 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4090 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004091 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004092 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004093 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004094 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004095 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004096 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004097 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004098 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004099 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004100 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004101 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004102 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004103
Jim Grosbachd3595712011-08-03 23:50:40 +00004104 // rrx stands alone.
4105 Amount = 0;
4106 if (St != ARM_AM::rrx) {
4107 Loc = Parser.getTok().getLoc();
4108 // A '#' and a shift amount.
4109 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004110 if (HashTok.isNot(AsmToken::Hash) &&
4111 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004112 return Error(HashTok.getLoc(), "'#' expected");
4113 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004114
Jim Grosbachd3595712011-08-03 23:50:40 +00004115 const MCExpr *Expr;
4116 if (getParser().ParseExpression(Expr))
4117 return true;
4118 // Range check the immediate.
4119 // lsl, ror: 0 <= imm <= 31
4120 // lsr, asr: 0 <= imm <= 32
4121 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4122 if (!CE)
4123 return Error(Loc, "shift amount must be an immediate");
4124 int64_t Imm = CE->getValue();
4125 if (Imm < 0 ||
4126 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4127 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4128 return Error(Loc, "immediate shift value out of range");
4129 Amount = Imm;
4130 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004131
4132 return false;
4133}
4134
Jim Grosbache7fbce72011-10-03 23:38:36 +00004135/// parseFPImm - A floating point immediate expression operand.
4136ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4137parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4138 SMLoc S = Parser.getTok().getLoc();
4139
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004140 if (Parser.getTok().isNot(AsmToken::Hash) &&
4141 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004142 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004143
4144 // Disambiguate the VMOV forms that can accept an FP immediate.
4145 // vmov.f32 <sreg>, #imm
4146 // vmov.f64 <dreg>, #imm
4147 // vmov.f32 <dreg>, #imm @ vector f32x2
4148 // vmov.f32 <qreg>, #imm @ vector f32x4
4149 //
4150 // There are also the NEON VMOV instructions which expect an
4151 // integer constant. Make sure we don't try to parse an FPImm
4152 // for these:
4153 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4154 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4155 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4156 TyOp->getToken() != ".f64"))
4157 return MatchOperand_NoMatch;
4158
Jim Grosbache7fbce72011-10-03 23:38:36 +00004159 Parser.Lex(); // Eat the '#'.
4160
4161 // Handle negation, as that still comes through as a separate token.
4162 bool isNegative = false;
4163 if (Parser.getTok().is(AsmToken::Minus)) {
4164 isNegative = true;
4165 Parser.Lex();
4166 }
4167 const AsmToken &Tok = Parser.getTok();
4168 if (Tok.is(AsmToken::Real)) {
4169 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4170 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4171 // If we had a '-' in front, toggle the sign bit.
4172 IntVal ^= (uint64_t)isNegative << 63;
4173 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4174 Parser.Lex(); // Eat the token.
4175 if (Val == -1) {
4176 TokError("floating point value out of range");
4177 return MatchOperand_ParseFail;
4178 }
4179 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4180 return MatchOperand_Success;
4181 }
4182 if (Tok.is(AsmToken::Integer)) {
4183 int64_t Val = Tok.getIntVal();
4184 Parser.Lex(); // Eat the token.
4185 if (Val > 255 || Val < 0) {
4186 TokError("encoded floating point value out of range");
4187 return MatchOperand_ParseFail;
4188 }
4189 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4190 return MatchOperand_Success;
4191 }
4192
4193 TokError("invalid floating point immediate");
4194 return MatchOperand_ParseFail;
4195}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004196/// Parse a arm instruction operand. For now this parses the operand regardless
4197/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004198bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004199 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004200 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004201
4202 // Check if the current operand has a custom associated parser, if so, try to
4203 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004204 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4205 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004206 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004207 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4208 // there was a match, but an error occurred, in which case, just return that
4209 // the operand parsing failed.
4210 if (ResTy == MatchOperand_ParseFail)
4211 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004212
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004213 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004214 default:
4215 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004216 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004217 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004218 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004219 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004220 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004221 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004222 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004223 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004224 else if (Res == -1) // irrecoverable error
4225 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004226 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4227 S = Parser.getTok().getLoc();
4228 Parser.Lex();
4229 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4230 return false;
4231 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004232
4233 // Fall though for the Identifier case that is not a register or a
4234 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004235 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004236 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004237 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004238 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004239 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004240 // This was not a register so parse other operands that start with an
4241 // identifier (like labels) as expressions and create them as immediates.
4242 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004243 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004244 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004245 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004246 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004247 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4248 return false;
4249 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004250 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004251 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004252 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004253 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004254 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004255 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004256 // #42 -> immediate.
4257 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004258 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004259 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004260 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004261 const MCExpr *ImmVal;
4262 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004263 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004264 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004265 if (CE) {
4266 int32_t Val = CE->getValue();
4267 if (isNegative && Val == 0)
4268 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004269 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004270 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004271 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4272 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004273 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004274 case AsmToken::Colon: {
4275 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004276 // FIXME: Check it's an expression prefix,
4277 // e.g. (FOO - :lower16:BAR) isn't legal.
4278 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004279 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004280 return true;
4281
Evan Cheng965b3c72011-01-13 07:58:56 +00004282 const MCExpr *SubExprVal;
4283 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004284 return true;
4285
Evan Cheng965b3c72011-01-13 07:58:56 +00004286 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4287 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004288 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004289 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004290 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004291 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004292 }
4293}
4294
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004295// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004296// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004297bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004298 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004299
4300 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004301 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004302 Parser.Lex(); // Eat ':'
4303
4304 if (getLexer().isNot(AsmToken::Identifier)) {
4305 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4306 return true;
4307 }
4308
4309 StringRef IDVal = Parser.getTok().getIdentifier();
4310 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004311 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004312 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004313 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004314 } else {
4315 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4316 return true;
4317 }
4318 Parser.Lex();
4319
4320 if (getLexer().isNot(AsmToken::Colon)) {
4321 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4322 return true;
4323 }
4324 Parser.Lex(); // Eat the last ':'
4325 return false;
4326}
4327
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004328/// \brief Given a mnemonic, split out possible predication code and carry
4329/// setting letters to form a canonical mnemonic and flags.
4330//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004331// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004332// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004333StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004334 unsigned &PredicationCode,
4335 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004336 unsigned &ProcessorIMod,
4337 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004338 PredicationCode = ARMCC::AL;
4339 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004340 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004341
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004342 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004343 //
4344 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004345 if ((Mnemonic == "movs" && isThumb()) ||
4346 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4347 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4348 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4349 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4350 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4351 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4352 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004353 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004354
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004355 // First, split out any predication code. Ignore mnemonics we know aren't
4356 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004357 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004358 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004359 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004360 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004361 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4362 .Case("eq", ARMCC::EQ)
4363 .Case("ne", ARMCC::NE)
4364 .Case("hs", ARMCC::HS)
4365 .Case("cs", ARMCC::HS)
4366 .Case("lo", ARMCC::LO)
4367 .Case("cc", ARMCC::LO)
4368 .Case("mi", ARMCC::MI)
4369 .Case("pl", ARMCC::PL)
4370 .Case("vs", ARMCC::VS)
4371 .Case("vc", ARMCC::VC)
4372 .Case("hi", ARMCC::HI)
4373 .Case("ls", ARMCC::LS)
4374 .Case("ge", ARMCC::GE)
4375 .Case("lt", ARMCC::LT)
4376 .Case("gt", ARMCC::GT)
4377 .Case("le", ARMCC::LE)
4378 .Case("al", ARMCC::AL)
4379 .Default(~0U);
4380 if (CC != ~0U) {
4381 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4382 PredicationCode = CC;
4383 }
Bill Wendling193961b2010-10-29 23:50:21 +00004384 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004385
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004386 // Next, determine if we have a carry setting bit. We explicitly ignore all
4387 // the instructions we know end in 's'.
4388 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004389 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004390 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4391 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4392 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004393 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004394 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach2a2348e2011-12-13 20:13:48 +00004395 Mnemonic == "fsts" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004396 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004397 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4398 CarrySetting = true;
4399 }
4400
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004401 // The "cps" instruction can have a interrupt mode operand which is glued into
4402 // the mnemonic. Check if this is the case, split it and parse the imod op
4403 if (Mnemonic.startswith("cps")) {
4404 // Split out any imod code.
4405 unsigned IMod =
4406 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4407 .Case("ie", ARM_PROC::IE)
4408 .Case("id", ARM_PROC::ID)
4409 .Default(~0U);
4410 if (IMod != ~0U) {
4411 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4412 ProcessorIMod = IMod;
4413 }
4414 }
4415
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004416 // The "it" instruction has the condition mask on the end of the mnemonic.
4417 if (Mnemonic.startswith("it")) {
4418 ITMask = Mnemonic.slice(2, Mnemonic.size());
4419 Mnemonic = Mnemonic.slice(0, 2);
4420 }
4421
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004422 return Mnemonic;
4423}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004424
4425/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4426/// inclusion of carry set or predication code operands.
4427//
4428// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004429void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004430getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004431 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004432 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4433 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004434 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004435 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004436 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004437 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004438 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004439 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004440 Mnemonic == "mla" || Mnemonic == "smlal" ||
4441 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004442 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004443 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004444 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004445
Daniel Dunbar09264122011-01-11 19:06:29 +00004446 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4447 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4448 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4449 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004450 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4451 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004452 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004453 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4454 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4455 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004456 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4457 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004458 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004459 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004460 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004461 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004462
Jim Grosbach6c45b752011-09-16 16:39:25 +00004463 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004464 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004465 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004466 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004467 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004468}
4469
Jim Grosbach7283da92011-08-16 21:12:37 +00004470bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4471 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004472 // FIXME: This is all horribly hacky. We really need a better way to deal
4473 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004474
4475 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4476 // another does not. Specifically, the MOVW instruction does not. So we
4477 // special case it here and remove the defaulted (non-setting) cc_out
4478 // operand if that's the instruction we're trying to match.
4479 //
4480 // We do this as post-processing of the explicit operands rather than just
4481 // conditionally adding the cc_out in the first place because we need
4482 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004483 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004484 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4485 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4486 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4487 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004488
4489 // Register-register 'add' for thumb does not have a cc_out operand
4490 // when there are only two register operands.
4491 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4492 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4493 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4494 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4495 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004496 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004497 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4498 // have to check the immediate range here since Thumb2 has a variant
4499 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004500 if (((isThumb() && Mnemonic == "add") ||
4501 (isThumbTwo() && Mnemonic == "sub")) &&
4502 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004503 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4504 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4505 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004506 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4507 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4508 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004509 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004510 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4511 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004512 // selecting via the generic "add" mnemonic, so to know that we
4513 // should remove the cc_out operand, we have to explicitly check that
4514 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004515 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4516 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004517 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4518 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4519 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4520 // Nest conditions rather than one big 'if' statement for readability.
4521 //
4522 // If either register is a high reg, it's either one of the SP
4523 // variants (handled above) or a 32-bit encoding, so we just
4524 // check against T3.
4525 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4526 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4527 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4528 return false;
4529 // If both registers are low, we're in an IT block, and the immediate is
4530 // in range, we should use encoding T1 instead, which has a cc_out.
4531 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004532 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004533 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4534 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4535 return false;
4536
4537 // Otherwise, we use encoding T4, which does not have a cc_out
4538 // operand.
4539 return true;
4540 }
4541
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004542 // The thumb2 multiply instruction doesn't have a CCOut register, so
4543 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4544 // use the 16-bit encoding or not.
4545 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4546 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4547 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4548 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4549 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4550 // If the registers aren't low regs, the destination reg isn't the
4551 // same as one of the source regs, or the cc_out operand is zero
4552 // outside of an IT block, we have to use the 32-bit encoding, so
4553 // remove the cc_out operand.
4554 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4555 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004556 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004557 !inITBlock() ||
4558 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4559 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4560 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4561 static_cast<ARMOperand*>(Operands[4])->getReg())))
4562 return true;
4563
Jim Grosbachefa7e952011-11-15 19:55:16 +00004564 // Also check the 'mul' syntax variant that doesn't specify an explicit
4565 // destination register.
4566 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4567 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4568 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4569 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4570 // If the registers aren't low regs or the cc_out operand is zero
4571 // outside of an IT block, we have to use the 32-bit encoding, so
4572 // remove the cc_out operand.
4573 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4574 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4575 !inITBlock()))
4576 return true;
4577
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004578
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004579
Jim Grosbach4b701af2011-08-24 21:42:27 +00004580 // Register-register 'add/sub' for thumb does not have a cc_out operand
4581 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4582 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4583 // right, this will result in better diagnostics (which operand is off)
4584 // anyway.
4585 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4586 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004587 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4588 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4589 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4590 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004591
Jim Grosbach7283da92011-08-16 21:12:37 +00004592 return false;
4593}
4594
Jim Grosbach12952fe2011-11-11 23:08:10 +00004595static bool isDataTypeToken(StringRef Tok) {
4596 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4597 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4598 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4599 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4600 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4601 Tok == ".f" || Tok == ".d";
4602}
4603
4604// FIXME: This bit should probably be handled via an explicit match class
4605// in the .td files that matches the suffix instead of having it be
4606// a literal string token the way it is now.
4607static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4608 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4609}
4610
Jim Grosbach8be2f652011-12-09 23:34:09 +00004611static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004612/// Parse an arm instruction mnemonic followed by its operands.
4613bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4614 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004615 // Apply mnemonic aliases before doing anything else, as the destination
4616 // mnemnonic may include suffices and we want to handle them normally.
4617 // The generic tblgen'erated code does this later, at the start of
4618 // MatchInstructionImpl(), but that's too late for aliases that include
4619 // any sort of suffix.
4620 unsigned AvailableFeatures = getAvailableFeatures();
4621 applyMnemonicAliases(Name, AvailableFeatures);
4622
Jim Grosbachab5830e2011-12-14 02:16:11 +00004623 // First check for the ARM-specific .req directive.
4624 if (Parser.getTok().is(AsmToken::Identifier) &&
4625 Parser.getTok().getIdentifier() == ".req") {
4626 parseDirectiveReq(Name, NameLoc);
4627 // We always return 'error' for this, as we're done with this
4628 // statement and don't need to match the 'instruction."
4629 return true;
4630 }
4631
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004632 // Create the leading tokens for the mnemonic, split by '.' characters.
4633 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004634 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004635
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004636 // Split out the predication code and carry setting flag from the mnemonic.
4637 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004638 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004639 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004640 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004641 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004642 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004643
Jim Grosbach1c171b12011-08-25 17:23:55 +00004644 // In Thumb1, only the branch (B) instruction can be predicated.
4645 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4646 Parser.EatToEndOfStatement();
4647 return Error(NameLoc, "conditional execution not supported in Thumb1");
4648 }
4649
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004650 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4651
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004652 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4653 // is the mask as it will be for the IT encoding if the conditional
4654 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4655 // where the conditional bit0 is zero, the instruction post-processing
4656 // will adjust the mask accordingly.
4657 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004658 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4659 if (ITMask.size() > 3) {
4660 Parser.EatToEndOfStatement();
4661 return Error(Loc, "too many conditions on IT instruction");
4662 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004663 unsigned Mask = 8;
4664 for (unsigned i = ITMask.size(); i != 0; --i) {
4665 char pos = ITMask[i - 1];
4666 if (pos != 't' && pos != 'e') {
4667 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004668 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004669 }
4670 Mask >>= 1;
4671 if (ITMask[i - 1] == 't')
4672 Mask |= 8;
4673 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004674 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004675 }
4676
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004677 // FIXME: This is all a pretty gross hack. We should automatically handle
4678 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004679
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004680 // Next, add the CCOut and ConditionCode operands, if needed.
4681 //
4682 // For mnemonics which can ever incorporate a carry setting bit or predication
4683 // code, our matching model involves us always generating CCOut and
4684 // ConditionCode operands to match the mnemonic "as written" and then we let
4685 // the matcher deal with finding the right instruction or generating an
4686 // appropriate error.
4687 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004688 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004689
Jim Grosbach03a8a162011-07-14 22:04:21 +00004690 // If we had a carry-set on an instruction that can't do that, issue an
4691 // error.
4692 if (!CanAcceptCarrySet && CarrySetting) {
4693 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004694 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004695 "' can not set flags, but 's' suffix specified");
4696 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004697 // If we had a predication code on an instruction that can't do that, issue an
4698 // error.
4699 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4700 Parser.EatToEndOfStatement();
4701 return Error(NameLoc, "instruction '" + Mnemonic +
4702 "' is not predicable, but condition code specified");
4703 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004704
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004705 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004706 if (CanAcceptCarrySet) {
4707 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004708 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004709 Loc));
4710 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004711
4712 // Add the predication code operand, if necessary.
4713 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004714 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4715 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004716 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004717 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004718 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004719
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004720 // Add the processor imod operand, if necessary.
4721 if (ProcessorIMod) {
4722 Operands.push_back(ARMOperand::CreateImm(
4723 MCConstantExpr::Create(ProcessorIMod, getContext()),
4724 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004725 }
4726
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004727 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004728 while (Next != StringRef::npos) {
4729 Start = Next;
4730 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004731 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004732
Jim Grosbach12952fe2011-11-11 23:08:10 +00004733 // Some NEON instructions have an optional datatype suffix that is
4734 // completely ignored. Check for that.
4735 if (isDataTypeToken(ExtraToken) &&
4736 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4737 continue;
4738
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004739 if (ExtraToken != ".n") {
4740 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4741 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4742 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004743 }
4744
4745 // Read the remaining operands.
4746 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004747 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004748 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004749 Parser.EatToEndOfStatement();
4750 return true;
4751 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004752
4753 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004754 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004755
4756 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004757 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004758 Parser.EatToEndOfStatement();
4759 return true;
4760 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004761 }
4762 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004763
Chris Lattnera2a9d162010-09-11 16:18:25 +00004764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004765 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004766 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004767 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004768 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004769
Chris Lattner91689c12010-09-08 05:10:46 +00004770 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004771
Jim Grosbach7283da92011-08-16 21:12:37 +00004772 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4773 // do and don't have a cc_out optional-def operand. With some spot-checks
4774 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004775 // parse and adjust accordingly before actually matching. We shouldn't ever
4776 // try to remove a cc_out operand that was explicitly set on the the
4777 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4778 // table driven matcher doesn't fit well with the ARM instruction set.
4779 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004780 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4781 Operands.erase(Operands.begin() + 1);
4782 delete Op;
4783 }
4784
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004785 // ARM mode 'blx' need special handling, as the register operand version
4786 // is predicable, but the label operand version is not. So, we can't rely
4787 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004788 // a k_CondCode operand in the list. If we're trying to match the label
4789 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004790 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4791 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4792 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4793 Operands.erase(Operands.begin() + 1);
4794 delete Op;
4795 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004796
4797 // The vector-compare-to-zero instructions have a literal token "#0" at
4798 // the end that comes to here as an immediate operand. Convert it to a
4799 // token to play nicely with the matcher.
4800 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4801 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4802 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4803 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4804 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4805 if (CE && CE->getValue() == 0) {
4806 Operands.erase(Operands.begin() + 5);
4807 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4808 delete Op;
4809 }
4810 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004811 // VCMP{E} does the same thing, but with a different operand count.
4812 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4813 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4814 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4815 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4816 if (CE && CE->getValue() == 0) {
4817 Operands.erase(Operands.begin() + 4);
4818 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4819 delete Op;
4820 }
4821 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004822 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004823 // end. Convert it to a token here. Take care not to convert those
4824 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004825 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004826 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4827 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004828 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4829 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4830 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004831 if (CE && CE->getValue() == 0 &&
4832 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00004833 // The cc_out operand matches the IT block.
4834 ((inITBlock() != CarrySetting) &&
4835 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004836 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00004837 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004838 Operands.erase(Operands.begin() + 5);
4839 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4840 delete Op;
4841 }
4842 }
4843
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004844 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004845}
4846
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004847// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004848
4849// return 'true' if register list contains non-low GPR registers,
4850// 'false' otherwise. If Reg is in the register list or is HiReg, set
4851// 'containsReg' to true.
4852static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4853 unsigned HiReg, bool &containsReg) {
4854 containsReg = false;
4855 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4856 unsigned OpReg = Inst.getOperand(i).getReg();
4857 if (OpReg == Reg)
4858 containsReg = true;
4859 // Anything other than a low register isn't legal here.
4860 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4861 return true;
4862 }
4863 return false;
4864}
4865
Jim Grosbacha31f2232011-09-07 18:05:34 +00004866// Check if the specified regisgter is in the register list of the inst,
4867// starting at the indicated operand number.
4868static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4869 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4870 unsigned OpReg = Inst.getOperand(i).getReg();
4871 if (OpReg == Reg)
4872 return true;
4873 }
4874 return false;
4875}
4876
Jim Grosbached16ec42011-08-29 22:24:09 +00004877// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4878// the ARMInsts array) instead. Getting that here requires awkward
4879// API changes, though. Better way?
4880namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004881extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004882}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004883static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004884 return ARMInsts[Opcode];
4885}
4886
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004887// FIXME: We would really like to be able to tablegen'erate this.
4888bool ARMAsmParser::
4889validateInstruction(MCInst &Inst,
4890 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004891 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004892 SMLoc Loc = Operands[0]->getStartLoc();
4893 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004894 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4895 // being allowed in IT blocks, but not being predicable. It just always
4896 // executes.
4897 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004898 unsigned bit = 1;
4899 if (ITState.FirstCond)
4900 ITState.FirstCond = false;
4901 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004902 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004903 // The instruction must be predicable.
4904 if (!MCID.isPredicable())
4905 return Error(Loc, "instructions in IT block must be predicable");
4906 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4907 unsigned ITCond = bit ? ITState.Cond :
4908 ARMCC::getOppositeCondition(ITState.Cond);
4909 if (Cond != ITCond) {
4910 // Find the condition code Operand to get its SMLoc information.
4911 SMLoc CondLoc;
4912 for (unsigned i = 1; i < Operands.size(); ++i)
4913 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4914 CondLoc = Operands[i]->getStartLoc();
4915 return Error(CondLoc, "incorrect condition in IT block; got '" +
4916 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4917 "', but expected '" +
4918 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4919 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004920 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004921 } else if (isThumbTwo() && MCID.isPredicable() &&
4922 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004923 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4924 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004925 return Error(Loc, "predicated instructions must be in IT block");
4926
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004927 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004928 case ARM::LDRD:
4929 case ARM::LDRD_PRE:
4930 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004931 case ARM::LDREXD: {
4932 // Rt2 must be Rt + 1.
4933 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4934 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4935 if (Rt2 != Rt + 1)
4936 return Error(Operands[3]->getStartLoc(),
4937 "destination operands must be sequential");
4938 return false;
4939 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004940 case ARM::STRD: {
4941 // Rt2 must be Rt + 1.
4942 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4943 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4944 if (Rt2 != Rt + 1)
4945 return Error(Operands[3]->getStartLoc(),
4946 "source operands must be sequential");
4947 return false;
4948 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004949 case ARM::STRD_PRE:
4950 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004951 case ARM::STREXD: {
4952 // Rt2 must be Rt + 1.
4953 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4954 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4955 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004956 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004957 "source operands must be sequential");
4958 return false;
4959 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004960 case ARM::SBFX:
4961 case ARM::UBFX: {
4962 // width must be in range [1, 32-lsb]
4963 unsigned lsb = Inst.getOperand(2).getImm();
4964 unsigned widthm1 = Inst.getOperand(3).getImm();
4965 if (widthm1 >= 32 - lsb)
4966 return Error(Operands[5]->getStartLoc(),
4967 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004968 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004969 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004970 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004971 // If we're parsing Thumb2, the .w variant is available and handles
4972 // most cases that are normally illegal for a Thumb1 LDM
4973 // instruction. We'll make the transformation in processInstruction()
4974 // if necessary.
4975 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004976 // Thumb LDM instructions are writeback iff the base register is not
4977 // in the register list.
4978 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004979 bool hasWritebackToken =
4980 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4981 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004982 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004983 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004984 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4985 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004986 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004987 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004988 return Error(Operands[2]->getStartLoc(),
4989 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004990 // If we should not have writeback, there must not be a '!'. This is
4991 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004992 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004993 return Error(Operands[3]->getStartLoc(),
4994 "writeback operator '!' not allowed when base register "
4995 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004996
4997 break;
4998 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004999 case ARM::t2LDMIA_UPD: {
5000 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5001 return Error(Operands[4]->getStartLoc(),
5002 "writeback operator '!' not allowed when base register "
5003 "in register list");
5004 break;
5005 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005006 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5007 // so only issue a diagnostic for thumb1. The instructions will be
5008 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005009 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005010 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005011 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5012 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005013 return Error(Operands[2]->getStartLoc(),
5014 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005015 break;
5016 }
5017 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00005018 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005019 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5020 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00005021 return Error(Operands[2]->getStartLoc(),
5022 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00005023 break;
5024 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00005025 case ARM::tSTMIA_UPD: {
5026 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00005027 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00005028 return Error(Operands[4]->getStartLoc(),
5029 "registers must be in range r0-r7");
5030 break;
5031 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005032 }
5033
5034 return false;
5035}
5036
Jim Grosbacheb538222011-12-02 22:34:51 +00005037static unsigned getRealVSTLNOpcode(unsigned Opc) {
5038 switch(Opc) {
5039 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005040 // VST1LN
5041 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5042 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5043 case ARM::VST1LNdWB_fixed_Asm_U8:
5044 return ARM::VST1LNd8_UPD;
5045 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5046 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5047 case ARM::VST1LNdWB_fixed_Asm_U16:
5048 return ARM::VST1LNd16_UPD;
5049 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5050 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5051 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
5052 return ARM::VST1LNd32_UPD;
5053 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5054 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5055 case ARM::VST1LNdWB_register_Asm_U8:
5056 return ARM::VST1LNd8_UPD;
5057 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5058 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5059 case ARM::VST1LNdWB_register_Asm_U16:
5060 return ARM::VST1LNd16_UPD;
5061 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5062 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5063 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
5064 return ARM::VST1LNd32_UPD;
5065 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5066 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5067 case ARM::VST1LNdAsm_U8:
5068 return ARM::VST1LNd8;
5069 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5070 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5071 case ARM::VST1LNdAsm_U16:
5072 return ARM::VST1LNd16;
5073 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5074 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5075 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
5076 return ARM::VST1LNd32;
5077
5078 // VST2LN
5079 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5080 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5081 case ARM::VST2LNdWB_fixed_Asm_U8:
5082 return ARM::VST2LNd8_UPD;
5083 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5084 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5085 case ARM::VST2LNdWB_fixed_Asm_U16:
5086 return ARM::VST2LNd16_UPD;
5087 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5088 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5089 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5090 return ARM::VST2LNd32_UPD;
5091 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5092 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5093 case ARM::VST2LNdWB_register_Asm_U8:
5094 return ARM::VST2LNd8_UPD;
5095 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5096 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5097 case ARM::VST2LNdWB_register_Asm_U16:
5098 return ARM::VST2LNd16_UPD;
5099 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5100 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5101 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5102 return ARM::VST2LNd32_UPD;
5103 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5104 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5105 case ARM::VST2LNdAsm_U8:
5106 return ARM::VST2LNd8;
5107 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5108 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5109 case ARM::VST2LNdAsm_U16:
5110 return ARM::VST2LNd16;
5111 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5112 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5113 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
5114 return ARM::VST2LNd32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005115 }
5116}
5117
5118static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005119 switch(Opc) {
5120 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005121 // VLD1LN
5122 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5123 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5124 case ARM::VLD1LNdWB_fixed_Asm_U8:
5125 return ARM::VLD1LNd8_UPD;
5126 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5127 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5128 case ARM::VLD1LNdWB_fixed_Asm_U16:
5129 return ARM::VLD1LNd16_UPD;
5130 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5131 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5132 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
5133 return ARM::VLD1LNd32_UPD;
5134 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5135 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5136 case ARM::VLD1LNdWB_register_Asm_U8:
5137 return ARM::VLD1LNd8_UPD;
5138 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5139 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5140 case ARM::VLD1LNdWB_register_Asm_U16:
5141 return ARM::VLD1LNd16_UPD;
5142 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5143 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5144 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
5145 return ARM::VLD1LNd32_UPD;
5146 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5147 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5148 case ARM::VLD1LNdAsm_U8:
5149 return ARM::VLD1LNd8;
5150 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5151 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5152 case ARM::VLD1LNdAsm_U16:
5153 return ARM::VLD1LNd16;
5154 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5155 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5156 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
5157 return ARM::VLD1LNd32;
5158
5159 // VLD2LN
5160 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5161 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5162 case ARM::VLD2LNdWB_fixed_Asm_U8:
5163 return ARM::VLD2LNd8_UPD;
5164 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5165 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5166 case ARM::VLD2LNdWB_fixed_Asm_U16:
5167 return ARM::VLD2LNd16_UPD;
5168 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5169 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5170 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
5171 return ARM::VLD2LNd32_UPD;
5172 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5173 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5174 case ARM::VLD2LNdWB_register_Asm_U8:
5175 return ARM::VLD2LNd8_UPD;
5176 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5177 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5178 case ARM::VLD2LNdWB_register_Asm_U16:
5179 return ARM::VLD2LNd16_UPD;
5180 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5181 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5182 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
5183 return ARM::VLD2LNd32_UPD;
5184 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5185 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5186 case ARM::VLD2LNdAsm_U8:
5187 return ARM::VLD2LNd8;
5188 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5189 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5190 case ARM::VLD2LNdAsm_U16:
5191 return ARM::VLD2LNd16;
5192 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5193 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5194 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
5195 return ARM::VLD2LNd32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005196 }
5197}
5198
Jim Grosbachafad0532011-11-10 23:42:14 +00005199bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005200processInstruction(MCInst &Inst,
5201 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5202 switch (Inst.getOpcode()) {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005203 // Handle NEON VST complex aliases.
5204 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5205 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5206 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5207 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5208 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5209 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5210 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5211 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005212 MCInst TmpInst;
5213 // Shuffle the operands around so the lane index operand is in the
5214 // right place.
5215 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5216 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5217 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5218 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5219 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5220 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5221 TmpInst.addOperand(Inst.getOperand(1)); // lane
5222 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5223 TmpInst.addOperand(Inst.getOperand(6));
5224 Inst = TmpInst;
5225 return true;
5226 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005227
5228 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5229 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5230 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
5231 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5232 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
5233 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5234 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5235 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32: {
5236 MCInst TmpInst;
5237 // Shuffle the operands around so the lane index operand is in the
5238 // right place.
5239 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5240 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5241 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5242 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5243 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5244 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5245 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5246 TmpInst.addOperand(Inst.getOperand(1)); // lane
5247 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5248 TmpInst.addOperand(Inst.getOperand(6));
5249 Inst = TmpInst;
5250 return true;
5251 }
5252 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5253 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5254 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5255 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5256 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5257 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5258 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5259 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005260 MCInst TmpInst;
5261 // Shuffle the operands around so the lane index operand is in the
5262 // right place.
5263 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5264 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5265 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5266 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5267 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5268 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5269 TmpInst.addOperand(Inst.getOperand(1)); // lane
5270 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5271 TmpInst.addOperand(Inst.getOperand(5));
5272 Inst = TmpInst;
5273 return true;
5274 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005275
5276 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5277 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5278 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
5279 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5280 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
5281 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5282 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5283 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32: {
5284 MCInst TmpInst;
5285 // Shuffle the operands around so the lane index operand is in the
5286 // right place.
5287 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5288 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5289 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5290 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5291 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5292 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5293 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5294 TmpInst.addOperand(Inst.getOperand(1)); // lane
5295 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5296 TmpInst.addOperand(Inst.getOperand(5));
5297 Inst = TmpInst;
5298 return true;
5299 }
5300 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5301 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5302 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5303 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5304 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbacheb538222011-12-02 22:34:51 +00005305 case ARM::VST1LNdAsm_U32: {
5306 MCInst TmpInst;
5307 // Shuffle the operands around so the lane index operand is in the
5308 // right place.
5309 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5310 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5311 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5312 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5313 TmpInst.addOperand(Inst.getOperand(1)); // lane
5314 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5315 TmpInst.addOperand(Inst.getOperand(5));
5316 Inst = TmpInst;
5317 return true;
5318 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005319
5320 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5321 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
5322 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5323 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5324 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
5325 case ARM::VST2LNdAsm_U32: {
5326 MCInst TmpInst;
5327 // Shuffle the operands around so the lane index operand is in the
5328 // right place.
5329 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5330 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5331 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5332 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5333 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5334 TmpInst.addOperand(Inst.getOperand(1)); // lane
5335 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5336 TmpInst.addOperand(Inst.getOperand(5));
5337 Inst = TmpInst;
5338 return true;
5339 }
5340 // Handle NEON VLD complex aliases.
5341 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5342 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5343 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5344 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5345 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5346 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5347 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5348 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005349 MCInst TmpInst;
5350 // Shuffle the operands around so the lane index operand is in the
5351 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005352 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005353 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5354 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5355 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5356 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5357 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5358 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5359 TmpInst.addOperand(Inst.getOperand(1)); // lane
5360 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5361 TmpInst.addOperand(Inst.getOperand(6));
5362 Inst = TmpInst;
5363 return true;
5364 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005365
5366 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5367 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5368 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
5369 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5370 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
5371 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5372 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5373 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32: {
5374 MCInst TmpInst;
5375 // Shuffle the operands around so the lane index operand is in the
5376 // right place.
5377 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5378 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5379 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5380 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5381 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5382 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5383 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5384 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5385 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5386 TmpInst.addOperand(Inst.getOperand(1)); // lane
5387 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5388 TmpInst.addOperand(Inst.getOperand(6));
5389 Inst = TmpInst;
5390 return true;
5391 }
5392
5393 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5394 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5395 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5396 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5397 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5398 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5399 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5400 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005401 MCInst TmpInst;
5402 // Shuffle the operands around so the lane index operand is in the
5403 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005404 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005405 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5406 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5407 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5408 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5409 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5410 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5411 TmpInst.addOperand(Inst.getOperand(1)); // lane
5412 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5413 TmpInst.addOperand(Inst.getOperand(5));
5414 Inst = TmpInst;
5415 return true;
5416 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005417
5418 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5419 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5420 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
5421 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5422 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
5423 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5424 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5425 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32: {
5426 MCInst TmpInst;
5427 // Shuffle the operands around so the lane index operand is in the
5428 // right place.
5429 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5430 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5431 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5432 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5433 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5434 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5435 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5436 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5437 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5438 TmpInst.addOperand(Inst.getOperand(1)); // lane
5439 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5440 TmpInst.addOperand(Inst.getOperand(5));
5441 Inst = TmpInst;
5442 return true;
5443 }
5444
5445 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5446 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
5447 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5448 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5449 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005450 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005451 MCInst TmpInst;
5452 // Shuffle the operands around so the lane index operand is in the
5453 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005454 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach04945c42011-12-02 00:35:16 +00005455 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5456 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5457 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5458 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5459 TmpInst.addOperand(Inst.getOperand(1)); // lane
5460 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5461 TmpInst.addOperand(Inst.getOperand(5));
5462 Inst = TmpInst;
5463 return true;
5464 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005465
5466 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5467 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
5468 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5469 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5470 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
5471 case ARM::VLD2LNdAsm_U32: {
5472 MCInst TmpInst;
5473 // Shuffle the operands around so the lane index operand is in the
5474 // right place.
5475 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5476 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5477 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5478 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5479 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5480 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5481 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5482 TmpInst.addOperand(Inst.getOperand(1)); // lane
5483 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5484 TmpInst.addOperand(Inst.getOperand(5));
5485 Inst = TmpInst;
5486 return true;
5487 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005488 // Handle the Thumb2 mode MOV complex aliases.
5489 case ARM::t2MOVsi:
5490 case ARM::t2MOVSsi: {
5491 // Which instruction to expand to depends on the CCOut operand and
5492 // whether we're in an IT block if the register operands are low
5493 // registers.
5494 bool isNarrow = false;
5495 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5496 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5497 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5498 isNarrow = true;
5499 MCInst TmpInst;
5500 unsigned newOpc;
5501 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5502 default: llvm_unreachable("unexpected opcode!");
5503 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5504 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5505 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5506 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5507 }
5508 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5509 if (Ammount == 32) Ammount = 0;
5510 TmpInst.setOpcode(newOpc);
5511 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5512 if (isNarrow)
5513 TmpInst.addOperand(MCOperand::CreateReg(
5514 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5515 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5516 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5517 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5518 TmpInst.addOperand(Inst.getOperand(4));
5519 if (!isNarrow)
5520 TmpInst.addOperand(MCOperand::CreateReg(
5521 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5522 Inst = TmpInst;
5523 return true;
5524 }
5525 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005526 case ARM::ASRr:
5527 case ARM::LSRr:
5528 case ARM::LSLr:
5529 case ARM::RORr: {
5530 ARM_AM::ShiftOpc ShiftTy;
5531 switch(Inst.getOpcode()) {
5532 default: llvm_unreachable("unexpected opcode!");
5533 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5534 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5535 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5536 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5537 }
5538 // A shift by zero is a plain MOVr, not a MOVsi.
5539 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5540 MCInst TmpInst;
5541 TmpInst.setOpcode(ARM::MOVsr);
5542 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5543 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5544 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5545 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5546 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5547 TmpInst.addOperand(Inst.getOperand(4));
5548 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5549 Inst = TmpInst;
5550 return true;
5551 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005552 case ARM::ASRi:
5553 case ARM::LSRi:
5554 case ARM::LSLi:
5555 case ARM::RORi: {
5556 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005557 switch(Inst.getOpcode()) {
5558 default: llvm_unreachable("unexpected opcode!");
5559 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5560 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5561 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5562 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5563 }
5564 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005565 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005566 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5567 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005568 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005569 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005570 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5571 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005572 if (Opc == ARM::MOVsi)
5573 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005574 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5575 TmpInst.addOperand(Inst.getOperand(4));
5576 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5577 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005578 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005579 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005580 case ARM::RRXi: {
5581 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5582 MCInst TmpInst;
5583 TmpInst.setOpcode(ARM::MOVsi);
5584 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5585 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5586 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5587 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5588 TmpInst.addOperand(Inst.getOperand(3));
5589 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5590 Inst = TmpInst;
5591 return true;
5592 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005593 case ARM::t2LDMIA_UPD: {
5594 // If this is a load of a single register, then we should use
5595 // a post-indexed LDR instruction instead, per the ARM ARM.
5596 if (Inst.getNumOperands() != 5)
5597 return false;
5598 MCInst TmpInst;
5599 TmpInst.setOpcode(ARM::t2LDR_POST);
5600 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5601 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5602 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5603 TmpInst.addOperand(MCOperand::CreateImm(4));
5604 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5605 TmpInst.addOperand(Inst.getOperand(3));
5606 Inst = TmpInst;
5607 return true;
5608 }
5609 case ARM::t2STMDB_UPD: {
5610 // If this is a store of a single register, then we should use
5611 // a pre-indexed STR instruction instead, per the ARM ARM.
5612 if (Inst.getNumOperands() != 5)
5613 return false;
5614 MCInst TmpInst;
5615 TmpInst.setOpcode(ARM::t2STR_PRE);
5616 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5617 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5618 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5619 TmpInst.addOperand(MCOperand::CreateImm(-4));
5620 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5621 TmpInst.addOperand(Inst.getOperand(3));
5622 Inst = TmpInst;
5623 return true;
5624 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005625 case ARM::LDMIA_UPD:
5626 // If this is a load of a single register via a 'pop', then we should use
5627 // a post-indexed LDR instruction instead, per the ARM ARM.
5628 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5629 Inst.getNumOperands() == 5) {
5630 MCInst TmpInst;
5631 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5632 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5633 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5634 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5635 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5636 TmpInst.addOperand(MCOperand::CreateImm(4));
5637 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5638 TmpInst.addOperand(Inst.getOperand(3));
5639 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005640 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005641 }
5642 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005643 case ARM::STMDB_UPD:
5644 // If this is a store of a single register via a 'push', then we should use
5645 // a pre-indexed STR instruction instead, per the ARM ARM.
5646 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5647 Inst.getNumOperands() == 5) {
5648 MCInst TmpInst;
5649 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5650 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5651 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5652 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5653 TmpInst.addOperand(MCOperand::CreateImm(-4));
5654 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5655 TmpInst.addOperand(Inst.getOperand(3));
5656 Inst = TmpInst;
5657 }
5658 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005659 case ARM::t2ADDri12:
5660 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5661 // mnemonic was used (not "addw"), encoding T3 is preferred.
5662 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5663 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5664 break;
5665 Inst.setOpcode(ARM::t2ADDri);
5666 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5667 break;
5668 case ARM::t2SUBri12:
5669 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5670 // mnemonic was used (not "subw"), encoding T3 is preferred.
5671 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5672 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5673 break;
5674 Inst.setOpcode(ARM::t2SUBri);
5675 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5676 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005677 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005678 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5679 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5680 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5681 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005682 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005683 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005684 return true;
5685 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005686 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005687 case ARM::tSUBi8:
5688 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5689 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5690 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5691 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005692 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005693 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005694 return true;
5695 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005696 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00005697 case ARM::t2ADDrr: {
5698 // If the destination and first source operand are the same, and
5699 // there's no setting of the flags, use encoding T2 instead of T3.
5700 // Note that this is only for ADD, not SUB. This mirrors the system
5701 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5702 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5703 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00005704 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5705 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00005706 break;
5707 MCInst TmpInst;
5708 TmpInst.setOpcode(ARM::tADDhirr);
5709 TmpInst.addOperand(Inst.getOperand(0));
5710 TmpInst.addOperand(Inst.getOperand(0));
5711 TmpInst.addOperand(Inst.getOperand(2));
5712 TmpInst.addOperand(Inst.getOperand(3));
5713 TmpInst.addOperand(Inst.getOperand(4));
5714 Inst = TmpInst;
5715 return true;
5716 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005717 case ARM::tB:
5718 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005719 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005720 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005721 return true;
5722 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005723 break;
5724 case ARM::t2B:
5725 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005726 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005727 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005728 return true;
5729 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005730 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00005731 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005732 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00005733 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00005734 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00005735 return true;
5736 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00005737 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005738 case ARM::tBcc:
5739 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00005740 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005741 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00005742 return true;
5743 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00005744 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005745 case ARM::tLDMIA: {
5746 // If the register list contains any high registers, or if the writeback
5747 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5748 // instead if we're in Thumb2. Otherwise, this should have generated
5749 // an error in validateInstruction().
5750 unsigned Rn = Inst.getOperand(0).getReg();
5751 bool hasWritebackToken =
5752 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5753 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5754 bool listContainsBase;
5755 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5756 (!listContainsBase && !hasWritebackToken) ||
5757 (listContainsBase && hasWritebackToken)) {
5758 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5759 assert (isThumbTwo());
5760 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5761 // If we're switching to the updating version, we need to insert
5762 // the writeback tied operand.
5763 if (hasWritebackToken)
5764 Inst.insert(Inst.begin(),
5765 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00005766 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005767 }
5768 break;
5769 }
Jim Grosbach099c9762011-09-16 20:50:13 +00005770 case ARM::tSTMIA_UPD: {
5771 // If the register list contains any high registers, we need to use
5772 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5773 // should have generated an error in validateInstruction().
5774 unsigned Rn = Inst.getOperand(0).getReg();
5775 bool listContainsBase;
5776 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5777 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5778 assert (isThumbTwo());
5779 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00005780 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00005781 }
5782 break;
5783 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005784 case ARM::tPOP: {
5785 bool listContainsBase;
5786 // If the register list contains any high registers, we need to use
5787 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5788 // should have generated an error in validateInstruction().
5789 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005790 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005791 assert (isThumbTwo());
5792 Inst.setOpcode(ARM::t2LDMIA_UPD);
5793 // Add the base register and writeback operands.
5794 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5795 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005796 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005797 }
5798 case ARM::tPUSH: {
5799 bool listContainsBase;
5800 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005801 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005802 assert (isThumbTwo());
5803 Inst.setOpcode(ARM::t2STMDB_UPD);
5804 // Add the base register and writeback operands.
5805 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5806 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005807 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005808 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005809 case ARM::t2MOVi: {
5810 // If we can use the 16-bit encoding and the user didn't explicitly
5811 // request the 32-bit variant, transform it here.
5812 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5813 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00005814 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5815 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5816 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005817 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5818 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5819 // The operands aren't in the same order for tMOVi8...
5820 MCInst TmpInst;
5821 TmpInst.setOpcode(ARM::tMOVi8);
5822 TmpInst.addOperand(Inst.getOperand(0));
5823 TmpInst.addOperand(Inst.getOperand(4));
5824 TmpInst.addOperand(Inst.getOperand(1));
5825 TmpInst.addOperand(Inst.getOperand(2));
5826 TmpInst.addOperand(Inst.getOperand(3));
5827 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005828 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005829 }
5830 break;
5831 }
5832 case ARM::t2MOVr: {
5833 // If we can use the 16-bit encoding and the user didn't explicitly
5834 // request the 32-bit variant, transform it here.
5835 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5836 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5837 Inst.getOperand(2).getImm() == ARMCC::AL &&
5838 Inst.getOperand(4).getReg() == ARM::CPSR &&
5839 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5840 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5841 // The operands aren't the same for tMOV[S]r... (no cc_out)
5842 MCInst TmpInst;
5843 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5844 TmpInst.addOperand(Inst.getOperand(0));
5845 TmpInst.addOperand(Inst.getOperand(1));
5846 TmpInst.addOperand(Inst.getOperand(2));
5847 TmpInst.addOperand(Inst.getOperand(3));
5848 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005849 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005850 }
5851 break;
5852 }
Jim Grosbach82213192011-09-19 20:29:33 +00005853 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00005854 case ARM::t2SXTB:
5855 case ARM::t2UXTH:
5856 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00005857 // If we can use the 16-bit encoding and the user didn't explicitly
5858 // request the 32-bit variant, transform it here.
5859 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5860 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5861 Inst.getOperand(2).getImm() == 0 &&
5862 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5863 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00005864 unsigned NewOpc;
5865 switch (Inst.getOpcode()) {
5866 default: llvm_unreachable("Illegal opcode!");
5867 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5868 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5869 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5870 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5871 }
Jim Grosbach82213192011-09-19 20:29:33 +00005872 // The operands aren't the same for thumb1 (no rotate operand).
5873 MCInst TmpInst;
5874 TmpInst.setOpcode(NewOpc);
5875 TmpInst.addOperand(Inst.getOperand(0));
5876 TmpInst.addOperand(Inst.getOperand(1));
5877 TmpInst.addOperand(Inst.getOperand(3));
5878 TmpInst.addOperand(Inst.getOperand(4));
5879 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005880 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00005881 }
5882 break;
5883 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005884 case ARM::t2IT: {
5885 // The mask bits for all but the first condition are represented as
5886 // the low bit of the condition code value implies 't'. We currently
5887 // always have 1 implies 't', so XOR toggle the bits if the low bit
5888 // of the condition code is zero. The encoding also expects the low
5889 // bit of the condition to be encoded as bit 4 of the mask operand,
5890 // so mask that in if needed
5891 MCOperand &MO = Inst.getOperand(1);
5892 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00005893 unsigned OrigMask = Mask;
5894 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005895 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005896 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5897 for (unsigned i = 3; i != TZ; --i)
5898 Mask ^= 1 << i;
5899 } else
5900 Mask |= 0x10;
5901 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00005902
5903 // Set up the IT block state according to the IT instruction we just
5904 // matched.
5905 assert(!inITBlock() && "nested IT blocks?!");
5906 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5907 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5908 ITState.CurPosition = 0;
5909 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005910 break;
5911 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005912 }
Jim Grosbachafad0532011-11-10 23:42:14 +00005913 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005914}
5915
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005916unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5917 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5918 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005919 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005920 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005921 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5922 assert(MCID.hasOptionalDef() &&
5923 "optionally flag setting instruction missing optional def operand");
5924 assert(MCID.NumOperands == Inst.getNumOperands() &&
5925 "operand count mismatch!");
5926 // Find the optional-def operand (cc_out).
5927 unsigned OpNo;
5928 for (OpNo = 0;
5929 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5930 ++OpNo)
5931 ;
5932 // If we're parsing Thumb1, reject it completely.
5933 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5934 return Match_MnemonicFail;
5935 // If we're parsing Thumb2, which form is legal depends on whether we're
5936 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005937 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5938 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005939 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00005940 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5941 inITBlock())
5942 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005943 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005944 // Some high-register supporting Thumb1 encodings only allow both registers
5945 // to be from r0-r7 when in Thumb2.
5946 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5947 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5948 isARMLowRegister(Inst.getOperand(2).getReg()))
5949 return Match_RequiresThumb2;
5950 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00005951 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005952 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5953 isARMLowRegister(Inst.getOperand(1).getReg()))
5954 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005955 return Match_Success;
5956}
5957
Chris Lattner9487de62010-10-28 21:28:01 +00005958bool ARMAsmParser::
5959MatchAndEmitInstruction(SMLoc IDLoc,
5960 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5961 MCStreamer &Out) {
5962 MCInst Inst;
5963 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00005964 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00005965 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00005966 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00005967 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005968 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005969 // Context sensitive operand constraints aren't handled by the matcher,
5970 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005971 if (validateInstruction(Inst, Operands)) {
5972 // Still progress the IT block, otherwise one wrong condition causes
5973 // nasty cascading errors.
5974 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005975 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005976 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005977
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005978 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00005979 // encoding is selected. Loop on it while changes happen so the
5980 // individual transformations can chain off each other. E.g.,
5981 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5982 while (processInstruction(Inst, Operands))
5983 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005984
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005985 // Only move forward at the very end so that everything in validate
5986 // and process gets a consistent answer about whether we're in an IT
5987 // block.
5988 forwardITPosition();
5989
Chris Lattner9487de62010-10-28 21:28:01 +00005990 Out.EmitInstruction(Inst);
5991 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005992 case Match_MissingFeature:
5993 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5994 return true;
5995 case Match_InvalidOperand: {
5996 SMLoc ErrorLoc = IDLoc;
5997 if (ErrorInfo != ~0U) {
5998 if (ErrorInfo >= Operands.size())
5999 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00006000
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006001 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6002 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6003 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006004
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006005 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00006006 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006007 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006008 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00006009 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00006010 // The converter function will have already emited a diagnostic.
6011 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00006012 case Match_RequiresNotITBlock:
6013 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00006014 case Match_RequiresITBlock:
6015 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00006016 case Match_RequiresV6:
6017 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6018 case Match_RequiresThumb2:
6019 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00006020 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00006021
Eric Christopher91d7b902010-10-29 09:26:59 +00006022 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00006023 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00006024}
6025
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006026/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00006027bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6028 StringRef IDVal = DirectiveID.getIdentifier();
6029 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006030 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006031 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006032 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00006033 else if (IDVal == ".arm")
6034 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006035 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006036 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006037 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006038 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006039 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006040 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00006041 else if (IDVal == ".unreq")
6042 return parseDirectiveUnreq(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00006043 return true;
6044}
6045
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006046/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00006047/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006048bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00006049 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6050 for (;;) {
6051 const MCExpr *Value;
6052 if (getParser().ParseExpression(Value))
6053 return true;
6054
Chris Lattnerc35681b2010-01-19 19:46:13 +00006055 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00006056
6057 if (getLexer().is(AsmToken::EndOfStatement))
6058 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00006059
Kevin Enderbyccab3172009-09-15 00:27:25 +00006060 // FIXME: Improve diagnostic.
6061 if (getLexer().isNot(AsmToken::Comma))
6062 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006063 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006064 }
6065 }
6066
Sean Callanana83fd7d2010-01-19 20:27:46 +00006067 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006068 return false;
6069}
6070
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006071/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00006072/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006073bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00006074 if (getLexer().isNot(AsmToken::EndOfStatement))
6075 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006076 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006077
Jim Grosbach7f882392011-12-07 18:04:19 +00006078 if (!isThumb())
6079 SwitchMode();
6080 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6081 return false;
6082}
6083
6084/// parseDirectiveARM
6085/// ::= .arm
6086bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6087 if (getLexer().isNot(AsmToken::EndOfStatement))
6088 return Error(L, "unexpected token in directive");
6089 Parser.Lex();
6090
6091 if (isThumb())
6092 SwitchMode();
6093 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006094 return false;
6095}
6096
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006097/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00006098/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006099bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006100 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6101 bool isMachO = MAI.hasSubsectionsViaSymbols();
6102 StringRef Name;
6103
6104 // Darwin asm has function name after .thumb_func direction
6105 // ELF doesn't
6106 if (isMachO) {
6107 const AsmToken &Tok = Parser.getTok();
6108 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6109 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00006110 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006111 Parser.Lex(); // Consume the identifier token.
6112 }
6113
Jim Grosbach42ba6282011-11-10 20:48:53 +00006114 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00006115 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006116 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006117
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006118 // FIXME: assuming function name will be the line following .thumb_func
6119 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00006120 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006121 }
6122
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00006123 // Mark symbol as a thumb symbol.
6124 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6125 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006126 return false;
6127}
6128
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006129/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00006130/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006131bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006132 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006133 if (Tok.isNot(AsmToken::Identifier))
6134 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00006135 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00006136 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00006137 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006138 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00006139 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00006140 else
6141 return Error(L, "unrecognized syntax mode in .syntax directive");
6142
6143 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006144 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006145 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006146
6147 // TODO tell the MC streamer the mode
6148 // getParser().getStreamer().Emit???();
6149 return false;
6150}
6151
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006152/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00006153/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006154bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006155 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006156 if (Tok.isNot(AsmToken::Integer))
6157 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00006158 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00006159 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006160 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006161 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006162 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006163 else
6164 return Error(L, "invalid operand to .code directive");
6165
6166 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006167 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006168 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006169
Evan Cheng284b4672011-07-08 22:36:29 +00006170 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006171 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006172 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006173 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00006174 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006175 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006176 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006177 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00006178 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00006179
Kevin Enderby146dcf22009-10-15 20:48:48 +00006180 return false;
6181}
6182
Jim Grosbachab5830e2011-12-14 02:16:11 +00006183/// parseDirectiveReq
6184/// ::= name .req registername
6185bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6186 Parser.Lex(); // Eat the '.req' token.
6187 unsigned Reg;
6188 SMLoc SRegLoc, ERegLoc;
6189 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6190 Parser.EatToEndOfStatement();
6191 return Error(SRegLoc, "register name expected");
6192 }
6193
6194 // Shouldn't be anything else.
6195 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6196 Parser.EatToEndOfStatement();
6197 return Error(Parser.getTok().getLoc(),
6198 "unexpected input in .req directive.");
6199 }
6200
6201 Parser.Lex(); // Consume the EndOfStatement
6202
6203 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6204 return Error(SRegLoc, "redefinition of '" + Name +
6205 "' does not match original.");
6206
6207 return false;
6208}
6209
6210/// parseDirectiveUneq
6211/// ::= .unreq registername
6212bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6213 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6214 Parser.EatToEndOfStatement();
6215 return Error(L, "unexpected input in .unreq directive.");
6216 }
6217 RegisterReqs.erase(Parser.getTok().getIdentifier());
6218 Parser.Lex(); // Eat the identifier.
6219 return false;
6220}
6221
Sean Callanan643a5572010-04-07 20:29:34 +00006222extern "C" void LLVMInitializeARMAsmLexer();
6223
Kevin Enderby8be42bd2009-10-30 22:55:57 +00006224/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00006225extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00006226 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6227 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00006228 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006229}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006230
Chris Lattner3e4582a2010-09-06 19:11:01 +00006231#define GET_REGISTER_MATCHER
6232#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006233#include "ARMGenAsmMatcher.inc"