blob: ed81ae053c71564c7541d8f1bc5875c37bf2c273 [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 Grosbachad47cfc2011-10-18 23:02:30 +0000339 } VectorList;
340
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000341 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000342 unsigned Val;
343 } VectorIndex;
344
345 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000346 const MCExpr *Val;
347 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000348
Jim Grosbache7fbce72011-10-03 23:38:36 +0000349 struct {
350 unsigned Val; // encoded 8-bit representation
351 } FPImm;
352
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000353 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000354 struct {
355 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000356 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
357 // was specified.
358 const MCConstantExpr *OffsetImm; // Offset immediate value
359 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
360 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000361 unsigned ShiftImm; // shift for OffsetReg.
362 unsigned Alignment; // 0 = no alignment specified
363 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000364 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000365 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000366
367 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000368 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000369 bool isAdd;
370 ARM_AM::ShiftOpc ShiftTy;
371 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000372 } PostIdxReg;
373
374 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000375 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000376 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000377 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000378 struct {
379 ARM_AM::ShiftOpc ShiftTy;
380 unsigned SrcReg;
381 unsigned ShiftReg;
382 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000383 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000384 struct {
385 ARM_AM::ShiftOpc ShiftTy;
386 unsigned SrcReg;
387 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000388 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000389 struct {
390 unsigned Imm;
391 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000392 struct {
393 unsigned LSB;
394 unsigned Width;
395 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000396 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000397
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000398 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
399public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000400 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
401 Kind = o.Kind;
402 StartLoc = o.StartLoc;
403 EndLoc = o.EndLoc;
404 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000405 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000406 CC = o.CC;
407 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000408 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000409 ITMask = o.ITMask;
410 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000411 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000412 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000413 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000414 case k_CCOut:
415 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000416 Reg = o.Reg;
417 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000418 case k_RegisterList:
419 case k_DPRRegisterList:
420 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000421 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000422 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000423 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000424 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000425 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000426 VectorList = o.VectorList;
427 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000428 case k_CoprocNum:
429 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000430 Cop = o.Cop;
431 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000432 case k_CoprocOption:
433 CoprocOption = o.CoprocOption;
434 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000435 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000436 Imm = o.Imm;
437 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000438 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000439 FPImm = o.FPImm;
440 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000441 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000442 MBOpt = o.MBOpt;
443 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000444 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000445 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000446 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000447 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000448 PostIdxReg = o.PostIdxReg;
449 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000450 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000451 MMask = o.MMask;
452 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000453 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000454 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000455 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000456 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000457 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000458 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000459 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000460 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000461 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000462 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000463 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000464 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000465 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000466 RotImm = o.RotImm;
467 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000468 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000469 Bitfield = o.Bitfield;
470 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000471 case k_VectorIndex:
472 VectorIndex = o.VectorIndex;
473 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000474 }
475 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000476
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000477 /// getStartLoc - Get the location of the first token of this operand.
478 SMLoc getStartLoc() const { return StartLoc; }
479 /// getEndLoc - Get the location of the last token of this operand.
480 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000481
Daniel Dunbard8042b72010-08-11 06:36:53 +0000482 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000483 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000484 return CC.Val;
485 }
486
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000487 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000488 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000489 return Cop.Val;
490 }
491
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000492 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000493 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000494 return StringRef(Tok.Data, Tok.Length);
495 }
496
497 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000498 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000499 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000500 }
501
Bill Wendlingbed94652010-11-09 23:28:44 +0000502 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000503 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
504 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000505 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000506 }
507
Kevin Enderbyf5079942009-10-13 22:19:02 +0000508 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000509 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000510 return Imm.Val;
511 }
512
Jim Grosbache7fbce72011-10-03 23:38:36 +0000513 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000514 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000515 return FPImm.Val;
516 }
517
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000518 unsigned getVectorIndex() const {
519 assert(Kind == k_VectorIndex && "Invalid access!");
520 return VectorIndex.Val;
521 }
522
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000523 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000525 return MBOpt.Val;
526 }
527
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000528 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000529 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000530 return IFlags.Val;
531 }
532
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000533 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000534 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000535 return MMask.Val;
536 }
537
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000538 bool isCoprocNum() const { return Kind == k_CoprocNum; }
539 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000540 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000541 bool isCondCode() const { return Kind == k_CondCode; }
542 bool isCCOut() const { return Kind == k_CCOut; }
543 bool isITMask() const { return Kind == k_ITCondMask; }
544 bool isITCondCode() const { return Kind == k_CondCode; }
545 bool isImm() const { return Kind == k_Immediate; }
546 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000547 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000548 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000549 return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int64_t Value = CE->getValue();
553 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
554 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000555 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000556 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000557 return false;
558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
559 if (!CE) return false;
560 int64_t Value = CE->getValue();
561 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
562 }
563 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000564 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000565 return false;
566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
570 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000571 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000572 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000573 return false;
574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
575 if (!CE) return false;
576 int64_t Value = CE->getValue();
577 return Value >= 0 && Value < 256;
578 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000579 bool isImm0_1() const {
580 if (Kind != k_Immediate)
581 return false;
582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
583 if (!CE) return false;
584 int64_t Value = CE->getValue();
585 return Value >= 0 && Value < 2;
586 }
587 bool isImm0_3() const {
588 if (Kind != k_Immediate)
589 return false;
590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
591 if (!CE) return false;
592 int64_t Value = CE->getValue();
593 return Value >= 0 && Value < 4;
594 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000595 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000596 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000597 return false;
598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 if (!CE) return false;
600 int64_t Value = CE->getValue();
601 return Value >= 0 && Value < 8;
602 }
603 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000604 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +0000605 return false;
606 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
607 if (!CE) return false;
608 int64_t Value = CE->getValue();
609 return Value >= 0 && Value < 16;
610 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000611 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000612 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000613 return false;
614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
615 if (!CE) return false;
616 int64_t Value = CE->getValue();
617 return Value >= 0 && Value < 32;
618 }
Jim Grosbach00326402011-12-08 01:30:04 +0000619 bool isImm0_63() const {
620 if (Kind != k_Immediate)
621 return false;
622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000627 bool isImm8() const {
628 if (Kind != k_Immediate)
629 return false;
630 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
631 if (!CE) return false;
632 int64_t Value = CE->getValue();
633 return Value == 8;
634 }
635 bool isImm16() const {
636 if (Kind != k_Immediate)
637 return false;
638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
639 if (!CE) return false;
640 int64_t Value = CE->getValue();
641 return Value == 16;
642 }
643 bool isImm32() const {
644 if (Kind != k_Immediate)
645 return false;
646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
647 if (!CE) return false;
648 int64_t Value = CE->getValue();
649 return Value == 32;
650 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000651 bool isShrImm8() const {
652 if (Kind != k_Immediate)
653 return false;
654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
655 if (!CE) return false;
656 int64_t Value = CE->getValue();
657 return Value > 0 && Value <= 8;
658 }
659 bool isShrImm16() const {
660 if (Kind != k_Immediate)
661 return false;
662 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
663 if (!CE) return false;
664 int64_t Value = CE->getValue();
665 return Value > 0 && Value <= 16;
666 }
667 bool isShrImm32() const {
668 if (Kind != k_Immediate)
669 return false;
670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
671 if (!CE) return false;
672 int64_t Value = CE->getValue();
673 return Value > 0 && Value <= 32;
674 }
675 bool isShrImm64() const {
676 if (Kind != k_Immediate)
677 return false;
678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value <= 64;
682 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000683 bool isImm1_7() const {
684 if (Kind != k_Immediate)
685 return false;
686 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
687 if (!CE) return false;
688 int64_t Value = CE->getValue();
689 return Value > 0 && Value < 8;
690 }
691 bool isImm1_15() const {
692 if (Kind != k_Immediate)
693 return false;
694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
695 if (!CE) return false;
696 int64_t Value = CE->getValue();
697 return Value > 0 && Value < 16;
698 }
699 bool isImm1_31() const {
700 if (Kind != k_Immediate)
701 return false;
702 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
703 if (!CE) return false;
704 int64_t Value = CE->getValue();
705 return Value > 0 && Value < 32;
706 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000707 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000708 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +0000709 return false;
710 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
711 if (!CE) return false;
712 int64_t Value = CE->getValue();
713 return Value > 0 && Value < 17;
714 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000715 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000716 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000717 return false;
718 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
719 if (!CE) return false;
720 int64_t Value = CE->getValue();
721 return Value > 0 && Value < 33;
722 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000723 bool isImm0_32() const {
724 if (Kind != k_Immediate)
725 return false;
726 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
727 if (!CE) return false;
728 int64_t Value = CE->getValue();
729 return Value >= 0 && Value < 33;
730 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000731 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000732 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000733 return false;
734 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
735 if (!CE) return false;
736 int64_t Value = CE->getValue();
737 return Value >= 0 && Value < 65536;
738 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000739 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000740 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000741 return false;
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 // If it's not a constant expression, it'll generate a fixup and be
744 // handled later.
745 if (!CE) return true;
746 int64_t Value = CE->getValue();
747 return Value >= 0 && Value < 65536;
748 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000749 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000750 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000751 return false;
752 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
753 if (!CE) return false;
754 int64_t Value = CE->getValue();
755 return Value >= 0 && Value <= 0xffffff;
756 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000757 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000758 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000759 return false;
760 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
761 if (!CE) return false;
762 int64_t Value = CE->getValue();
763 return Value > 0 && Value < 33;
764 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000765 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000766 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000767 return false;
768 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
769 if (!CE) return false;
770 int64_t Value = CE->getValue();
771 return Value >= 0 && Value < 32;
772 }
773 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000774 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000775 return false;
776 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
777 if (!CE) return false;
778 int64_t Value = CE->getValue();
779 return Value > 0 && Value <= 32;
780 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000781 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000782 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000783 return false;
784 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
785 if (!CE) return false;
786 int64_t Value = CE->getValue();
787 return ARM_AM::getSOImmVal(Value) != -1;
788 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +0000789 bool isARMSOImmNot() const {
790 if (Kind != k_Immediate)
791 return false;
792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getSOImmVal(~Value) != -1;
796 }
Jim Grosbach30506252011-12-08 00:31:07 +0000797 bool isARMSOImmNeg() const {
798 if (Kind != k_Immediate)
799 return false;
800 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
801 if (!CE) return false;
802 int64_t Value = CE->getValue();
803 return ARM_AM::getSOImmVal(-Value) != -1;
804 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000805 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000806 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000807 return false;
808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
809 if (!CE) return false;
810 int64_t Value = CE->getValue();
811 return ARM_AM::getT2SOImmVal(Value) != -1;
812 }
Jim Grosbachb009a872011-10-28 22:36:30 +0000813 bool isT2SOImmNot() const {
814 if (Kind != k_Immediate)
815 return false;
816 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
817 if (!CE) return false;
818 int64_t Value = CE->getValue();
819 return ARM_AM::getT2SOImmVal(~Value) != -1;
820 }
Jim Grosbach30506252011-12-08 00:31:07 +0000821 bool isT2SOImmNeg() const {
822 if (Kind != k_Immediate)
823 return false;
824 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
825 if (!CE) return false;
826 int64_t Value = CE->getValue();
827 return ARM_AM::getT2SOImmVal(-Value) != -1;
828 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000829 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000830 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000831 return false;
832 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
833 if (!CE) return false;
834 int64_t Value = CE->getValue();
835 return Value == 1 || Value == 0;
836 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000837 bool isReg() const { return Kind == k_Register; }
838 bool isRegList() const { return Kind == k_RegisterList; }
839 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
840 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
841 bool isToken() const { return Kind == k_Token; }
842 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
843 bool isMemory() const { return Kind == k_Memory; }
844 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
845 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
846 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
847 bool isRotImm() const { return Kind == k_RotateImmediate; }
848 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
849 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000850 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +0000851 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000852 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000853 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000854 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000855 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000856 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000857 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
858 (alignOK || Memory.Alignment == 0);
859 }
860 bool isAlignedMemory() const {
861 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000862 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000863 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000864 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000865 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000866 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000867 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000868 if (!Memory.OffsetImm) return true;
869 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000870 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000871 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000872 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000873 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000874 return false;
875 // Immediate offset in range [-4095, 4095].
876 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
877 if (!CE) return false;
878 int64_t Val = CE->getValue();
879 return Val > -4096 && Val < 4096;
880 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000881 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000882 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000883 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000884 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000885 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000886 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000887 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000888 if (!Memory.OffsetImm) return true;
889 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000890 return Val > -256 && Val < 256;
891 }
892 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000893 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000894 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000895 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000896 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
897 // Immediate offset in range [-255, 255].
898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
899 if (!CE) return false;
900 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000901 // Special case, #-0 is INT32_MIN.
902 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000903 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000904 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000905 // If we have an immediate that's not a constant, treat it as a label
906 // reference needing a fixup. If it is a constant, it's something else
907 // and we reject it.
908 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
909 return true;
Jim Grosbacha95ec992011-10-11 17:29:55 +0000910 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000911 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000912 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000913 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000914 if (!Memory.OffsetImm) return true;
915 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000916 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +0000917 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000918 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000919 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000920 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000921 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000922 return false;
923 return true;
924 }
925 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000926 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000927 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
928 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000929 return false;
930 return true;
931 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000932 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000933 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000934 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000935 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000936 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000937 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000938 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
939 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000940 return false;
941 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000942 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000943 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000944 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000945 return false;
946 return true;
947 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000948 bool isMemThumbRR() const {
949 // Thumb reg+reg addressing is simple. Just two registers, a base and
950 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000951 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000952 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000953 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000954 return isARMLowRegister(Memory.BaseRegNum) &&
955 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000956 }
957 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000958 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000959 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000960 return false;
961 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000962 if (!Memory.OffsetImm) return true;
963 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000964 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
965 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000966 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000967 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000968 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000969 return false;
970 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000971 if (!Memory.OffsetImm) return true;
972 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000973 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
974 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000975 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000976 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000977 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000978 return false;
979 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000980 if (!Memory.OffsetImm) return true;
981 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000982 return Val >= 0 && Val <= 31;
983 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000984 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000985 if (!isMemory() || Memory.OffsetRegNum != 0 ||
986 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000987 return false;
988 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000991 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000992 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000993 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000995 return false;
996 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000999 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1000 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001001 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001002 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001003 return false;
1004 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001005 if (!Memory.OffsetImm) return true;
1006 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001007 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1008 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001009 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001010 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001011 return false;
1012 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001013 if (!Memory.OffsetImm) return true;
1014 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001015 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001016 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001017 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001018 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001019 return false;
1020 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001023 return Val >= 0 && Val < 256;
1024 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001025 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001027 return false;
1028 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001029 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001030 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001031 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001032 }
1033 bool isMemUImm12Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +00001034 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001035 return false;
1036 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001037 if (!Memory.OffsetImm) return true;
1038 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001039 return (Val >= 0 && Val < 4096);
1040 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001041 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001042 // If we have an immediate that's not a constant, treat it as a label
1043 // reference needing a fixup. If it is a constant, it's something else
1044 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001045 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001046 return true;
1047
Jim Grosbacha95ec992011-10-11 17:29:55 +00001048 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001049 return false;
1050 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001051 if (!Memory.OffsetImm) return true;
1052 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001053 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001054 }
1055 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001056 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +00001057 return false;
1058 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1059 if (!CE) return false;
1060 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001061 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001062 }
Jim Grosbach93981412011-10-11 21:55:36 +00001063 bool isPostIdxImm8s4() const {
1064 if (Kind != k_Immediate)
1065 return false;
1066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 if (!CE) return false;
1068 int64_t Val = CE->getValue();
1069 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1070 (Val == INT32_MIN);
1071 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001072
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001073 bool isMSRMask() const { return Kind == k_MSRMask; }
1074 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001075
Jim Grosbach741cd732011-10-17 22:26:03 +00001076 // NEON operands.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001077 bool isVecListOneD() const {
1078 if (Kind != k_VectorList) return false;
1079 return VectorList.Count == 1;
1080 }
1081
Jim Grosbach2f2e3c42011-10-21 18:54:25 +00001082 bool isVecListTwoD() const {
1083 if (Kind != k_VectorList) return false;
1084 return VectorList.Count == 2;
1085 }
1086
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001087 bool isVecListThreeD() const {
1088 if (Kind != k_VectorList) return false;
1089 return VectorList.Count == 3;
1090 }
1091
Jim Grosbach846bcff2011-10-21 20:35:01 +00001092 bool isVecListFourD() const {
1093 if (Kind != k_VectorList) return false;
1094 return VectorList.Count == 4;
1095 }
1096
Jim Grosbach118b38c2011-10-21 22:21:10 +00001097 bool isVecListTwoQ() const {
1098 if (Kind != k_VectorList) return false;
1099 //FIXME: We haven't taught the parser to handle by-two register lists
1100 // yet, so don't pretend to know one.
1101 return VectorList.Count == 2 && false;
1102 }
1103
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001104 bool isVecListOneDAllLanes() const {
1105 if (Kind != k_VectorListAllLanes) return false;
1106 return VectorList.Count == 1;
1107 }
1108
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001109 bool isVecListTwoDAllLanes() const {
1110 if (Kind != k_VectorListAllLanes) return false;
1111 return VectorList.Count == 2;
1112 }
1113
Jim Grosbach04945c42011-12-02 00:35:16 +00001114 bool isVecListOneDByteIndexed() const {
1115 if (Kind != k_VectorListIndexed) return false;
1116 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1117 }
1118
Jim Grosbachda511042011-12-14 23:35:06 +00001119 bool isVecListOneDHWordIndexed() const {
1120 if (Kind != k_VectorListIndexed) return false;
1121 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1122 }
1123
1124 bool isVecListOneDWordIndexed() const {
1125 if (Kind != k_VectorListIndexed) return false;
1126 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1127 }
1128
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001129 bool isVecListTwoDByteIndexed() const {
1130 if (Kind != k_VectorListIndexed) return false;
1131 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1132 }
1133
Jim Grosbachda511042011-12-14 23:35:06 +00001134 bool isVecListTwoDHWordIndexed() const {
1135 if (Kind != k_VectorListIndexed) return false;
1136 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1137 }
1138
1139 bool isVecListTwoDWordIndexed() const {
1140 if (Kind != k_VectorListIndexed) return false;
1141 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1142 }
1143
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001144 bool isVectorIndex8() const {
1145 if (Kind != k_VectorIndex) return false;
1146 return VectorIndex.Val < 8;
1147 }
1148 bool isVectorIndex16() const {
1149 if (Kind != k_VectorIndex) return false;
1150 return VectorIndex.Val < 4;
1151 }
1152 bool isVectorIndex32() const {
1153 if (Kind != k_VectorIndex) return false;
1154 return VectorIndex.Val < 2;
1155 }
1156
Jim Grosbach741cd732011-10-17 22:26:03 +00001157 bool isNEONi8splat() const {
1158 if (Kind != k_Immediate)
1159 return false;
1160 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1161 // Must be a constant.
1162 if (!CE) return false;
1163 int64_t Value = CE->getValue();
1164 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1165 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001166 return Value >= 0 && Value < 256;
1167 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001168
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001169 bool isNEONi16splat() const {
1170 if (Kind != k_Immediate)
1171 return false;
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 // Must be a constant.
1174 if (!CE) return false;
1175 int64_t Value = CE->getValue();
1176 // i16 value in the range [0,255] or [0x0100, 0xff00]
1177 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1178 }
1179
Jim Grosbach8211c052011-10-18 00:22:00 +00001180 bool isNEONi32splat() const {
1181 if (Kind != k_Immediate)
1182 return false;
1183 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1184 // Must be a constant.
1185 if (!CE) return false;
1186 int64_t Value = CE->getValue();
1187 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1188 return (Value >= 0 && Value < 256) ||
1189 (Value >= 0x0100 && Value <= 0xff00) ||
1190 (Value >= 0x010000 && Value <= 0xff0000) ||
1191 (Value >= 0x01000000 && Value <= 0xff000000);
1192 }
1193
1194 bool isNEONi32vmov() const {
1195 if (Kind != k_Immediate)
1196 return false;
1197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 // Must be a constant.
1199 if (!CE) return false;
1200 int64_t Value = CE->getValue();
1201 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1202 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1203 return (Value >= 0 && Value < 256) ||
1204 (Value >= 0x0100 && Value <= 0xff00) ||
1205 (Value >= 0x010000 && Value <= 0xff0000) ||
1206 (Value >= 0x01000000 && Value <= 0xff000000) ||
1207 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1208 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1209 }
1210
Jim Grosbache4454e02011-10-18 16:18:11 +00001211 bool isNEONi64splat() const {
1212 if (Kind != k_Immediate)
1213 return false;
1214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 // Must be a constant.
1216 if (!CE) return false;
1217 uint64_t Value = CE->getValue();
1218 // i64 value with each byte being either 0 or 0xff.
1219 for (unsigned i = 0; i < 8; ++i)
1220 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1221 return true;
1222 }
1223
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001224 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001225 // Add as immediates when possible. Null MCExpr = 0.
1226 if (Expr == 0)
1227 Inst.addOperand(MCOperand::CreateImm(0));
1228 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001229 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1230 else
1231 Inst.addOperand(MCOperand::CreateExpr(Expr));
1232 }
1233
Daniel Dunbard8042b72010-08-11 06:36:53 +00001234 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001235 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001236 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001237 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1238 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001239 }
1240
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001241 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1244 }
1245
Jim Grosbach48399582011-10-12 17:34:41 +00001246 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
1248 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1249 }
1250
1251 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1254 }
1255
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001256 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1257 assert(N == 1 && "Invalid number of operands!");
1258 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1259 }
1260
1261 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1264 }
1265
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001266 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 1 && "Invalid number of operands!");
1268 Inst.addOperand(MCOperand::CreateReg(getReg()));
1269 }
1270
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001271 void addRegOperands(MCInst &Inst, unsigned N) const {
1272 assert(N == 1 && "Invalid number of operands!");
1273 Inst.addOperand(MCOperand::CreateReg(getReg()));
1274 }
1275
Jim Grosbachac798e12011-07-25 20:49:51 +00001276 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001277 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001278 assert(isRegShiftedReg() &&
1279 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001280 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1281 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001282 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001283 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001284 }
1285
Jim Grosbachac798e12011-07-25 20:49:51 +00001286 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001287 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001288 assert(isRegShiftedImm() &&
1289 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001290 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001291 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001292 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001293 }
1294
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001295 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001296 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001297 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1298 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001299 }
1300
Bill Wendling8d2aa032010-11-08 23:49:57 +00001301 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001302 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001303 const SmallVectorImpl<unsigned> &RegList = getRegList();
1304 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001305 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1306 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001307 }
1308
Bill Wendling9898ac92010-11-17 04:32:08 +00001309 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1310 addRegListOperands(Inst, N);
1311 }
1312
1313 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1314 addRegListOperands(Inst, N);
1315 }
1316
Jim Grosbach833b9d32011-07-27 20:15:40 +00001317 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1318 assert(N == 1 && "Invalid number of operands!");
1319 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1320 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1321 }
1322
Jim Grosbach864b6092011-07-28 21:34:26 +00001323 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
1325 // Munge the lsb/width into a bitfield mask.
1326 unsigned lsb = Bitfield.LSB;
1327 unsigned width = Bitfield.Width;
1328 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1329 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1330 (32 - (lsb + width)));
1331 Inst.addOperand(MCOperand::CreateImm(Mask));
1332 }
1333
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001334 void addImmOperands(MCInst &Inst, unsigned N) const {
1335 assert(N == 1 && "Invalid number of operands!");
1336 addExpr(Inst, getImm());
1337 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001338
Jim Grosbache7fbce72011-10-03 23:38:36 +00001339 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1340 assert(N == 1 && "Invalid number of operands!");
1341 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1342 }
1343
Jim Grosbach7db8d692011-09-08 22:07:06 +00001344 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1345 assert(N == 1 && "Invalid number of operands!");
1346 // FIXME: We really want to scale the value here, but the LDRD/STRD
1347 // instruction don't encode operands that way yet.
1348 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1349 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1350 }
1351
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001352 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
1354 // The immediate is scaled by four in the encoding and is stored
1355 // in the MCInst as such. Lop off the low two bits here.
1356 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1357 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1358 }
1359
1360 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1361 assert(N == 1 && "Invalid number of operands!");
1362 // The immediate is scaled by four in the encoding and is stored
1363 // in the MCInst as such. Lop off the low two bits here.
1364 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1365 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1366 }
1367
Jim Grosbach475c6db2011-07-25 23:09:14 +00001368 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 // The constant encodes as the immediate-1, and we store in the instruction
1371 // the bits as encoded, so subtract off one here.
1372 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1373 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1374 }
1375
Jim Grosbach801e0a32011-07-22 23:16:18 +00001376 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1377 assert(N == 1 && "Invalid number of operands!");
1378 // The constant encodes as the immediate-1, and we store in the instruction
1379 // the bits as encoded, so subtract off one here.
1380 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1381 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1382 }
1383
Jim Grosbach46dd4132011-08-17 21:51:27 +00001384 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 // The constant encodes as the immediate, except for 32, which encodes as
1387 // zero.
1388 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1389 unsigned Imm = CE->getValue();
1390 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1391 }
1392
Jim Grosbach27c1e252011-07-21 17:23:04 +00001393 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1396 // the instruction as well.
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 int Val = CE->getValue();
1399 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1400 }
1401
Jim Grosbachb009a872011-10-28 22:36:30 +00001402 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 1 && "Invalid number of operands!");
1404 // The operand is actually a t2_so_imm, but we have its bitwise
1405 // negation in the assembly source, so twiddle it here.
1406 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1407 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1408 }
1409
Jim Grosbach30506252011-12-08 00:31:07 +00001410 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1411 assert(N == 1 && "Invalid number of operands!");
1412 // The operand is actually a t2_so_imm, but we have its
1413 // negation in the assembly source, so twiddle it here.
1414 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1415 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1416 }
1417
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001418 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1419 assert(N == 1 && "Invalid number of operands!");
1420 // The operand is actually a so_imm, but we have its bitwise
1421 // negation in the assembly source, so twiddle it here.
1422 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1423 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1424 }
1425
Jim Grosbach30506252011-12-08 00:31:07 +00001426 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
1428 // The operand is actually a so_imm, but we have its
1429 // negation in the assembly source, so twiddle it here.
1430 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1431 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1432 }
1433
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001434 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1437 }
1438
Jim Grosbachd3595712011-08-03 23:50:40 +00001439 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001442 }
1443
Jim Grosbacha95ec992011-10-11 17:29:55 +00001444 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 2 && "Invalid number of operands!");
1446 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1447 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1448 }
1449
Jim Grosbachd3595712011-08-03 23:50:40 +00001450 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1451 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001452 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1453 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001454 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1455 // Special case for #-0
1456 if (Val == INT32_MIN) Val = 0;
1457 if (Val < 0) Val = -Val;
1458 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1459 } else {
1460 // For register offset, we encode the shift type and negation flag
1461 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001462 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1463 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001464 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001465 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1466 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001467 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001468 }
1469
Jim Grosbachcd17c122011-08-04 23:01:30 +00001470 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1471 assert(N == 2 && "Invalid number of operands!");
1472 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1473 assert(CE && "non-constant AM2OffsetImm operand!");
1474 int32_t Val = CE->getValue();
1475 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1476 // Special case for #-0
1477 if (Val == INT32_MIN) Val = 0;
1478 if (Val < 0) Val = -Val;
1479 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1480 Inst.addOperand(MCOperand::CreateReg(0));
1481 Inst.addOperand(MCOperand::CreateImm(Val));
1482 }
1483
Jim Grosbach5b96b802011-08-10 20:29:19 +00001484 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001486 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1487 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001488 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1489 // Special case for #-0
1490 if (Val == INT32_MIN) Val = 0;
1491 if (Val < 0) Val = -Val;
1492 Val = ARM_AM::getAM3Opc(AddSub, Val);
1493 } else {
1494 // For register offset, we encode the shift type and negation flag
1495 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001496 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001497 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001498 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1499 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001500 Inst.addOperand(MCOperand::CreateImm(Val));
1501 }
1502
1503 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001505 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001506 int32_t Val =
1507 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1508 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1509 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001510 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001511 }
1512
1513 // Constant offset.
1514 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1515 int32_t Val = CE->getValue();
1516 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1517 // Special case for #-0
1518 if (Val == INT32_MIN) Val = 0;
1519 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001520 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001521 Inst.addOperand(MCOperand::CreateReg(0));
1522 Inst.addOperand(MCOperand::CreateImm(Val));
1523 }
1524
Jim Grosbachd3595712011-08-03 23:50:40 +00001525 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001527 // If we have an immediate that's not a constant, treat it as a label
1528 // reference needing a fixup. If it is a constant, it's something else
1529 // and we reject it.
1530 if (isImm()) {
1531 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1532 Inst.addOperand(MCOperand::CreateImm(0));
1533 return;
1534 }
1535
Jim Grosbachd3595712011-08-03 23:50:40 +00001536 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001537 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001538 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1539 // Special case for #-0
1540 if (Val == INT32_MIN) Val = 0;
1541 if (Val < 0) Val = -Val;
1542 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001543 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001544 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001545 }
1546
Jim Grosbach7db8d692011-09-08 22:07:06 +00001547 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001549 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1550 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001551 Inst.addOperand(MCOperand::CreateImm(Val));
1552 }
1553
Jim Grosbacha05627e2011-09-09 18:37:27 +00001554 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 2 && "Invalid number of operands!");
1556 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001557 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1558 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001559 Inst.addOperand(MCOperand::CreateImm(Val));
1560 }
1561
Jim Grosbachd3595712011-08-03 23:50:40 +00001562 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001564 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1565 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001566 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001567 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001568
Jim Grosbach2392c532011-09-07 23:39:14 +00001569 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1570 addMemImm8OffsetOperands(Inst, N);
1571 }
1572
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001573 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001574 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001575 }
1576
1577 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1578 assert(N == 2 && "Invalid number of operands!");
1579 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001580 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001581 addExpr(Inst, getImm());
1582 Inst.addOperand(MCOperand::CreateImm(0));
1583 return;
1584 }
1585
1586 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001587 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1588 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001589 Inst.addOperand(MCOperand::CreateImm(Val));
1590 }
1591
Jim Grosbachd3595712011-08-03 23:50:40 +00001592 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001594 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001595 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001596 addExpr(Inst, getImm());
1597 Inst.addOperand(MCOperand::CreateImm(0));
1598 return;
1599 }
1600
1601 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001602 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1603 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001604 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001605 }
Bill Wendling811c9362010-11-30 07:44:32 +00001606
Jim Grosbach05541f42011-09-19 22:21:13 +00001607 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1608 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001609 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1610 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001611 }
1612
1613 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001615 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1616 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001617 }
1618
Jim Grosbachd3595712011-08-03 23:50:40 +00001619 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1620 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001621 unsigned Val =
1622 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1623 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00001624 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1625 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001626 Inst.addOperand(MCOperand::CreateImm(Val));
1627 }
1628
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001629 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001631 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1632 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1633 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001634 }
1635
Jim Grosbachd3595712011-08-03 23:50:40 +00001636 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1637 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001638 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1639 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001640 }
1641
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001642 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1643 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001644 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1645 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001646 Inst.addOperand(MCOperand::CreateImm(Val));
1647 }
1648
Jim Grosbach26d35872011-08-19 18:55:51 +00001649 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1650 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001651 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1652 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001653 Inst.addOperand(MCOperand::CreateImm(Val));
1654 }
1655
Jim Grosbacha32c7532011-08-19 18:49:59 +00001656 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1657 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001658 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1659 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001660 Inst.addOperand(MCOperand::CreateImm(Val));
1661 }
1662
Jim Grosbach23983d62011-08-19 18:13:48 +00001663 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001665 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1666 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001667 Inst.addOperand(MCOperand::CreateImm(Val));
1668 }
1669
Jim Grosbachd3595712011-08-03 23:50:40 +00001670 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1671 assert(N == 1 && "Invalid number of operands!");
1672 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1673 assert(CE && "non-constant post-idx-imm8 operand!");
1674 int Imm = CE->getValue();
1675 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001676 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001677 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1678 Inst.addOperand(MCOperand::CreateImm(Imm));
1679 }
1680
Jim Grosbach93981412011-10-11 21:55:36 +00001681 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1682 assert(N == 1 && "Invalid number of operands!");
1683 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1684 assert(CE && "non-constant post-idx-imm8s4 operand!");
1685 int Imm = CE->getValue();
1686 bool isAdd = Imm >= 0;
1687 if (Imm == INT32_MIN) Imm = 0;
1688 // Immediate is scaled by 4.
1689 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1690 Inst.addOperand(MCOperand::CreateImm(Imm));
1691 }
1692
Jim Grosbachd3595712011-08-03 23:50:40 +00001693 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1694 assert(N == 2 && "Invalid number of operands!");
1695 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001696 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1697 }
1698
1699 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1700 assert(N == 2 && "Invalid number of operands!");
1701 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1702 // The sign, shift type, and shift amount are encoded in a single operand
1703 // using the AM2 encoding helpers.
1704 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1705 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1706 PostIdxReg.ShiftTy);
1707 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001708 }
1709
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001710 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1711 assert(N == 1 && "Invalid number of operands!");
1712 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1713 }
1714
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001715 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 1 && "Invalid number of operands!");
1717 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1718 }
1719
Jim Grosbach182b6a02011-11-29 23:51:09 +00001720 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001721 assert(N == 1 && "Invalid number of operands!");
1722 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1723 }
1724
Jim Grosbach04945c42011-12-02 00:35:16 +00001725 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1726 assert(N == 2 && "Invalid number of operands!");
1727 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1728 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1729 }
1730
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001731 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1732 assert(N == 1 && "Invalid number of operands!");
1733 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1734 }
1735
1736 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1737 assert(N == 1 && "Invalid number of operands!");
1738 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1739 }
1740
1741 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1742 assert(N == 1 && "Invalid number of operands!");
1743 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1744 }
1745
Jim Grosbach741cd732011-10-17 22:26:03 +00001746 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1747 assert(N == 1 && "Invalid number of operands!");
1748 // The immediate encodes the type of constant as well as the value.
1749 // Mask in that this is an i8 splat.
1750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1751 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1752 }
1753
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001754 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1755 assert(N == 1 && "Invalid number of operands!");
1756 // The immediate encodes the type of constant as well as the value.
1757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1758 unsigned Value = CE->getValue();
1759 if (Value >= 256)
1760 Value = (Value >> 8) | 0xa00;
1761 else
1762 Value |= 0x800;
1763 Inst.addOperand(MCOperand::CreateImm(Value));
1764 }
1765
Jim Grosbach8211c052011-10-18 00:22:00 +00001766 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1767 assert(N == 1 && "Invalid number of operands!");
1768 // The immediate encodes the type of constant as well as the value.
1769 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1770 unsigned Value = CE->getValue();
1771 if (Value >= 256 && Value <= 0xff00)
1772 Value = (Value >> 8) | 0x200;
1773 else if (Value > 0xffff && Value <= 0xff0000)
1774 Value = (Value >> 16) | 0x400;
1775 else if (Value > 0xffffff)
1776 Value = (Value >> 24) | 0x600;
1777 Inst.addOperand(MCOperand::CreateImm(Value));
1778 }
1779
1780 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1781 assert(N == 1 && "Invalid number of operands!");
1782 // The immediate encodes the type of constant as well as the value.
1783 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1784 unsigned Value = CE->getValue();
1785 if (Value >= 256 && Value <= 0xffff)
1786 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1787 else if (Value > 0xffff && Value <= 0xffffff)
1788 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1789 else if (Value > 0xffffff)
1790 Value = (Value >> 24) | 0x600;
1791 Inst.addOperand(MCOperand::CreateImm(Value));
1792 }
1793
Jim Grosbache4454e02011-10-18 16:18:11 +00001794 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1795 assert(N == 1 && "Invalid number of operands!");
1796 // The immediate encodes the type of constant as well as the value.
1797 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1798 uint64_t Value = CE->getValue();
1799 unsigned Imm = 0;
1800 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1801 Imm |= (Value & 1) << i;
1802 }
1803 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1804 }
1805
Jim Grosbach602aa902011-07-13 15:34:57 +00001806 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001807
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001808 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001809 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001810 Op->ITMask.Mask = Mask;
1811 Op->StartLoc = S;
1812 Op->EndLoc = S;
1813 return Op;
1814 }
1815
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001816 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001817 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001818 Op->CC.Val = CC;
1819 Op->StartLoc = S;
1820 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001821 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001822 }
1823
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001824 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001825 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001826 Op->Cop.Val = CopVal;
1827 Op->StartLoc = S;
1828 Op->EndLoc = S;
1829 return Op;
1830 }
1831
1832 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001833 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001834 Op->Cop.Val = CopVal;
1835 Op->StartLoc = S;
1836 Op->EndLoc = S;
1837 return Op;
1838 }
1839
Jim Grosbach48399582011-10-12 17:34:41 +00001840 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1841 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1842 Op->Cop.Val = Val;
1843 Op->StartLoc = S;
1844 Op->EndLoc = E;
1845 return Op;
1846 }
1847
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001848 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001849 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001850 Op->Reg.RegNum = RegNum;
1851 Op->StartLoc = S;
1852 Op->EndLoc = S;
1853 return Op;
1854 }
1855
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001856 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001857 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001858 Op->Tok.Data = Str.data();
1859 Op->Tok.Length = Str.size();
1860 Op->StartLoc = S;
1861 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001862 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001863 }
1864
Bill Wendling2063b842010-11-18 23:43:05 +00001865 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001866 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001867 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001868 Op->StartLoc = S;
1869 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001870 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001871 }
1872
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001873 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1874 unsigned SrcReg,
1875 unsigned ShiftReg,
1876 unsigned ShiftImm,
1877 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001878 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001879 Op->RegShiftedReg.ShiftTy = ShTy;
1880 Op->RegShiftedReg.SrcReg = SrcReg;
1881 Op->RegShiftedReg.ShiftReg = ShiftReg;
1882 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001883 Op->StartLoc = S;
1884 Op->EndLoc = E;
1885 return Op;
1886 }
1887
Owen Andersonb595ed02011-07-21 18:54:16 +00001888 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1889 unsigned SrcReg,
1890 unsigned ShiftImm,
1891 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001892 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001893 Op->RegShiftedImm.ShiftTy = ShTy;
1894 Op->RegShiftedImm.SrcReg = SrcReg;
1895 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001896 Op->StartLoc = S;
1897 Op->EndLoc = E;
1898 return Op;
1899 }
1900
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001901 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001902 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001903 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001904 Op->ShifterImm.isASR = isASR;
1905 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001906 Op->StartLoc = S;
1907 Op->EndLoc = E;
1908 return Op;
1909 }
1910
Jim Grosbach833b9d32011-07-27 20:15:40 +00001911 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001912 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001913 Op->RotImm.Imm = Imm;
1914 Op->StartLoc = S;
1915 Op->EndLoc = E;
1916 return Op;
1917 }
1918
Jim Grosbach864b6092011-07-28 21:34:26 +00001919 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1920 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001921 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001922 Op->Bitfield.LSB = LSB;
1923 Op->Bitfield.Width = Width;
1924 Op->StartLoc = S;
1925 Op->EndLoc = E;
1926 return Op;
1927 }
1928
Bill Wendling2cae3272010-11-09 22:44:22 +00001929 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001930 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001931 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001932 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001933
Jim Grosbach75461af2011-09-13 22:56:44 +00001934 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001935 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001936 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001937 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001938 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001939
1940 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001941 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001942 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001943 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001944 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001945 Op->StartLoc = StartLoc;
1946 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001947 return Op;
1948 }
1949
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001950 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1951 SMLoc S, SMLoc E) {
1952 ARMOperand *Op = new ARMOperand(k_VectorList);
1953 Op->VectorList.RegNum = RegNum;
1954 Op->VectorList.Count = Count;
1955 Op->StartLoc = S;
1956 Op->EndLoc = E;
1957 return Op;
1958 }
1959
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001960 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1961 SMLoc S, SMLoc E) {
1962 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1963 Op->VectorList.RegNum = RegNum;
1964 Op->VectorList.Count = Count;
1965 Op->StartLoc = S;
1966 Op->EndLoc = E;
1967 return Op;
1968 }
1969
Jim Grosbach04945c42011-12-02 00:35:16 +00001970 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1971 unsigned Index, SMLoc S, SMLoc E) {
1972 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1973 Op->VectorList.RegNum = RegNum;
1974 Op->VectorList.Count = Count;
1975 Op->VectorList.LaneIndex = Index;
1976 Op->StartLoc = S;
1977 Op->EndLoc = E;
1978 return Op;
1979 }
1980
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001981 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1982 MCContext &Ctx) {
1983 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1984 Op->VectorIndex.Val = Idx;
1985 Op->StartLoc = S;
1986 Op->EndLoc = E;
1987 return Op;
1988 }
1989
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001990 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001991 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001992 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001993 Op->StartLoc = S;
1994 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001995 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001996 }
1997
Jim Grosbache7fbce72011-10-03 23:38:36 +00001998 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001999 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00002000 Op->FPImm.Val = Val;
2001 Op->StartLoc = S;
2002 Op->EndLoc = S;
2003 return Op;
2004 }
2005
Jim Grosbachd3595712011-08-03 23:50:40 +00002006 static ARMOperand *CreateMem(unsigned BaseRegNum,
2007 const MCConstantExpr *OffsetImm,
2008 unsigned OffsetRegNum,
2009 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002010 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00002011 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00002012 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002013 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002014 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002015 Op->Memory.BaseRegNum = BaseRegNum;
2016 Op->Memory.OffsetImm = OffsetImm;
2017 Op->Memory.OffsetRegNum = OffsetRegNum;
2018 Op->Memory.ShiftType = ShiftType;
2019 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002020 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002021 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002022 Op->StartLoc = S;
2023 Op->EndLoc = E;
2024 return Op;
2025 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002026
Jim Grosbachc320c852011-08-05 21:28:30 +00002027 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2028 ARM_AM::ShiftOpc ShiftTy,
2029 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00002030 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002031 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002032 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002033 Op->PostIdxReg.isAdd = isAdd;
2034 Op->PostIdxReg.ShiftTy = ShiftTy;
2035 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002036 Op->StartLoc = S;
2037 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002038 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002039 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002040
2041 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002042 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002043 Op->MBOpt.Val = Opt;
2044 Op->StartLoc = S;
2045 Op->EndLoc = S;
2046 return Op;
2047 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002048
2049 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002050 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002051 Op->IFlags.Val = IFlags;
2052 Op->StartLoc = S;
2053 Op->EndLoc = S;
2054 return Op;
2055 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002056
2057 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002058 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002059 Op->MMask.Val = MMask;
2060 Op->StartLoc = S;
2061 Op->EndLoc = S;
2062 return Op;
2063 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002064};
2065
2066} // end anonymous namespace.
2067
Jim Grosbach602aa902011-07-13 15:34:57 +00002068void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002069 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002070 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00002071 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2072 << ") >";
2073 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002074 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002075 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002076 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002077 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002078 OS << "<ccout " << getReg() << ">";
2079 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002080 case k_ITCondMask: {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002081 static const char *MaskStr[] = {
2082 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2083 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2084 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002085 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2086 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2087 break;
2088 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002089 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002090 OS << "<coprocessor number: " << getCoproc() << ">";
2091 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002092 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002093 OS << "<coprocessor register: " << getCoproc() << ">";
2094 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002095 case k_CoprocOption:
2096 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2097 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002098 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002099 OS << "<mask: " << getMSRMask() << ">";
2100 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002101 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002102 getImm()->print(OS);
2103 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002104 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002105 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2106 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002107 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002108 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002109 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002110 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002111 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002112 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002113 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2114 << PostIdxReg.RegNum;
2115 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2116 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2117 << PostIdxReg.ShiftImm;
2118 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002119 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002120 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002121 OS << "<ARM_PROC::";
2122 unsigned IFlags = getProcIFlags();
2123 for (int i=2; i >= 0; --i)
2124 if (IFlags & (1 << i))
2125 OS << ARM_PROC::IFlagsToString(1 << i);
2126 OS << ">";
2127 break;
2128 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002129 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002130 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002131 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002132 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002133 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2134 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002135 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002136 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002137 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002138 << RegShiftedReg.SrcReg << " "
2139 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2140 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002141 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002142 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002143 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002144 << RegShiftedImm.SrcReg << " "
2145 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2146 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002147 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002148 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002149 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2150 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002151 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002152 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2153 << ", width: " << Bitfield.Width << ">";
2154 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002155 case k_RegisterList:
2156 case k_DPRRegisterList:
2157 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002158 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002159
Bill Wendlingbed94652010-11-09 23:28:44 +00002160 const SmallVectorImpl<unsigned> &RegList = getRegList();
2161 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002162 I = RegList.begin(), E = RegList.end(); I != E; ) {
2163 OS << *I;
2164 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002165 }
2166
2167 OS << ">";
2168 break;
2169 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002170 case k_VectorList:
2171 OS << "<vector_list " << VectorList.Count << " * "
2172 << VectorList.RegNum << ">";
2173 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002174 case k_VectorListAllLanes:
2175 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2176 << VectorList.RegNum << ">";
2177 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002178 case k_VectorListIndexed:
2179 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2180 << VectorList.Count << " * " << VectorList.RegNum << ">";
2181 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002182 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002183 OS << "'" << getToken() << "'";
2184 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002185 case k_VectorIndex:
2186 OS << "<vectorindex " << getVectorIndex() << ">";
2187 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002188 }
2189}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002190
2191/// @name Auto-generated Match Functions
2192/// {
2193
2194static unsigned MatchRegisterName(StringRef Name);
2195
2196/// }
2197
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002198bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2199 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002200 StartLoc = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002201 RegNo = tryParseRegister();
Jim Grosbachab5830e2011-12-14 02:16:11 +00002202 EndLoc = Parser.getTok().getLoc();
Roman Divacky36b1b472011-01-27 17:14:22 +00002203
2204 return (RegNo == (unsigned)-1);
2205}
2206
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002207/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002208/// and if it is a register name the token is eaten and the register number is
2209/// returned. Otherwise return -1.
2210///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002211int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002212 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002213 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002214
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002215 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002216 unsigned RegNum = MatchRegisterName(lowerCase);
2217 if (!RegNum) {
2218 RegNum = StringSwitch<unsigned>(lowerCase)
2219 .Case("r13", ARM::SP)
2220 .Case("r14", ARM::LR)
2221 .Case("r15", ARM::PC)
2222 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002223 // Additional register name aliases for 'gas' compatibility.
2224 .Case("a1", ARM::R0)
2225 .Case("a2", ARM::R1)
2226 .Case("a3", ARM::R2)
2227 .Case("a4", ARM::R3)
2228 .Case("v1", ARM::R4)
2229 .Case("v2", ARM::R5)
2230 .Case("v3", ARM::R6)
2231 .Case("v4", ARM::R7)
2232 .Case("v5", ARM::R8)
2233 .Case("v6", ARM::R9)
2234 .Case("v7", ARM::R10)
2235 .Case("v8", ARM::R11)
2236 .Case("sb", ARM::R9)
2237 .Case("sl", ARM::R10)
2238 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002239 .Default(0);
2240 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002241 if (!RegNum) {
2242 // Check for aliases registered via .req.
2243 StringMap<unsigned>::const_iterator Entry =
2244 RegisterReqs.find(Tok.getIdentifier());
2245 // If no match, return failure.
2246 if (Entry == RegisterReqs.end())
2247 return -1;
2248 Parser.Lex(); // Eat identifier token.
2249 return Entry->getValue();
2250 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002251
Chris Lattner44e5981c2010-10-30 04:09:10 +00002252 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002253
Chris Lattner44e5981c2010-10-30 04:09:10 +00002254 return RegNum;
2255}
Jim Grosbach99710a82010-11-01 16:44:21 +00002256
Jim Grosbachbb24c592011-07-13 18:49:30 +00002257// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2258// If a recoverable error occurs, return 1. If an irrecoverable error
2259// occurs, return -1. An irrecoverable error is one where tokens have been
2260// consumed in the process of trying to parse the shifter (i.e., when it is
2261// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00002262int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002263 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2264 SMLoc S = Parser.getTok().getLoc();
2265 const AsmToken &Tok = Parser.getTok();
2266 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2267
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002268 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002269 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00002270 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002271 .Case("lsl", ARM_AM::lsl)
2272 .Case("lsr", ARM_AM::lsr)
2273 .Case("asr", ARM_AM::asr)
2274 .Case("ror", ARM_AM::ror)
2275 .Case("rrx", ARM_AM::rrx)
2276 .Default(ARM_AM::no_shift);
2277
2278 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00002279 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002280
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002281 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002282
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002283 // The source register for the shift has already been added to the
2284 // operand list, so we need to pop it off and combine it into the shifted
2285 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00002286 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002287 if (!PrevOp->isReg())
2288 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2289 int SrcReg = PrevOp->getReg();
2290 int64_t Imm = 0;
2291 int ShiftReg = 0;
2292 if (ShiftTy == ARM_AM::rrx) {
2293 // RRX Doesn't have an explicit shift amount. The encoder expects
2294 // the shift register to be the same as the source register. Seems odd,
2295 // but OK.
2296 ShiftReg = SrcReg;
2297 } else {
2298 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00002299 if (Parser.getTok().is(AsmToken::Hash) ||
2300 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002301 Parser.Lex(); // Eat hash.
2302 SMLoc ImmLoc = Parser.getTok().getLoc();
2303 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002304 if (getParser().ParseExpression(ShiftExpr)) {
2305 Error(ImmLoc, "invalid immediate shift value");
2306 return -1;
2307 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002308 // The expression must be evaluatable as an immediate.
2309 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002310 if (!CE) {
2311 Error(ImmLoc, "invalid immediate shift value");
2312 return -1;
2313 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002314 // Range check the immediate.
2315 // lsl, ror: 0 <= imm <= 31
2316 // lsr, asr: 0 <= imm <= 32
2317 Imm = CE->getValue();
2318 if (Imm < 0 ||
2319 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2320 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002321 Error(ImmLoc, "immediate shift value out of range");
2322 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002323 }
2324 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002325 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002326 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002327 if (ShiftReg == -1) {
2328 Error (L, "expected immediate or register in shift operand");
2329 return -1;
2330 }
2331 } else {
2332 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002333 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002334 return -1;
2335 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002336 }
2337
Owen Andersonb595ed02011-07-21 18:54:16 +00002338 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2339 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002340 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002341 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002342 else
2343 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2344 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002345
Jim Grosbachbb24c592011-07-13 18:49:30 +00002346 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002347}
2348
2349
Bill Wendling2063b842010-11-18 23:43:05 +00002350/// Try to parse a register name. The token must be an Identifier when called.
2351/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2352/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002353///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002354/// TODO this is likely to change to allow different register types and or to
2355/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002356bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002357tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002358 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002359 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002360 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002361 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002362
Bill Wendling2063b842010-11-18 23:43:05 +00002363 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002364
Chris Lattner44e5981c2010-10-30 04:09:10 +00002365 const AsmToken &ExclaimTok = Parser.getTok();
2366 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002367 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2368 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002369 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002370 return false;
2371 }
2372
2373 // Also check for an index operand. This is only legal for vector registers,
2374 // but that'll get caught OK in operand matching, so we don't need to
2375 // explicitly filter everything else out here.
2376 if (Parser.getTok().is(AsmToken::LBrac)) {
2377 SMLoc SIdx = Parser.getTok().getLoc();
2378 Parser.Lex(); // Eat left bracket token.
2379
2380 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002381 if (getParser().ParseExpression(ImmVal))
2382 return MatchOperand_ParseFail;
2383 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2384 if (!MCE) {
2385 TokError("immediate value expected for vector index");
2386 return MatchOperand_ParseFail;
2387 }
2388
2389 SMLoc E = Parser.getTok().getLoc();
2390 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2391 Error(E, "']' expected");
2392 return MatchOperand_ParseFail;
2393 }
2394
2395 Parser.Lex(); // Eat right bracket token.
2396
2397 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2398 SIdx, E,
2399 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002400 }
2401
Bill Wendling2063b842010-11-18 23:43:05 +00002402 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002403}
2404
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002405/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2406/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2407/// "c5", ...
2408static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002409 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2410 // but efficient.
2411 switch (Name.size()) {
2412 default: break;
2413 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002414 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002415 return -1;
2416 switch (Name[1]) {
2417 default: return -1;
2418 case '0': return 0;
2419 case '1': return 1;
2420 case '2': return 2;
2421 case '3': return 3;
2422 case '4': return 4;
2423 case '5': return 5;
2424 case '6': return 6;
2425 case '7': return 7;
2426 case '8': return 8;
2427 case '9': return 9;
2428 }
2429 break;
2430 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002431 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002432 return -1;
2433 switch (Name[2]) {
2434 default: return -1;
2435 case '0': return 10;
2436 case '1': return 11;
2437 case '2': return 12;
2438 case '3': return 13;
2439 case '4': return 14;
2440 case '5': return 15;
2441 }
2442 break;
2443 }
2444
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002445 return -1;
2446}
2447
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002448/// parseITCondCode - Try to parse a condition code for an IT instruction.
2449ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2450parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2451 SMLoc S = Parser.getTok().getLoc();
2452 const AsmToken &Tok = Parser.getTok();
2453 if (!Tok.is(AsmToken::Identifier))
2454 return MatchOperand_NoMatch;
2455 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2456 .Case("eq", ARMCC::EQ)
2457 .Case("ne", ARMCC::NE)
2458 .Case("hs", ARMCC::HS)
2459 .Case("cs", ARMCC::HS)
2460 .Case("lo", ARMCC::LO)
2461 .Case("cc", ARMCC::LO)
2462 .Case("mi", ARMCC::MI)
2463 .Case("pl", ARMCC::PL)
2464 .Case("vs", ARMCC::VS)
2465 .Case("vc", ARMCC::VC)
2466 .Case("hi", ARMCC::HI)
2467 .Case("ls", ARMCC::LS)
2468 .Case("ge", ARMCC::GE)
2469 .Case("lt", ARMCC::LT)
2470 .Case("gt", ARMCC::GT)
2471 .Case("le", ARMCC::LE)
2472 .Case("al", ARMCC::AL)
2473 .Default(~0U);
2474 if (CC == ~0U)
2475 return MatchOperand_NoMatch;
2476 Parser.Lex(); // Eat the token.
2477
2478 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2479
2480 return MatchOperand_Success;
2481}
2482
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002483/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002484/// token must be an Identifier when called, and if it is a coprocessor
2485/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002486ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002487parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002488 SMLoc S = Parser.getTok().getLoc();
2489 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002490 if (Tok.isNot(AsmToken::Identifier))
2491 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002492
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002493 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002494 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002495 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002496
2497 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002498 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002499 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002500}
2501
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002502/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002503/// token must be an Identifier when called, and if it is a coprocessor
2504/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002505ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002506parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002507 SMLoc S = Parser.getTok().getLoc();
2508 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002509 if (Tok.isNot(AsmToken::Identifier))
2510 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002511
2512 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2513 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002514 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002515
2516 Parser.Lex(); // Eat identifier token.
2517 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002518 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002519}
2520
Jim Grosbach48399582011-10-12 17:34:41 +00002521/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2522/// coproc_option : '{' imm0_255 '}'
2523ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2524parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2525 SMLoc S = Parser.getTok().getLoc();
2526
2527 // If this isn't a '{', this isn't a coprocessor immediate operand.
2528 if (Parser.getTok().isNot(AsmToken::LCurly))
2529 return MatchOperand_NoMatch;
2530 Parser.Lex(); // Eat the '{'
2531
2532 const MCExpr *Expr;
2533 SMLoc Loc = Parser.getTok().getLoc();
2534 if (getParser().ParseExpression(Expr)) {
2535 Error(Loc, "illegal expression");
2536 return MatchOperand_ParseFail;
2537 }
2538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2539 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2540 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2541 return MatchOperand_ParseFail;
2542 }
2543 int Val = CE->getValue();
2544
2545 // Check for and consume the closing '}'
2546 if (Parser.getTok().isNot(AsmToken::RCurly))
2547 return MatchOperand_ParseFail;
2548 SMLoc E = Parser.getTok().getLoc();
2549 Parser.Lex(); // Eat the '}'
2550
2551 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2552 return MatchOperand_Success;
2553}
2554
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002555// For register list parsing, we need to map from raw GPR register numbering
2556// to the enumeration values. The enumeration values aren't sorted by
2557// register number due to our using "sp", "lr" and "pc" as canonical names.
2558static unsigned getNextRegister(unsigned Reg) {
2559 // If this is a GPR, we need to do it manually, otherwise we can rely
2560 // on the sort ordering of the enumeration since the other reg-classes
2561 // are sane.
2562 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2563 return Reg + 1;
2564 switch(Reg) {
2565 default: assert(0 && "Invalid GPR number!");
2566 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2567 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2568 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2569 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2570 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2571 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2572 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2573 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2574 }
2575}
2576
Jim Grosbach85a23432011-11-11 21:27:40 +00002577// Return the low-subreg of a given Q register.
2578static unsigned getDRegFromQReg(unsigned QReg) {
2579 switch (QReg) {
2580 default: llvm_unreachable("expected a Q register!");
2581 case ARM::Q0: return ARM::D0;
2582 case ARM::Q1: return ARM::D2;
2583 case ARM::Q2: return ARM::D4;
2584 case ARM::Q3: return ARM::D6;
2585 case ARM::Q4: return ARM::D8;
2586 case ARM::Q5: return ARM::D10;
2587 case ARM::Q6: return ARM::D12;
2588 case ARM::Q7: return ARM::D14;
2589 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00002590 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00002591 case ARM::Q10: return ARM::D20;
2592 case ARM::Q11: return ARM::D22;
2593 case ARM::Q12: return ARM::D24;
2594 case ARM::Q13: return ARM::D26;
2595 case ARM::Q14: return ARM::D28;
2596 case ARM::Q15: return ARM::D30;
2597 }
2598}
2599
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002600/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002601bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002602parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002603 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002604 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002605 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002606 Parser.Lex(); // Eat '{' token.
2607 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002608
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002609 // Check the first register in the list to see what register class
2610 // this is a list of.
2611 int Reg = tryParseRegister();
2612 if (Reg == -1)
2613 return Error(RegLoc, "register expected");
2614
Jim Grosbach85a23432011-11-11 21:27:40 +00002615 // The reglist instructions have at most 16 registers, so reserve
2616 // space for that many.
2617 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2618
2619 // Allow Q regs and just interpret them as the two D sub-registers.
2620 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2621 Reg = getDRegFromQReg(Reg);
2622 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2623 ++Reg;
2624 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002625 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002626 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2627 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2628 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2629 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2630 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2631 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2632 else
2633 return Error(RegLoc, "invalid register in register list");
2634
Jim Grosbach85a23432011-11-11 21:27:40 +00002635 // Store the register.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002636 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002637
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002638 // This starts immediately after the first register token in the list,
2639 // so we can see either a comma or a minus (range separator) as a legal
2640 // next token.
2641 while (Parser.getTok().is(AsmToken::Comma) ||
2642 Parser.getTok().is(AsmToken::Minus)) {
2643 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00002644 Parser.Lex(); // Eat the minus.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002645 SMLoc EndLoc = Parser.getTok().getLoc();
2646 int EndReg = tryParseRegister();
2647 if (EndReg == -1)
2648 return Error(EndLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002649 // Allow Q regs and just interpret them as the two D sub-registers.
2650 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2651 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002652 // If the register is the same as the start reg, there's nothing
2653 // more to do.
2654 if (Reg == EndReg)
2655 continue;
2656 // The register must be in the same register class as the first.
2657 if (!RC->contains(EndReg))
2658 return Error(EndLoc, "invalid register in register list");
2659 // Ranges must go from low to high.
2660 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2661 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002662
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002663 // Add all the registers in the range to the register list.
2664 while (Reg != EndReg) {
2665 Reg = getNextRegister(Reg);
2666 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2667 }
2668 continue;
2669 }
2670 Parser.Lex(); // Eat the comma.
2671 RegLoc = Parser.getTok().getLoc();
2672 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00002673 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002674 Reg = tryParseRegister();
2675 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002676 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00002677 // Allow Q regs and just interpret them as the two D sub-registers.
2678 bool isQReg = false;
2679 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2680 Reg = getDRegFromQReg(Reg);
2681 isQReg = true;
2682 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002683 // The register must be in the same register class as the first.
2684 if (!RC->contains(Reg))
2685 return Error(RegLoc, "invalid register in register list");
2686 // List must be monotonically increasing.
Jim Grosbach98bc7972011-12-08 21:34:20 +00002687 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002688 return Error(RegLoc, "register list not in ascending order");
Jim Grosbach98bc7972011-12-08 21:34:20 +00002689 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2690 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2691 ") in register list");
2692 continue;
2693 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002694 // VFP register lists must also be contiguous.
2695 // It's OK to use the enumeration values directly here rather, as the
2696 // VFP register classes have the enum sorted properly.
2697 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2698 Reg != OldReg + 1)
2699 return Error(RegLoc, "non-contiguous register range");
2700 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbach85a23432011-11-11 21:27:40 +00002701 if (isQReg)
2702 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002703 }
2704
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002705 SMLoc E = Parser.getTok().getLoc();
2706 if (Parser.getTok().isNot(AsmToken::RCurly))
2707 return Error(E, "'}' expected");
2708 Parser.Lex(); // Eat '}' token.
2709
Jim Grosbach18bf3632011-12-13 21:48:29 +00002710 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00002711 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00002712
2713 // The ARM system instruction variants for LDM/STM have a '^' token here.
2714 if (Parser.getTok().is(AsmToken::Caret)) {
2715 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2716 Parser.Lex(); // Eat '^' token.
2717 }
2718
Bill Wendling2063b842010-11-18 23:43:05 +00002719 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002720}
2721
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002722// Helper function to parse the lane index for vector lists.
2723ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach04945c42011-12-02 00:35:16 +00002724parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2725 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002726 if (Parser.getTok().is(AsmToken::LBrac)) {
2727 Parser.Lex(); // Eat the '['.
2728 if (Parser.getTok().is(AsmToken::RBrac)) {
2729 // "Dn[]" is the 'all lanes' syntax.
2730 LaneKind = AllLanes;
2731 Parser.Lex(); // Eat the ']'.
2732 return MatchOperand_Success;
2733 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002734 if (Parser.getTok().is(AsmToken::Integer)) {
2735 int64_t Val = Parser.getTok().getIntVal();
2736 // Make this range check context sensitive for .8, .16, .32.
2737 if (Val < 0 && Val > 7)
2738 Error(Parser.getTok().getLoc(), "lane index out of range");
2739 Index = Val;
2740 LaneKind = IndexedLane;
2741 Parser.Lex(); // Eat the token;
2742 if (Parser.getTok().isNot(AsmToken::RBrac))
2743 Error(Parser.getTok().getLoc(), "']' expected");
2744 Parser.Lex(); // Eat the ']'.
2745 return MatchOperand_Success;
2746 }
2747 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002748 return MatchOperand_ParseFail;
2749 }
2750 LaneKind = NoLanes;
2751 return MatchOperand_Success;
2752}
2753
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002754// parse a vector register list
2755ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2756parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002757 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002758 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00002759 SMLoc S = Parser.getTok().getLoc();
2760 // As an extension (to match gas), support a plain D register or Q register
2761 // (without encosing curly braces) as a single or double entry list,
2762 // respectively.
2763 if (Parser.getTok().is(AsmToken::Identifier)) {
2764 int Reg = tryParseRegister();
2765 if (Reg == -1)
2766 return MatchOperand_NoMatch;
2767 SMLoc E = Parser.getTok().getLoc();
2768 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach04945c42011-12-02 00:35:16 +00002769 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002770 if (Res != MatchOperand_Success)
2771 return Res;
2772 switch (LaneKind) {
2773 default:
2774 assert(0 && "unexpected lane kind!");
2775 case NoLanes:
2776 E = Parser.getTok().getLoc();
2777 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2778 break;
2779 case AllLanes:
2780 E = Parser.getTok().getLoc();
2781 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2782 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002783 case IndexedLane:
2784 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2785 LaneIndex, S,E));
2786 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002787 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002788 return MatchOperand_Success;
2789 }
2790 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2791 Reg = getDRegFromQReg(Reg);
Jim Grosbach04945c42011-12-02 00:35:16 +00002792 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002793 if (Res != MatchOperand_Success)
2794 return Res;
2795 switch (LaneKind) {
2796 default:
2797 assert(0 && "unexpected lane kind!");
2798 case NoLanes:
2799 E = Parser.getTok().getLoc();
2800 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2801 break;
2802 case AllLanes:
2803 E = Parser.getTok().getLoc();
2804 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2805 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002806 case IndexedLane:
2807 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2808 LaneIndex, S,E));
2809 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002810 }
Jim Grosbach8d579232011-11-15 21:45:55 +00002811 return MatchOperand_Success;
2812 }
2813 Error(S, "vector register expected");
2814 return MatchOperand_ParseFail;
2815 }
2816
2817 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002818 return MatchOperand_NoMatch;
2819
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002820 Parser.Lex(); // Eat '{' token.
2821 SMLoc RegLoc = Parser.getTok().getLoc();
2822
2823 int Reg = tryParseRegister();
2824 if (Reg == -1) {
2825 Error(RegLoc, "register expected");
2826 return MatchOperand_ParseFail;
2827 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002828 unsigned Count = 1;
Jim Grosbach080a4992011-10-28 00:06:50 +00002829 unsigned FirstReg = Reg;
2830 // The list is of D registers, but we also allow Q regs and just interpret
2831 // them as the two D sub-registers.
2832 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2833 FirstReg = Reg = getDRegFromQReg(Reg);
2834 ++Reg;
2835 ++Count;
2836 }
Jim Grosbach04945c42011-12-02 00:35:16 +00002837 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002838 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00002839
Jim Grosbache891fe82011-11-15 23:19:15 +00002840 while (Parser.getTok().is(AsmToken::Comma) ||
2841 Parser.getTok().is(AsmToken::Minus)) {
2842 if (Parser.getTok().is(AsmToken::Minus)) {
2843 Parser.Lex(); // Eat the minus.
2844 SMLoc EndLoc = Parser.getTok().getLoc();
2845 int EndReg = tryParseRegister();
2846 if (EndReg == -1) {
2847 Error(EndLoc, "register expected");
2848 return MatchOperand_ParseFail;
2849 }
2850 // Allow Q regs and just interpret them as the two D sub-registers.
2851 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2852 EndReg = getDRegFromQReg(EndReg) + 1;
2853 // If the register is the same as the start reg, there's nothing
2854 // more to do.
2855 if (Reg == EndReg)
2856 continue;
2857 // The register must be in the same register class as the first.
2858 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2859 Error(EndLoc, "invalid register in register list");
2860 return MatchOperand_ParseFail;
2861 }
2862 // Ranges must go from low to high.
2863 if (Reg > EndReg) {
2864 Error(EndLoc, "bad range in register list");
2865 return MatchOperand_ParseFail;
2866 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002867 // Parse the lane specifier if present.
2868 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002869 unsigned NextLaneIndex;
2870 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002871 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002872 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002873 Error(EndLoc, "mismatched lane index in register list");
2874 return MatchOperand_ParseFail;
2875 }
2876 EndLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00002877
2878 // Add all the registers in the range to the register list.
2879 Count += EndReg - Reg;
2880 Reg = EndReg;
2881 continue;
2882 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002883 Parser.Lex(); // Eat the comma.
2884 RegLoc = Parser.getTok().getLoc();
2885 int OldReg = Reg;
2886 Reg = tryParseRegister();
2887 if (Reg == -1) {
2888 Error(RegLoc, "register expected");
2889 return MatchOperand_ParseFail;
2890 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002891 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002892 // It's OK to use the enumeration values directly here rather, as the
2893 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00002894 //
2895 // The list is of D registers, but we also allow Q regs and just interpret
2896 // them as the two D sub-registers.
2897 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2898 Reg = getDRegFromQReg(Reg);
2899 if (Reg != OldReg + 1) {
2900 Error(RegLoc, "non-contiguous register range");
2901 return MatchOperand_ParseFail;
2902 }
2903 ++Reg;
2904 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002905 // Parse the lane specifier if present.
2906 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002907 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002908 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002909 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002910 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002911 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002912 Error(EndLoc, "mismatched lane index in register list");
2913 return MatchOperand_ParseFail;
2914 }
Jim Grosbach080a4992011-10-28 00:06:50 +00002915 continue;
2916 }
2917 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002918 if (Reg != OldReg + 1) {
2919 Error(RegLoc, "non-contiguous register range");
2920 return MatchOperand_ParseFail;
2921 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002922 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002923 // Parse the lane specifier if present.
2924 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00002925 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002926 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach04945c42011-12-02 00:35:16 +00002927 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002928 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00002929 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002930 Error(EndLoc, "mismatched lane index in register list");
2931 return MatchOperand_ParseFail;
2932 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002933 }
2934
2935 SMLoc E = Parser.getTok().getLoc();
2936 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2937 Error(E, "'}' expected");
2938 return MatchOperand_ParseFail;
2939 }
2940 Parser.Lex(); // Eat '}' token.
2941
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002942 switch (LaneKind) {
2943 default:
2944 assert(0 && "unexpected lane kind in register list.");
2945 case NoLanes:
2946 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2947 break;
2948 case AllLanes:
2949 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2950 S, E));
2951 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002952 case IndexedLane:
2953 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2954 LaneIndex, S, E));
2955 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002956 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002957 return MatchOperand_Success;
2958}
2959
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002960/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002961ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002962parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002963 SMLoc S = Parser.getTok().getLoc();
2964 const AsmToken &Tok = Parser.getTok();
2965 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2966 StringRef OptStr = Tok.getString();
2967
2968 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2969 .Case("sy", ARM_MB::SY)
2970 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002971 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002972 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002973 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002974 .Case("ishst", ARM_MB::ISHST)
2975 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002976 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002977 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002978 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002979 .Case("osh", ARM_MB::OSH)
2980 .Case("oshst", ARM_MB::OSHST)
2981 .Default(~0U);
2982
2983 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002984 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002985
2986 Parser.Lex(); // Eat identifier token.
2987 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002988 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002989}
2990
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002991/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002992ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002993parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002994 SMLoc S = Parser.getTok().getLoc();
2995 const AsmToken &Tok = Parser.getTok();
2996 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2997 StringRef IFlagsStr = Tok.getString();
2998
Owen Anderson10c5b122011-10-05 17:16:40 +00002999 // An iflags string of "none" is interpreted to mean that none of the AIF
3000 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003001 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003002 if (IFlagsStr != "none") {
3003 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3004 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3005 .Case("a", ARM_PROC::A)
3006 .Case("i", ARM_PROC::I)
3007 .Case("f", ARM_PROC::F)
3008 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003009
Owen Anderson10c5b122011-10-05 17:16:40 +00003010 // If some specific iflag is already set, it means that some letter is
3011 // present more than once, this is not acceptable.
3012 if (Flag == ~0U || (IFlags & Flag))
3013 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003014
Owen Anderson10c5b122011-10-05 17:16:40 +00003015 IFlags |= Flag;
3016 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003017 }
3018
3019 Parser.Lex(); // Eat identifier token.
3020 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3021 return MatchOperand_Success;
3022}
3023
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003024/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003025ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003026parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003027 SMLoc S = Parser.getTok().getLoc();
3028 const AsmToken &Tok = Parser.getTok();
3029 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3030 StringRef Mask = Tok.getString();
3031
James Molloy21efa7d2011-09-28 14:21:38 +00003032 if (isMClass()) {
3033 // See ARMv6-M 10.1.1
3034 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3035 .Case("apsr", 0)
3036 .Case("iapsr", 1)
3037 .Case("eapsr", 2)
3038 .Case("xpsr", 3)
3039 .Case("ipsr", 5)
3040 .Case("epsr", 6)
3041 .Case("iepsr", 7)
3042 .Case("msp", 8)
3043 .Case("psp", 9)
3044 .Case("primask", 16)
3045 .Case("basepri", 17)
3046 .Case("basepri_max", 18)
3047 .Case("faultmask", 19)
3048 .Case("control", 20)
3049 .Default(~0U);
3050
3051 if (FlagsVal == ~0U)
3052 return MatchOperand_NoMatch;
3053
3054 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3055 // basepri, basepri_max and faultmask only valid for V7m.
3056 return MatchOperand_NoMatch;
3057
3058 Parser.Lex(); // Eat identifier token.
3059 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3060 return MatchOperand_Success;
3061 }
3062
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003063 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3064 size_t Start = 0, Next = Mask.find('_');
3065 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003066 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003067 if (Next != StringRef::npos)
3068 Flags = Mask.slice(Next+1, Mask.size());
3069
3070 // FlagsVal contains the complete mask:
3071 // 3-0: Mask
3072 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3073 unsigned FlagsVal = 0;
3074
3075 if (SpecReg == "apsr") {
3076 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00003077 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003078 .Case("g", 0x4) // same as CPSR_s
3079 .Case("nzcvqg", 0xc) // same as CPSR_fs
3080 .Default(~0U);
3081
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003082 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003083 if (!Flags.empty())
3084 return MatchOperand_NoMatch;
3085 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00003086 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00003087 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003088 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00003089 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3090 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003091 for (int i = 0, e = Flags.size(); i != e; ++i) {
3092 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3093 .Case("c", 1)
3094 .Case("x", 2)
3095 .Case("s", 4)
3096 .Case("f", 8)
3097 .Default(~0U);
3098
3099 // If some specific flag is already set, it means that some letter is
3100 // present more than once, this is not acceptable.
3101 if (FlagsVal == ~0U || (FlagsVal & Flag))
3102 return MatchOperand_NoMatch;
3103 FlagsVal |= Flag;
3104 }
3105 } else // No match for special register.
3106 return MatchOperand_NoMatch;
3107
Owen Anderson03a173e2011-10-21 18:43:28 +00003108 // Special register without flags is NOT equivalent to "fc" flags.
3109 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3110 // two lines would enable gas compatibility at the expense of breaking
3111 // round-tripping.
3112 //
3113 // if (!FlagsVal)
3114 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003115
3116 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3117 if (SpecReg == "spsr")
3118 FlagsVal |= 16;
3119
3120 Parser.Lex(); // Eat identifier token.
3121 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3122 return MatchOperand_Success;
3123}
3124
Jim Grosbach27c1e252011-07-21 17:23:04 +00003125ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3126parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3127 int Low, int High) {
3128 const AsmToken &Tok = Parser.getTok();
3129 if (Tok.isNot(AsmToken::Identifier)) {
3130 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3131 return MatchOperand_ParseFail;
3132 }
3133 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003134 std::string LowerOp = Op.lower();
3135 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00003136 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3137 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3138 return MatchOperand_ParseFail;
3139 }
3140 Parser.Lex(); // Eat shift type token.
3141
3142 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003143 if (Parser.getTok().isNot(AsmToken::Hash) &&
3144 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00003145 Error(Parser.getTok().getLoc(), "'#' expected");
3146 return MatchOperand_ParseFail;
3147 }
3148 Parser.Lex(); // Eat hash token.
3149
3150 const MCExpr *ShiftAmount;
3151 SMLoc Loc = Parser.getTok().getLoc();
3152 if (getParser().ParseExpression(ShiftAmount)) {
3153 Error(Loc, "illegal expression");
3154 return MatchOperand_ParseFail;
3155 }
3156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3157 if (!CE) {
3158 Error(Loc, "constant expression expected");
3159 return MatchOperand_ParseFail;
3160 }
3161 int Val = CE->getValue();
3162 if (Val < Low || Val > High) {
3163 Error(Loc, "immediate value out of range");
3164 return MatchOperand_ParseFail;
3165 }
3166
3167 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3168
3169 return MatchOperand_Success;
3170}
3171
Jim Grosbach0a547702011-07-22 17:44:50 +00003172ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3173parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3174 const AsmToken &Tok = Parser.getTok();
3175 SMLoc S = Tok.getLoc();
3176 if (Tok.isNot(AsmToken::Identifier)) {
3177 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3178 return MatchOperand_ParseFail;
3179 }
3180 int Val = StringSwitch<int>(Tok.getString())
3181 .Case("be", 1)
3182 .Case("le", 0)
3183 .Default(-1);
3184 Parser.Lex(); // Eat the token.
3185
3186 if (Val == -1) {
3187 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3188 return MatchOperand_ParseFail;
3189 }
3190 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3191 getContext()),
3192 S, Parser.getTok().getLoc()));
3193 return MatchOperand_Success;
3194}
3195
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003196/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3197/// instructions. Legal values are:
3198/// lsl #n 'n' in [0,31]
3199/// asr #n 'n' in [1,32]
3200/// n == 32 encoded as n == 0.
3201ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3202parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3203 const AsmToken &Tok = Parser.getTok();
3204 SMLoc S = Tok.getLoc();
3205 if (Tok.isNot(AsmToken::Identifier)) {
3206 Error(S, "shift operator 'asr' or 'lsl' expected");
3207 return MatchOperand_ParseFail;
3208 }
3209 StringRef ShiftName = Tok.getString();
3210 bool isASR;
3211 if (ShiftName == "lsl" || ShiftName == "LSL")
3212 isASR = false;
3213 else if (ShiftName == "asr" || ShiftName == "ASR")
3214 isASR = true;
3215 else {
3216 Error(S, "shift operator 'asr' or 'lsl' expected");
3217 return MatchOperand_ParseFail;
3218 }
3219 Parser.Lex(); // Eat the operator.
3220
3221 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003222 if (Parser.getTok().isNot(AsmToken::Hash) &&
3223 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003224 Error(Parser.getTok().getLoc(), "'#' expected");
3225 return MatchOperand_ParseFail;
3226 }
3227 Parser.Lex(); // Eat hash token.
3228
3229 const MCExpr *ShiftAmount;
3230 SMLoc E = Parser.getTok().getLoc();
3231 if (getParser().ParseExpression(ShiftAmount)) {
3232 Error(E, "malformed shift expression");
3233 return MatchOperand_ParseFail;
3234 }
3235 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3236 if (!CE) {
3237 Error(E, "shift amount must be an immediate");
3238 return MatchOperand_ParseFail;
3239 }
3240
3241 int64_t Val = CE->getValue();
3242 if (isASR) {
3243 // Shift amount must be in [1,32]
3244 if (Val < 1 || Val > 32) {
3245 Error(E, "'asr' shift amount must be in range [1,32]");
3246 return MatchOperand_ParseFail;
3247 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00003248 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3249 if (isThumb() && Val == 32) {
3250 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3251 return MatchOperand_ParseFail;
3252 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00003253 if (Val == 32) Val = 0;
3254 } else {
3255 // Shift amount must be in [1,32]
3256 if (Val < 0 || Val > 31) {
3257 Error(E, "'lsr' shift amount must be in range [0,31]");
3258 return MatchOperand_ParseFail;
3259 }
3260 }
3261
3262 E = Parser.getTok().getLoc();
3263 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3264
3265 return MatchOperand_Success;
3266}
3267
Jim Grosbach833b9d32011-07-27 20:15:40 +00003268/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3269/// of instructions. Legal values are:
3270/// ror #n 'n' in {0, 8, 16, 24}
3271ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3272parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3273 const AsmToken &Tok = Parser.getTok();
3274 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00003275 if (Tok.isNot(AsmToken::Identifier))
3276 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003277 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00003278 if (ShiftName != "ror" && ShiftName != "ROR")
3279 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00003280 Parser.Lex(); // Eat the operator.
3281
3282 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003283 if (Parser.getTok().isNot(AsmToken::Hash) &&
3284 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00003285 Error(Parser.getTok().getLoc(), "'#' expected");
3286 return MatchOperand_ParseFail;
3287 }
3288 Parser.Lex(); // Eat hash token.
3289
3290 const MCExpr *ShiftAmount;
3291 SMLoc E = Parser.getTok().getLoc();
3292 if (getParser().ParseExpression(ShiftAmount)) {
3293 Error(E, "malformed rotate expression");
3294 return MatchOperand_ParseFail;
3295 }
3296 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3297 if (!CE) {
3298 Error(E, "rotate amount must be an immediate");
3299 return MatchOperand_ParseFail;
3300 }
3301
3302 int64_t Val = CE->getValue();
3303 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3304 // normally, zero is represented in asm by omitting the rotate operand
3305 // entirely.
3306 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3307 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3308 return MatchOperand_ParseFail;
3309 }
3310
3311 E = Parser.getTok().getLoc();
3312 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3313
3314 return MatchOperand_Success;
3315}
3316
Jim Grosbach864b6092011-07-28 21:34:26 +00003317ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3318parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3319 SMLoc S = Parser.getTok().getLoc();
3320 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003321 if (Parser.getTok().isNot(AsmToken::Hash) &&
3322 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003323 Error(Parser.getTok().getLoc(), "'#' expected");
3324 return MatchOperand_ParseFail;
3325 }
3326 Parser.Lex(); // Eat hash token.
3327
3328 const MCExpr *LSBExpr;
3329 SMLoc E = Parser.getTok().getLoc();
3330 if (getParser().ParseExpression(LSBExpr)) {
3331 Error(E, "malformed immediate expression");
3332 return MatchOperand_ParseFail;
3333 }
3334 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3335 if (!CE) {
3336 Error(E, "'lsb' operand must be an immediate");
3337 return MatchOperand_ParseFail;
3338 }
3339
3340 int64_t LSB = CE->getValue();
3341 // The LSB must be in the range [0,31]
3342 if (LSB < 0 || LSB > 31) {
3343 Error(E, "'lsb' operand must be in the range [0,31]");
3344 return MatchOperand_ParseFail;
3345 }
3346 E = Parser.getTok().getLoc();
3347
3348 // Expect another immediate operand.
3349 if (Parser.getTok().isNot(AsmToken::Comma)) {
3350 Error(Parser.getTok().getLoc(), "too few operands");
3351 return MatchOperand_ParseFail;
3352 }
3353 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003354 if (Parser.getTok().isNot(AsmToken::Hash) &&
3355 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00003356 Error(Parser.getTok().getLoc(), "'#' expected");
3357 return MatchOperand_ParseFail;
3358 }
3359 Parser.Lex(); // Eat hash token.
3360
3361 const MCExpr *WidthExpr;
3362 if (getParser().ParseExpression(WidthExpr)) {
3363 Error(E, "malformed immediate expression");
3364 return MatchOperand_ParseFail;
3365 }
3366 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3367 if (!CE) {
3368 Error(E, "'width' operand must be an immediate");
3369 return MatchOperand_ParseFail;
3370 }
3371
3372 int64_t Width = CE->getValue();
3373 // The LSB must be in the range [1,32-lsb]
3374 if (Width < 1 || Width > 32 - LSB) {
3375 Error(E, "'width' operand must be in the range [1,32-lsb]");
3376 return MatchOperand_ParseFail;
3377 }
3378 E = Parser.getTok().getLoc();
3379
3380 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3381
3382 return MatchOperand_Success;
3383}
3384
Jim Grosbachd3595712011-08-03 23:50:40 +00003385ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3386parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3387 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00003388 // postidx_reg := '+' register {, shift}
3389 // | '-' register {, shift}
3390 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00003391
3392 // This method must return MatchOperand_NoMatch without consuming any tokens
3393 // in the case where there is no match, as other alternatives take other
3394 // parse methods.
3395 AsmToken Tok = Parser.getTok();
3396 SMLoc S = Tok.getLoc();
3397 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003398 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003399 int Reg = -1;
3400 if (Tok.is(AsmToken::Plus)) {
3401 Parser.Lex(); // Eat the '+' token.
3402 haveEaten = true;
3403 } else if (Tok.is(AsmToken::Minus)) {
3404 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00003405 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00003406 haveEaten = true;
3407 }
3408 if (Parser.getTok().is(AsmToken::Identifier))
3409 Reg = tryParseRegister();
3410 if (Reg == -1) {
3411 if (!haveEaten)
3412 return MatchOperand_NoMatch;
3413 Error(Parser.getTok().getLoc(), "register expected");
3414 return MatchOperand_ParseFail;
3415 }
3416 SMLoc E = Parser.getTok().getLoc();
3417
Jim Grosbachc320c852011-08-05 21:28:30 +00003418 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3419 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003420 if (Parser.getTok().is(AsmToken::Comma)) {
3421 Parser.Lex(); // Eat the ','.
3422 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3423 return MatchOperand_ParseFail;
3424 }
Jim Grosbachc320c852011-08-05 21:28:30 +00003425
3426 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3427 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003428
3429 return MatchOperand_Success;
3430}
3431
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003432ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3433parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3434 // Check for a post-index addressing register operand. Specifically:
3435 // am3offset := '+' register
3436 // | '-' register
3437 // | register
3438 // | # imm
3439 // | # + imm
3440 // | # - imm
3441
3442 // This method must return MatchOperand_NoMatch without consuming any tokens
3443 // in the case where there is no match, as other alternatives take other
3444 // parse methods.
3445 AsmToken Tok = Parser.getTok();
3446 SMLoc S = Tok.getLoc();
3447
3448 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003449 if (Parser.getTok().is(AsmToken::Hash) ||
3450 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00003451 Parser.Lex(); // Eat the '#'.
3452 // Explicitly look for a '-', as we need to encode negative zero
3453 // differently.
3454 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3455 const MCExpr *Offset;
3456 if (getParser().ParseExpression(Offset))
3457 return MatchOperand_ParseFail;
3458 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3459 if (!CE) {
3460 Error(S, "constant expression expected");
3461 return MatchOperand_ParseFail;
3462 }
3463 SMLoc E = Tok.getLoc();
3464 // Negative zero is encoded as the flag value INT32_MIN.
3465 int32_t Val = CE->getValue();
3466 if (isNegative && Val == 0)
3467 Val = INT32_MIN;
3468
3469 Operands.push_back(
3470 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3471
3472 return MatchOperand_Success;
3473 }
3474
3475
3476 bool haveEaten = false;
3477 bool isAdd = true;
3478 int Reg = -1;
3479 if (Tok.is(AsmToken::Plus)) {
3480 Parser.Lex(); // Eat the '+' token.
3481 haveEaten = true;
3482 } else if (Tok.is(AsmToken::Minus)) {
3483 Parser.Lex(); // Eat the '-' token.
3484 isAdd = false;
3485 haveEaten = true;
3486 }
3487 if (Parser.getTok().is(AsmToken::Identifier))
3488 Reg = tryParseRegister();
3489 if (Reg == -1) {
3490 if (!haveEaten)
3491 return MatchOperand_NoMatch;
3492 Error(Parser.getTok().getLoc(), "register expected");
3493 return MatchOperand_ParseFail;
3494 }
3495 SMLoc E = Parser.getTok().getLoc();
3496
3497 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3498 0, S, E));
3499
3500 return MatchOperand_Success;
3501}
3502
Jim Grosbach7db8d692011-09-08 22:07:06 +00003503/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3504/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3505/// when they refer multiple MIOperands inside a single one.
3506bool ARMAsmParser::
3507cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3508 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3509 // Rt, Rt2
3510 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3511 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3512 // Create a writeback register dummy placeholder.
3513 Inst.addOperand(MCOperand::CreateReg(0));
3514 // addr
3515 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3516 // pred
3517 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3518 return true;
3519}
3520
3521/// cvtT2StrdPre - Convert parsed operands to MCInst.
3522/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3523/// when they refer multiple MIOperands inside a single one.
3524bool ARMAsmParser::
3525cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3526 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3527 // Create a writeback register dummy placeholder.
3528 Inst.addOperand(MCOperand::CreateReg(0));
3529 // Rt, Rt2
3530 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3531 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3532 // addr
3533 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3534 // pred
3535 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3536 return true;
3537}
3538
Jim Grosbachc086f682011-09-08 00:39:19 +00003539/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3540/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3541/// when they refer multiple MIOperands inside a single one.
3542bool ARMAsmParser::
3543cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3544 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3545 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3546
3547 // Create a writeback register dummy placeholder.
3548 Inst.addOperand(MCOperand::CreateImm(0));
3549
3550 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3551 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3552 return true;
3553}
3554
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00003555/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3556/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3557/// when they refer multiple MIOperands inside a single one.
3558bool ARMAsmParser::
3559cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3560 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3561 // Create a writeback register dummy placeholder.
3562 Inst.addOperand(MCOperand::CreateImm(0));
3563 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3564 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3565 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3566 return true;
3567}
3568
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003569/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003570/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3571/// when they refer multiple MIOperands inside a single one.
3572bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003573cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003574 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3575 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3576
3577 // Create a writeback register dummy placeholder.
3578 Inst.addOperand(MCOperand::CreateImm(0));
3579
Jim Grosbachd3595712011-08-03 23:50:40 +00003580 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003581 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3582 return true;
3583}
3584
Owen Anderson16d33f32011-08-26 20:43:14 +00003585/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3586/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3587/// when they refer multiple MIOperands inside a single one.
3588bool ARMAsmParser::
3589cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3590 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3591 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3592
3593 // Create a writeback register dummy placeholder.
3594 Inst.addOperand(MCOperand::CreateImm(0));
3595
3596 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3597 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3598 return true;
3599}
3600
3601
Jim Grosbachd564bf32011-08-11 19:22:40 +00003602/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3603/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3604/// when they refer multiple MIOperands inside a single one.
3605bool ARMAsmParser::
3606cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3607 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3608 // Create a writeback register dummy placeholder.
3609 Inst.addOperand(MCOperand::CreateImm(0));
3610 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3611 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3612 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3613 return true;
3614}
3615
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003616/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003617/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3618/// when they refer multiple MIOperands inside a single one.
3619bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003620cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003621 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3622 // Create a writeback register dummy placeholder.
3623 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003624 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3625 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3626 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003627 return true;
3628}
3629
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003630/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3631/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3632/// when they refer multiple MIOperands inside a single one.
3633bool ARMAsmParser::
3634cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3635 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3636 // Create a writeback register dummy placeholder.
3637 Inst.addOperand(MCOperand::CreateImm(0));
3638 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3639 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3640 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3641 return true;
3642}
3643
Jim Grosbachd3595712011-08-03 23:50:40 +00003644/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3645/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3646/// when they refer multiple MIOperands inside a single one.
3647bool ARMAsmParser::
3648cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3649 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3650 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003651 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003652 // Create a writeback register dummy placeholder.
3653 Inst.addOperand(MCOperand::CreateImm(0));
3654 // addr
3655 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3656 // offset
3657 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3658 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003659 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3660 return true;
3661}
3662
Jim Grosbachd3595712011-08-03 23:50:40 +00003663/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003664/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3665/// when they refer multiple MIOperands inside a single one.
3666bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003667cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3668 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3669 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003670 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003671 // Create a writeback register dummy placeholder.
3672 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003673 // addr
3674 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3675 // offset
3676 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3677 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003678 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3679 return true;
3680}
3681
Jim Grosbachd3595712011-08-03 23:50:40 +00003682/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003683/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3684/// when they refer multiple MIOperands inside a single one.
3685bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003686cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3687 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003688 // Create a writeback register dummy placeholder.
3689 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003690 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003691 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003692 // addr
3693 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3694 // offset
3695 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3696 // pred
3697 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3698 return true;
3699}
3700
3701/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3702/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3703/// when they refer multiple MIOperands inside a single one.
3704bool ARMAsmParser::
3705cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3706 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3707 // Create a writeback register dummy placeholder.
3708 Inst.addOperand(MCOperand::CreateImm(0));
3709 // Rt
3710 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3711 // addr
3712 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3713 // offset
3714 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3715 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003716 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3717 return true;
3718}
3719
Jim Grosbach5b96b802011-08-10 20:29:19 +00003720/// cvtLdrdPre - Convert parsed operands to MCInst.
3721/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3722/// when they refer multiple MIOperands inside a single one.
3723bool ARMAsmParser::
3724cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3725 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3726 // Rt, Rt2
3727 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3728 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3729 // Create a writeback register dummy placeholder.
3730 Inst.addOperand(MCOperand::CreateImm(0));
3731 // addr
3732 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3733 // pred
3734 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3735 return true;
3736}
3737
Jim Grosbacheb09f492011-08-11 20:28:23 +00003738/// cvtStrdPre - Convert parsed operands to MCInst.
3739/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3740/// when they refer multiple MIOperands inside a single one.
3741bool ARMAsmParser::
3742cvtStrdPre(MCInst &Inst, unsigned Opcode,
3743 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3744 // Create a writeback register dummy placeholder.
3745 Inst.addOperand(MCOperand::CreateImm(0));
3746 // Rt, Rt2
3747 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3748 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3749 // addr
3750 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3751 // pred
3752 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3753 return true;
3754}
3755
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003756/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3757/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3758/// when they refer multiple MIOperands inside a single one.
3759bool ARMAsmParser::
3760cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3761 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3762 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3763 // Create a writeback register dummy placeholder.
3764 Inst.addOperand(MCOperand::CreateImm(0));
3765 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3766 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3767 return true;
3768}
3769
Jim Grosbach8e048492011-08-19 22:07:46 +00003770/// cvtThumbMultiple- Convert parsed operands to MCInst.
3771/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3772/// when they refer multiple MIOperands inside a single one.
3773bool ARMAsmParser::
3774cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3775 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3776 // The second source operand must be the same register as the destination
3777 // operand.
3778 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003779 (((ARMOperand*)Operands[3])->getReg() !=
3780 ((ARMOperand*)Operands[5])->getReg()) &&
3781 (((ARMOperand*)Operands[3])->getReg() !=
3782 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003783 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003784 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003785 return false;
3786 }
3787 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3788 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00003789 // If we have a three-operand form, make sure to set Rn to be the operand
3790 // that isn't the same as Rd.
3791 unsigned RegOp = 4;
3792 if (Operands.size() == 6 &&
3793 ((ARMOperand*)Operands[4])->getReg() ==
3794 ((ARMOperand*)Operands[3])->getReg())
3795 RegOp = 5;
3796 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3797 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003798 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3799
3800 return true;
3801}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003802
Jim Grosbach3ea06572011-10-24 22:16:58 +00003803bool ARMAsmParser::
3804cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3805 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3806 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003807 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003808 // Create a writeback register dummy placeholder.
3809 Inst.addOperand(MCOperand::CreateImm(0));
3810 // Vn
3811 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3812 // pred
3813 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3814 return true;
3815}
3816
3817bool ARMAsmParser::
3818cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3819 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3820 // Vd
Jim Grosbach182b6a02011-11-29 23:51:09 +00003821 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach3ea06572011-10-24 22:16:58 +00003822 // Create a writeback register dummy placeholder.
3823 Inst.addOperand(MCOperand::CreateImm(0));
3824 // Vn
3825 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3826 // Vm
3827 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3828 // pred
3829 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3830 return true;
3831}
3832
Jim Grosbach05df4602011-10-31 21:50:31 +00003833bool ARMAsmParser::
3834cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3835 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3836 // Create a writeback register dummy placeholder.
3837 Inst.addOperand(MCOperand::CreateImm(0));
3838 // Vn
3839 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3840 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003841 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003842 // pred
3843 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3844 return true;
3845}
3846
3847bool ARMAsmParser::
3848cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3849 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3850 // Create a writeback register dummy placeholder.
3851 Inst.addOperand(MCOperand::CreateImm(0));
3852 // Vn
3853 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3854 // Vm
3855 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3856 // Vt
Jim Grosbach182b6a02011-11-29 23:51:09 +00003857 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach05df4602011-10-31 21:50:31 +00003858 // pred
3859 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3860 return true;
3861}
3862
Bill Wendlinge18980a2010-11-06 22:36:58 +00003863/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003864/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003865bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003866parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003867 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003868 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003869 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003870 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003871 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003872
Sean Callanan936b0d32010-01-19 21:44:56 +00003873 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003874 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003875 if (BaseRegNum == -1)
3876 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003877
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003878 // The next token must either be a comma or a closing bracket.
3879 const AsmToken &Tok = Parser.getTok();
3880 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003881 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003882
Jim Grosbachd3595712011-08-03 23:50:40 +00003883 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003884 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003885 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003886
Jim Grosbachd3595712011-08-03 23:50:40 +00003887 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003888 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003889
Jim Grosbach40700e02011-09-19 18:42:21 +00003890 // If there's a pre-indexing writeback marker, '!', just add it as a token
3891 // operand. It's rather odd, but syntactically valid.
3892 if (Parser.getTok().is(AsmToken::Exclaim)) {
3893 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3894 Parser.Lex(); // Eat the '!'.
3895 }
3896
Jim Grosbachd3595712011-08-03 23:50:40 +00003897 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003898 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003899
Jim Grosbachd3595712011-08-03 23:50:40 +00003900 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3901 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003902
Jim Grosbacha95ec992011-10-11 17:29:55 +00003903 // If we have a ':', it's an alignment specifier.
3904 if (Parser.getTok().is(AsmToken::Colon)) {
3905 Parser.Lex(); // Eat the ':'.
3906 E = Parser.getTok().getLoc();
3907
3908 const MCExpr *Expr;
3909 if (getParser().ParseExpression(Expr))
3910 return true;
3911
3912 // The expression has to be a constant. Memory references with relocations
3913 // don't come through here, as they use the <label> forms of the relevant
3914 // instructions.
3915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3916 if (!CE)
3917 return Error (E, "constant expression expected");
3918
3919 unsigned Align = 0;
3920 switch (CE->getValue()) {
3921 default:
3922 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3923 case 64: Align = 8; break;
3924 case 128: Align = 16; break;
3925 case 256: Align = 32; break;
3926 }
3927
3928 // Now we should have the closing ']'
3929 E = Parser.getTok().getLoc();
3930 if (Parser.getTok().isNot(AsmToken::RBrac))
3931 return Error(E, "']' expected");
3932 Parser.Lex(); // Eat right bracket token.
3933
3934 // Don't worry about range checking the value here. That's handled by
3935 // the is*() predicates.
3936 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3937 ARM_AM::no_shift, 0, Align,
3938 false, S, E));
3939
3940 // If there's a pre-indexing writeback marker, '!', just add it as a token
3941 // operand.
3942 if (Parser.getTok().is(AsmToken::Exclaim)) {
3943 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3944 Parser.Lex(); // Eat the '!'.
3945 }
3946
3947 return false;
3948 }
3949
3950 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00003951 // offset. Be friendly and also accept a plain integer (without a leading
3952 // hash) for gas compatibility.
3953 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003954 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00003955 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003956 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach8279c182011-11-15 22:14:41 +00003957 Parser.Lex(); // Eat the '#'.
Jim Grosbachd3595712011-08-03 23:50:40 +00003958 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003959
Owen Anderson967674d2011-08-29 19:36:44 +00003960 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003961 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003962 if (getParser().ParseExpression(Offset))
3963 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003964
3965 // The expression has to be a constant. Memory references with relocations
3966 // don't come through here, as they use the <label> forms of the relevant
3967 // instructions.
3968 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3969 if (!CE)
3970 return Error (E, "constant expression expected");
3971
Owen Anderson967674d2011-08-29 19:36:44 +00003972 // If the constant was #-0, represent it as INT32_MIN.
3973 int32_t Val = CE->getValue();
3974 if (isNegative && Val == 0)
3975 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3976
Jim Grosbachd3595712011-08-03 23:50:40 +00003977 // Now we should have the closing ']'
3978 E = Parser.getTok().getLoc();
3979 if (Parser.getTok().isNot(AsmToken::RBrac))
3980 return Error(E, "']' expected");
3981 Parser.Lex(); // Eat right bracket token.
3982
3983 // Don't worry about range checking the value here. That's handled by
3984 // the is*() predicates.
3985 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003986 ARM_AM::no_shift, 0, 0,
3987 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003988
3989 // If there's a pre-indexing writeback marker, '!', just add it as a token
3990 // operand.
3991 if (Parser.getTok().is(AsmToken::Exclaim)) {
3992 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3993 Parser.Lex(); // Eat the '!'.
3994 }
3995
3996 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003997 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003998
3999 // The register offset is optionally preceded by a '+' or '-'
4000 bool isNegative = false;
4001 if (Parser.getTok().is(AsmToken::Minus)) {
4002 isNegative = true;
4003 Parser.Lex(); // Eat the '-'.
4004 } else if (Parser.getTok().is(AsmToken::Plus)) {
4005 // Nothing to do.
4006 Parser.Lex(); // Eat the '+'.
4007 }
4008
4009 E = Parser.getTok().getLoc();
4010 int OffsetRegNum = tryParseRegister();
4011 if (OffsetRegNum == -1)
4012 return Error(E, "register expected");
4013
4014 // If there's a shift operator, handle it.
4015 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004016 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004017 if (Parser.getTok().is(AsmToken::Comma)) {
4018 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004019 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004020 return true;
4021 }
4022
4023 // Now we should have the closing ']'
4024 E = Parser.getTok().getLoc();
4025 if (Parser.getTok().isNot(AsmToken::RBrac))
4026 return Error(E, "']' expected");
4027 Parser.Lex(); // Eat right bracket token.
4028
4029 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004030 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004031 S, E));
4032
Jim Grosbachc320c852011-08-05 21:28:30 +00004033 // If there's a pre-indexing writeback marker, '!', just add it as a token
4034 // operand.
4035 if (Parser.getTok().is(AsmToken::Exclaim)) {
4036 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4037 Parser.Lex(); // Eat the '!'.
4038 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004039
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004040 return false;
4041}
4042
Jim Grosbachd3595712011-08-03 23:50:40 +00004043/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004044/// ( lsl | lsr | asr | ror ) , # shift_amount
4045/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004046/// return true if it parses a shift otherwise it returns false.
4047bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4048 unsigned &Amount) {
4049 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004050 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004051 if (Tok.isNot(AsmToken::Identifier))
4052 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004053 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004054 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4055 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004056 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004057 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004058 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004059 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004060 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004061 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004062 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004063 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004064 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004065 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004066 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004067 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004068
Jim Grosbachd3595712011-08-03 23:50:40 +00004069 // rrx stands alone.
4070 Amount = 0;
4071 if (St != ARM_AM::rrx) {
4072 Loc = Parser.getTok().getLoc();
4073 // A '#' and a shift amount.
4074 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004075 if (HashTok.isNot(AsmToken::Hash) &&
4076 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004077 return Error(HashTok.getLoc(), "'#' expected");
4078 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004079
Jim Grosbachd3595712011-08-03 23:50:40 +00004080 const MCExpr *Expr;
4081 if (getParser().ParseExpression(Expr))
4082 return true;
4083 // Range check the immediate.
4084 // lsl, ror: 0 <= imm <= 31
4085 // lsr, asr: 0 <= imm <= 32
4086 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4087 if (!CE)
4088 return Error(Loc, "shift amount must be an immediate");
4089 int64_t Imm = CE->getValue();
4090 if (Imm < 0 ||
4091 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4092 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4093 return Error(Loc, "immediate shift value out of range");
4094 Amount = Imm;
4095 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004096
4097 return false;
4098}
4099
Jim Grosbache7fbce72011-10-03 23:38:36 +00004100/// parseFPImm - A floating point immediate expression operand.
4101ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4102parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4103 SMLoc S = Parser.getTok().getLoc();
4104
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004105 if (Parser.getTok().isNot(AsmToken::Hash) &&
4106 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004107 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004108
4109 // Disambiguate the VMOV forms that can accept an FP immediate.
4110 // vmov.f32 <sreg>, #imm
4111 // vmov.f64 <dreg>, #imm
4112 // vmov.f32 <dreg>, #imm @ vector f32x2
4113 // vmov.f32 <qreg>, #imm @ vector f32x4
4114 //
4115 // There are also the NEON VMOV instructions which expect an
4116 // integer constant. Make sure we don't try to parse an FPImm
4117 // for these:
4118 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4119 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4120 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4121 TyOp->getToken() != ".f64"))
4122 return MatchOperand_NoMatch;
4123
Jim Grosbache7fbce72011-10-03 23:38:36 +00004124 Parser.Lex(); // Eat the '#'.
4125
4126 // Handle negation, as that still comes through as a separate token.
4127 bool isNegative = false;
4128 if (Parser.getTok().is(AsmToken::Minus)) {
4129 isNegative = true;
4130 Parser.Lex();
4131 }
4132 const AsmToken &Tok = Parser.getTok();
4133 if (Tok.is(AsmToken::Real)) {
4134 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4135 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4136 // If we had a '-' in front, toggle the sign bit.
4137 IntVal ^= (uint64_t)isNegative << 63;
4138 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4139 Parser.Lex(); // Eat the token.
4140 if (Val == -1) {
4141 TokError("floating point value out of range");
4142 return MatchOperand_ParseFail;
4143 }
4144 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4145 return MatchOperand_Success;
4146 }
4147 if (Tok.is(AsmToken::Integer)) {
4148 int64_t Val = Tok.getIntVal();
4149 Parser.Lex(); // Eat the token.
4150 if (Val > 255 || Val < 0) {
4151 TokError("encoded floating point value out of range");
4152 return MatchOperand_ParseFail;
4153 }
4154 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4155 return MatchOperand_Success;
4156 }
4157
4158 TokError("invalid floating point immediate");
4159 return MatchOperand_ParseFail;
4160}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004161/// Parse a arm instruction operand. For now this parses the operand regardless
4162/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004163bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004164 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004165 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004166
4167 // Check if the current operand has a custom associated parser, if so, try to
4168 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004169 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4170 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004171 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004172 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4173 // there was a match, but an error occurred, in which case, just return that
4174 // the operand parsing failed.
4175 if (ResTy == MatchOperand_ParseFail)
4176 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004177
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004178 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004179 default:
4180 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004181 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004182 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004183 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004184 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00004185 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00004186 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00004187 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004188 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004189 else if (Res == -1) // irrecoverable error
4190 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004191 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4192 S = Parser.getTok().getLoc();
4193 Parser.Lex();
4194 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4195 return false;
4196 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004197
4198 // Fall though for the Identifier case that is not a register or a
4199 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004200 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004201 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004202 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004203 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004204 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004205 // This was not a register so parse other operands that start with an
4206 // identifier (like labels) as expressions and create them as immediates.
4207 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004208 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004209 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004210 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004211 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004212 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4213 return false;
4214 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004215 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004216 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004217 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004218 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004219 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004220 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004221 // #42 -> immediate.
4222 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004223 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004224 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00004225 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004226 const MCExpr *ImmVal;
4227 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004228 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbach7f1f3bd2011-11-01 22:37:37 +00004230 if (CE) {
4231 int32_t Val = CE->getValue();
4232 if (isNegative && Val == 0)
4233 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Andersonf02d98d2011-08-29 17:17:09 +00004234 }
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004235 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004236 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4237 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00004238 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004239 case AsmToken::Colon: {
4240 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00004241 // FIXME: Check it's an expression prefix,
4242 // e.g. (FOO - :lower16:BAR) isn't legal.
4243 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004244 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004245 return true;
4246
Evan Cheng965b3c72011-01-13 07:58:56 +00004247 const MCExpr *SubExprVal;
4248 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00004249 return true;
4250
Evan Cheng965b3c72011-01-13 07:58:56 +00004251 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4252 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00004253 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00004254 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00004255 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004256 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00004257 }
4258}
4259
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004260// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00004261// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004262bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00004263 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004264
4265 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00004266 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00004267 Parser.Lex(); // Eat ':'
4268
4269 if (getLexer().isNot(AsmToken::Identifier)) {
4270 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4271 return true;
4272 }
4273
4274 StringRef IDVal = Parser.getTok().getIdentifier();
4275 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004276 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004277 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00004278 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00004279 } else {
4280 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4281 return true;
4282 }
4283 Parser.Lex();
4284
4285 if (getLexer().isNot(AsmToken::Colon)) {
4286 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4287 return true;
4288 }
4289 Parser.Lex(); // Eat the last ':'
4290 return false;
4291}
4292
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004293/// \brief Given a mnemonic, split out possible predication code and carry
4294/// setting letters to form a canonical mnemonic and flags.
4295//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004296// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004297// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004298StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004299 unsigned &PredicationCode,
4300 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004301 unsigned &ProcessorIMod,
4302 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004303 PredicationCode = ARMCC::AL;
4304 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004305 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004306
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004307 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004308 //
4309 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004310 if ((Mnemonic == "movs" && isThumb()) ||
4311 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4312 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4313 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4314 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4315 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4316 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4317 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004318 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004319
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004320 // First, split out any predication code. Ignore mnemonics we know aren't
4321 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00004322 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00004323 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00004324 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00004325 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00004326 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4327 .Case("eq", ARMCC::EQ)
4328 .Case("ne", ARMCC::NE)
4329 .Case("hs", ARMCC::HS)
4330 .Case("cs", ARMCC::HS)
4331 .Case("lo", ARMCC::LO)
4332 .Case("cc", ARMCC::LO)
4333 .Case("mi", ARMCC::MI)
4334 .Case("pl", ARMCC::PL)
4335 .Case("vs", ARMCC::VS)
4336 .Case("vc", ARMCC::VC)
4337 .Case("hi", ARMCC::HI)
4338 .Case("ls", ARMCC::LS)
4339 .Case("ge", ARMCC::GE)
4340 .Case("lt", ARMCC::LT)
4341 .Case("gt", ARMCC::GT)
4342 .Case("le", ARMCC::LE)
4343 .Case("al", ARMCC::AL)
4344 .Default(~0U);
4345 if (CC != ~0U) {
4346 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4347 PredicationCode = CC;
4348 }
Bill Wendling193961b2010-10-29 23:50:21 +00004349 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004350
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004351 // Next, determine if we have a carry setting bit. We explicitly ignore all
4352 // the instructions we know end in 's'.
4353 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00004354 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00004355 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4356 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4357 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00004358 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00004359 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach2a2348e2011-12-13 20:13:48 +00004360 Mnemonic == "fsts" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00004361 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004362 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4363 CarrySetting = true;
4364 }
4365
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004366 // The "cps" instruction can have a interrupt mode operand which is glued into
4367 // the mnemonic. Check if this is the case, split it and parse the imod op
4368 if (Mnemonic.startswith("cps")) {
4369 // Split out any imod code.
4370 unsigned IMod =
4371 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4372 .Case("ie", ARM_PROC::IE)
4373 .Case("id", ARM_PROC::ID)
4374 .Default(~0U);
4375 if (IMod != ~0U) {
4376 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4377 ProcessorIMod = IMod;
4378 }
4379 }
4380
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004381 // The "it" instruction has the condition mask on the end of the mnemonic.
4382 if (Mnemonic.startswith("it")) {
4383 ITMask = Mnemonic.slice(2, Mnemonic.size());
4384 Mnemonic = Mnemonic.slice(0, 2);
4385 }
4386
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004387 return Mnemonic;
4388}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004389
4390/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4391/// inclusion of carry set or predication code operands.
4392//
4393// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004394void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004395getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00004396 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004397 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4398 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004399 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004400 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004401 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00004402 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004403 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00004404 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00004405 Mnemonic == "mla" || Mnemonic == "smlal" ||
4406 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00004407 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004408 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00004409 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004410
Daniel Dunbar09264122011-01-11 19:06:29 +00004411 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4412 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4413 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4414 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00004415 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4416 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00004417 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00004418 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4419 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4420 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00004421 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4422 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004423 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004424 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004425 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004426 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004427
Jim Grosbach6c45b752011-09-16 16:39:25 +00004428 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004429 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00004430 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00004431 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00004432 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004433}
4434
Jim Grosbach7283da92011-08-16 21:12:37 +00004435bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4436 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004437 // FIXME: This is all horribly hacky. We really need a better way to deal
4438 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00004439
4440 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4441 // another does not. Specifically, the MOVW instruction does not. So we
4442 // special case it here and remove the defaulted (non-setting) cc_out
4443 // operand if that's the instruction we're trying to match.
4444 //
4445 // We do this as post-processing of the explicit operands rather than just
4446 // conditionally adding the cc_out in the first place because we need
4447 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00004448 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00004449 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4450 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4451 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4452 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004453
4454 // Register-register 'add' for thumb does not have a cc_out operand
4455 // when there are only two register operands.
4456 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4457 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4458 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4459 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4460 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004461 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004462 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4463 // have to check the immediate range here since Thumb2 has a variant
4464 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004465 if (((isThumb() && Mnemonic == "add") ||
4466 (isThumbTwo() && Mnemonic == "sub")) &&
4467 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004468 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4469 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4470 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004471 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4472 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4473 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004474 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004475 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4476 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004477 // selecting via the generic "add" mnemonic, so to know that we
4478 // should remove the cc_out operand, we have to explicitly check that
4479 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004480 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4481 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004482 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4483 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4484 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4485 // Nest conditions rather than one big 'if' statement for readability.
4486 //
4487 // If either register is a high reg, it's either one of the SP
4488 // variants (handled above) or a 32-bit encoding, so we just
4489 // check against T3.
4490 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4491 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4492 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4493 return false;
4494 // If both registers are low, we're in an IT block, and the immediate is
4495 // in range, we should use encoding T1 instead, which has a cc_out.
4496 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004497 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004498 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4499 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4500 return false;
4501
4502 // Otherwise, we use encoding T4, which does not have a cc_out
4503 // operand.
4504 return true;
4505 }
4506
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004507 // The thumb2 multiply instruction doesn't have a CCOut register, so
4508 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4509 // use the 16-bit encoding or not.
4510 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4511 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4512 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4513 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4514 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4515 // If the registers aren't low regs, the destination reg isn't the
4516 // same as one of the source regs, or the cc_out operand is zero
4517 // outside of an IT block, we have to use the 32-bit encoding, so
4518 // remove the cc_out operand.
4519 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4520 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach6efa7b92011-11-15 19:29:45 +00004521 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004522 !inITBlock() ||
4523 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4524 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4525 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4526 static_cast<ARMOperand*>(Operands[4])->getReg())))
4527 return true;
4528
Jim Grosbachefa7e952011-11-15 19:55:16 +00004529 // Also check the 'mul' syntax variant that doesn't specify an explicit
4530 // destination register.
4531 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4532 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4533 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4534 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4535 // If the registers aren't low regs or the cc_out operand is zero
4536 // outside of an IT block, we have to use the 32-bit encoding, so
4537 // remove the cc_out operand.
4538 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4539 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4540 !inITBlock()))
4541 return true;
4542
Jim Grosbach9c8b9932011-09-14 21:00:40 +00004543
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004544
Jim Grosbach4b701af2011-08-24 21:42:27 +00004545 // Register-register 'add/sub' for thumb does not have a cc_out operand
4546 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4547 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4548 // right, this will result in better diagnostics (which operand is off)
4549 // anyway.
4550 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4551 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00004552 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4553 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4554 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4555 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00004556
Jim Grosbach7283da92011-08-16 21:12:37 +00004557 return false;
4558}
4559
Jim Grosbach12952fe2011-11-11 23:08:10 +00004560static bool isDataTypeToken(StringRef Tok) {
4561 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4562 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4563 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4564 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4565 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4566 Tok == ".f" || Tok == ".d";
4567}
4568
4569// FIXME: This bit should probably be handled via an explicit match class
4570// in the .td files that matches the suffix instead of having it be
4571// a literal string token the way it is now.
4572static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4573 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4574}
4575
Jim Grosbach8be2f652011-12-09 23:34:09 +00004576static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004577/// Parse an arm instruction mnemonic followed by its operands.
4578bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4579 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach8be2f652011-12-09 23:34:09 +00004580 // Apply mnemonic aliases before doing anything else, as the destination
4581 // mnemnonic may include suffices and we want to handle them normally.
4582 // The generic tblgen'erated code does this later, at the start of
4583 // MatchInstructionImpl(), but that's too late for aliases that include
4584 // any sort of suffix.
4585 unsigned AvailableFeatures = getAvailableFeatures();
4586 applyMnemonicAliases(Name, AvailableFeatures);
4587
Jim Grosbachab5830e2011-12-14 02:16:11 +00004588 // First check for the ARM-specific .req directive.
4589 if (Parser.getTok().is(AsmToken::Identifier) &&
4590 Parser.getTok().getIdentifier() == ".req") {
4591 parseDirectiveReq(Name, NameLoc);
4592 // We always return 'error' for this, as we're done with this
4593 // statement and don't need to match the 'instruction."
4594 return true;
4595 }
4596
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004597 // Create the leading tokens for the mnemonic, split by '.' characters.
4598 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004599 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004600
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004601 // Split out the predication code and carry setting flag from the mnemonic.
4602 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004603 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00004604 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004605 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004606 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004607 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004608
Jim Grosbach1c171b12011-08-25 17:23:55 +00004609 // In Thumb1, only the branch (B) instruction can be predicated.
4610 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4611 Parser.EatToEndOfStatement();
4612 return Error(NameLoc, "conditional execution not supported in Thumb1");
4613 }
4614
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004615 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4616
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004617 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4618 // is the mask as it will be for the IT encoding if the conditional
4619 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4620 // where the conditional bit0 is zero, the instruction post-processing
4621 // will adjust the mask accordingly.
4622 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00004623 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4624 if (ITMask.size() > 3) {
4625 Parser.EatToEndOfStatement();
4626 return Error(Loc, "too many conditions on IT instruction");
4627 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004628 unsigned Mask = 8;
4629 for (unsigned i = ITMask.size(); i != 0; --i) {
4630 char pos = ITMask[i - 1];
4631 if (pos != 't' && pos != 'e') {
4632 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00004633 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004634 }
4635 Mask >>= 1;
4636 if (ITMask[i - 1] == 't')
4637 Mask |= 8;
4638 }
Jim Grosbached16ec42011-08-29 22:24:09 +00004639 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004640 }
4641
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004642 // FIXME: This is all a pretty gross hack. We should automatically handle
4643 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00004644
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004645 // Next, add the CCOut and ConditionCode operands, if needed.
4646 //
4647 // For mnemonics which can ever incorporate a carry setting bit or predication
4648 // code, our matching model involves us always generating CCOut and
4649 // ConditionCode operands to match the mnemonic "as written" and then we let
4650 // the matcher deal with finding the right instruction or generating an
4651 // appropriate error.
4652 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004653 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004654
Jim Grosbach03a8a162011-07-14 22:04:21 +00004655 // If we had a carry-set on an instruction that can't do that, issue an
4656 // error.
4657 if (!CanAcceptCarrySet && CarrySetting) {
4658 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004659 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00004660 "' can not set flags, but 's' suffix specified");
4661 }
Jim Grosbach0a547702011-07-22 17:44:50 +00004662 // If we had a predication code on an instruction that can't do that, issue an
4663 // error.
4664 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4665 Parser.EatToEndOfStatement();
4666 return Error(NameLoc, "instruction '" + Mnemonic +
4667 "' is not predicable, but condition code specified");
4668 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00004669
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004670 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00004671 if (CanAcceptCarrySet) {
4672 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004673 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00004674 Loc));
4675 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004676
4677 // Add the predication code operand, if necessary.
4678 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004679 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4680 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00004681 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00004682 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00004683 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004684
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004685 // Add the processor imod operand, if necessary.
4686 if (ProcessorIMod) {
4687 Operands.push_back(ARMOperand::CreateImm(
4688 MCConstantExpr::Create(ProcessorIMod, getContext()),
4689 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004690 }
4691
Daniel Dunbar188b47b2010-08-11 06:37:20 +00004692 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004693 while (Next != StringRef::npos) {
4694 Start = Next;
4695 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00004696 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004697
Jim Grosbach12952fe2011-11-11 23:08:10 +00004698 // Some NEON instructions have an optional datatype suffix that is
4699 // completely ignored. Check for that.
4700 if (isDataTypeToken(ExtraToken) &&
4701 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4702 continue;
4703
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00004704 if (ExtraToken != ".n") {
4705 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4706 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4707 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00004708 }
4709
4710 // Read the remaining operands.
4711 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004712 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004713 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004714 Parser.EatToEndOfStatement();
4715 return true;
4716 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004717
4718 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00004719 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004720
4721 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004722 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00004723 Parser.EatToEndOfStatement();
4724 return true;
4725 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004726 }
4727 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004728
Chris Lattnera2a9d162010-09-11 16:18:25 +00004729 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004730 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004731 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004732 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004733 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004734
Chris Lattner91689c12010-09-08 05:10:46 +00004735 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004736
Jim Grosbach7283da92011-08-16 21:12:37 +00004737 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4738 // do and don't have a cc_out optional-def operand. With some spot-checks
4739 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004740 // parse and adjust accordingly before actually matching. We shouldn't ever
4741 // try to remove a cc_out operand that was explicitly set on the the
4742 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4743 // table driven matcher doesn't fit well with the ARM instruction set.
4744 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004745 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4746 Operands.erase(Operands.begin() + 1);
4747 delete Op;
4748 }
4749
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004750 // ARM mode 'blx' need special handling, as the register operand version
4751 // is predicable, but the label operand version is not. So, we can't rely
4752 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004753 // a k_CondCode operand in the list. If we're trying to match the label
4754 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004755 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4756 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4757 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4758 Operands.erase(Operands.begin() + 1);
4759 delete Op;
4760 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004761
4762 // The vector-compare-to-zero instructions have a literal token "#0" at
4763 // the end that comes to here as an immediate operand. Convert it to a
4764 // token to play nicely with the matcher.
4765 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4766 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4767 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4768 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4769 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4770 if (CE && CE->getValue() == 0) {
4771 Operands.erase(Operands.begin() + 5);
4772 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4773 delete Op;
4774 }
4775 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004776 // VCMP{E} does the same thing, but with a different operand count.
4777 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4778 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4779 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4780 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4781 if (CE && CE->getValue() == 0) {
4782 Operands.erase(Operands.begin() + 4);
4783 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4784 delete Op;
4785 }
4786 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004787 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004788 // end. Convert it to a token here. Take care not to convert those
4789 // that should hit the Thumb2 encoding.
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004790 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004791 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4792 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004793 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4794 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004796 if (CE && CE->getValue() == 0 &&
4797 (isThumbOne() ||
Jim Grosbach5ac89672011-12-13 21:06:41 +00004798 // The cc_out operand matches the IT block.
4799 ((inITBlock() != CarrySetting) &&
4800 // Neither register operand is a high register.
Jim Grosbach1f1a3592011-12-13 20:50:38 +00004801 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach5ac89672011-12-13 21:06:41 +00004802 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004803 Operands.erase(Operands.begin() + 5);
4804 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4805 delete Op;
4806 }
4807 }
4808
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004809 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004810}
4811
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004812// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004813
4814// return 'true' if register list contains non-low GPR registers,
4815// 'false' otherwise. If Reg is in the register list or is HiReg, set
4816// 'containsReg' to true.
4817static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4818 unsigned HiReg, bool &containsReg) {
4819 containsReg = false;
4820 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4821 unsigned OpReg = Inst.getOperand(i).getReg();
4822 if (OpReg == Reg)
4823 containsReg = true;
4824 // Anything other than a low register isn't legal here.
4825 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4826 return true;
4827 }
4828 return false;
4829}
4830
Jim Grosbacha31f2232011-09-07 18:05:34 +00004831// Check if the specified regisgter is in the register list of the inst,
4832// starting at the indicated operand number.
4833static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4834 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4835 unsigned OpReg = Inst.getOperand(i).getReg();
4836 if (OpReg == Reg)
4837 return true;
4838 }
4839 return false;
4840}
4841
Jim Grosbached16ec42011-08-29 22:24:09 +00004842// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4843// the ARMInsts array) instead. Getting that here requires awkward
4844// API changes, though. Better way?
4845namespace llvm {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004846extern const MCInstrDesc ARMInsts[];
Jim Grosbached16ec42011-08-29 22:24:09 +00004847}
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004848static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004849 return ARMInsts[Opcode];
4850}
4851
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004852// FIXME: We would really like to be able to tablegen'erate this.
4853bool ARMAsmParser::
4854validateInstruction(MCInst &Inst,
4855 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00004856 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00004857 SMLoc Loc = Operands[0]->getStartLoc();
4858 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004859 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4860 // being allowed in IT blocks, but not being predicable. It just always
4861 // executes.
4862 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004863 unsigned bit = 1;
4864 if (ITState.FirstCond)
4865 ITState.FirstCond = false;
4866 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004867 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004868 // The instruction must be predicable.
4869 if (!MCID.isPredicable())
4870 return Error(Loc, "instructions in IT block must be predicable");
4871 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4872 unsigned ITCond = bit ? ITState.Cond :
4873 ARMCC::getOppositeCondition(ITState.Cond);
4874 if (Cond != ITCond) {
4875 // Find the condition code Operand to get its SMLoc information.
4876 SMLoc CondLoc;
4877 for (unsigned i = 1; i < Operands.size(); ++i)
4878 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4879 CondLoc = Operands[i]->getStartLoc();
4880 return Error(CondLoc, "incorrect condition in IT block; got '" +
4881 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4882 "', but expected '" +
4883 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4884 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004885 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004886 } else if (isThumbTwo() && MCID.isPredicable() &&
4887 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004888 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4889 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004890 return Error(Loc, "predicated instructions must be in IT block");
4891
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004892 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004893 case ARM::LDRD:
4894 case ARM::LDRD_PRE:
4895 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004896 case ARM::LDREXD: {
4897 // Rt2 must be Rt + 1.
4898 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4899 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4900 if (Rt2 != Rt + 1)
4901 return Error(Operands[3]->getStartLoc(),
4902 "destination operands must be sequential");
4903 return false;
4904 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004905 case ARM::STRD: {
4906 // Rt2 must be Rt + 1.
4907 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4908 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4909 if (Rt2 != Rt + 1)
4910 return Error(Operands[3]->getStartLoc(),
4911 "source operands must be sequential");
4912 return false;
4913 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004914 case ARM::STRD_PRE:
4915 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004916 case ARM::STREXD: {
4917 // Rt2 must be Rt + 1.
4918 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4919 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4920 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004921 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004922 "source operands must be sequential");
4923 return false;
4924 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004925 case ARM::SBFX:
4926 case ARM::UBFX: {
4927 // width must be in range [1, 32-lsb]
4928 unsigned lsb = Inst.getOperand(2).getImm();
4929 unsigned widthm1 = Inst.getOperand(3).getImm();
4930 if (widthm1 >= 32 - lsb)
4931 return Error(Operands[5]->getStartLoc(),
4932 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004933 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004934 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004935 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004936 // If we're parsing Thumb2, the .w variant is available and handles
4937 // most cases that are normally illegal for a Thumb1 LDM
4938 // instruction. We'll make the transformation in processInstruction()
4939 // if necessary.
4940 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004941 // Thumb LDM instructions are writeback iff the base register is not
4942 // in the register list.
4943 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004944 bool hasWritebackToken =
4945 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4946 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004947 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004948 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004949 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4950 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004951 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004952 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004953 return Error(Operands[2]->getStartLoc(),
4954 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004955 // If we should not have writeback, there must not be a '!'. This is
4956 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004957 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004958 return Error(Operands[3]->getStartLoc(),
4959 "writeback operator '!' not allowed when base register "
4960 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004961
4962 break;
4963 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004964 case ARM::t2LDMIA_UPD: {
4965 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4966 return Error(Operands[4]->getStartLoc(),
4967 "writeback operator '!' not allowed when base register "
4968 "in register list");
4969 break;
4970 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004971 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4972 // so only issue a diagnostic for thumb1. The instructions will be
4973 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004974 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004975 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004976 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4977 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004978 return Error(Operands[2]->getStartLoc(),
4979 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004980 break;
4981 }
4982 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004983 bool listContainsBase;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00004984 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4985 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004986 return Error(Operands[2]->getStartLoc(),
4987 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004988 break;
4989 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004990 case ARM::tSTMIA_UPD: {
4991 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004992 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004993 return Error(Operands[4]->getStartLoc(),
4994 "registers must be in range r0-r7");
4995 break;
4996 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004997 }
4998
4999 return false;
5000}
5001
Jim Grosbacheb538222011-12-02 22:34:51 +00005002static unsigned getRealVSTLNOpcode(unsigned Opc) {
5003 switch(Opc) {
5004 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005005 // VST1LN
5006 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5007 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5008 case ARM::VST1LNdWB_fixed_Asm_U8:
5009 return ARM::VST1LNd8_UPD;
5010 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5011 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5012 case ARM::VST1LNdWB_fixed_Asm_U16:
5013 return ARM::VST1LNd16_UPD;
5014 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5015 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5016 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
5017 return ARM::VST1LNd32_UPD;
5018 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5019 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5020 case ARM::VST1LNdWB_register_Asm_U8:
5021 return ARM::VST1LNd8_UPD;
5022 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5023 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5024 case ARM::VST1LNdWB_register_Asm_U16:
5025 return ARM::VST1LNd16_UPD;
5026 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5027 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5028 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
5029 return ARM::VST1LNd32_UPD;
5030 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5031 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5032 case ARM::VST1LNdAsm_U8:
5033 return ARM::VST1LNd8;
5034 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5035 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5036 case ARM::VST1LNdAsm_U16:
5037 return ARM::VST1LNd16;
5038 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5039 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5040 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
5041 return ARM::VST1LNd32;
5042
5043 // VST2LN
5044 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5045 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5046 case ARM::VST2LNdWB_fixed_Asm_U8:
5047 return ARM::VST2LNd8_UPD;
5048 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5049 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5050 case ARM::VST2LNdWB_fixed_Asm_U16:
5051 return ARM::VST2LNd16_UPD;
5052 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5053 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5054 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5055 return ARM::VST2LNd32_UPD;
5056 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5057 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5058 case ARM::VST2LNdWB_register_Asm_U8:
5059 return ARM::VST2LNd8_UPD;
5060 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5061 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5062 case ARM::VST2LNdWB_register_Asm_U16:
5063 return ARM::VST2LNd16_UPD;
5064 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5065 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5066 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5067 return ARM::VST2LNd32_UPD;
5068 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5069 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5070 case ARM::VST2LNdAsm_U8:
5071 return ARM::VST2LNd8;
5072 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5073 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5074 case ARM::VST2LNdAsm_U16:
5075 return ARM::VST2LNd16;
5076 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5077 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5078 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
5079 return ARM::VST2LNd32;
Jim Grosbacheb538222011-12-02 22:34:51 +00005080 }
5081}
5082
5083static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach04945c42011-12-02 00:35:16 +00005084 switch(Opc) {
5085 default: assert(0 && "unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005086 // VLD1LN
5087 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5088 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5089 case ARM::VLD1LNdWB_fixed_Asm_U8:
5090 return ARM::VLD1LNd8_UPD;
5091 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5092 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5093 case ARM::VLD1LNdWB_fixed_Asm_U16:
5094 return ARM::VLD1LNd16_UPD;
5095 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5096 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5097 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
5098 return ARM::VLD1LNd32_UPD;
5099 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5100 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5101 case ARM::VLD1LNdWB_register_Asm_U8:
5102 return ARM::VLD1LNd8_UPD;
5103 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5104 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5105 case ARM::VLD1LNdWB_register_Asm_U16:
5106 return ARM::VLD1LNd16_UPD;
5107 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5108 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5109 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
5110 return ARM::VLD1LNd32_UPD;
5111 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5112 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5113 case ARM::VLD1LNdAsm_U8:
5114 return ARM::VLD1LNd8;
5115 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5116 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5117 case ARM::VLD1LNdAsm_U16:
5118 return ARM::VLD1LNd16;
5119 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5120 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5121 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
5122 return ARM::VLD1LNd32;
5123
5124 // VLD2LN
5125 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5126 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5127 case ARM::VLD2LNdWB_fixed_Asm_U8:
5128 return ARM::VLD2LNd8_UPD;
5129 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5130 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5131 case ARM::VLD2LNdWB_fixed_Asm_U16:
5132 return ARM::VLD2LNd16_UPD;
5133 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5134 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5135 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
5136 return ARM::VLD2LNd32_UPD;
5137 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5138 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5139 case ARM::VLD2LNdWB_register_Asm_U8:
5140 return ARM::VLD2LNd8_UPD;
5141 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5142 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5143 case ARM::VLD2LNdWB_register_Asm_U16:
5144 return ARM::VLD2LNd16_UPD;
5145 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5146 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5147 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
5148 return ARM::VLD2LNd32_UPD;
5149 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5150 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5151 case ARM::VLD2LNdAsm_U8:
5152 return ARM::VLD2LNd8;
5153 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5154 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5155 case ARM::VLD2LNdAsm_U16:
5156 return ARM::VLD2LNd16;
5157 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5158 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5159 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
5160 return ARM::VLD2LNd32;
Jim Grosbach04945c42011-12-02 00:35:16 +00005161 }
5162}
5163
Jim Grosbachafad0532011-11-10 23:42:14 +00005164bool ARMAsmParser::
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005165processInstruction(MCInst &Inst,
5166 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5167 switch (Inst.getOpcode()) {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005168 // Handle NEON VST complex aliases.
5169 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5170 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5171 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5172 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5173 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5174 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5175 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5176 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005177 MCInst TmpInst;
5178 // Shuffle the operands around so the lane index operand is in the
5179 // right place.
5180 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5181 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5182 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5183 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5184 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5185 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5186 TmpInst.addOperand(Inst.getOperand(1)); // lane
5187 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5188 TmpInst.addOperand(Inst.getOperand(6));
5189 Inst = TmpInst;
5190 return true;
5191 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005192
5193 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5194 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5195 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
5196 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5197 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
5198 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5199 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5200 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32: {
5201 MCInst TmpInst;
5202 // Shuffle the operands around so the lane index operand is in the
5203 // right place.
5204 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5205 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5206 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5207 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5208 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5209 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5210 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5211 TmpInst.addOperand(Inst.getOperand(1)); // lane
5212 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5213 TmpInst.addOperand(Inst.getOperand(6));
5214 Inst = TmpInst;
5215 return true;
5216 }
5217 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5218 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5219 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5220 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5221 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5222 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5223 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5224 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00005225 MCInst TmpInst;
5226 // Shuffle the operands around so the lane index operand is in the
5227 // right place.
5228 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5229 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5230 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5231 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5232 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5233 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5234 TmpInst.addOperand(Inst.getOperand(1)); // lane
5235 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5236 TmpInst.addOperand(Inst.getOperand(5));
5237 Inst = TmpInst;
5238 return true;
5239 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005240
5241 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5242 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5243 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
5244 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5245 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
5246 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5247 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5248 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32: {
5249 MCInst TmpInst;
5250 // Shuffle the operands around so the lane index operand is in the
5251 // right place.
5252 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5253 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5254 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5255 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5256 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5257 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5258 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5259 TmpInst.addOperand(Inst.getOperand(1)); // lane
5260 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5261 TmpInst.addOperand(Inst.getOperand(5));
5262 Inst = TmpInst;
5263 return true;
5264 }
5265 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5266 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5267 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5268 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5269 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbacheb538222011-12-02 22:34:51 +00005270 case ARM::VST1LNdAsm_U32: {
5271 MCInst TmpInst;
5272 // Shuffle the operands around so the lane index operand is in the
5273 // right place.
5274 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5275 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5276 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5277 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5278 TmpInst.addOperand(Inst.getOperand(1)); // lane
5279 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5280 TmpInst.addOperand(Inst.getOperand(5));
5281 Inst = TmpInst;
5282 return true;
5283 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005284
5285 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5286 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
5287 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5288 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5289 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
5290 case ARM::VST2LNdAsm_U32: {
5291 MCInst TmpInst;
5292 // Shuffle the operands around so the lane index operand is in the
5293 // right place.
5294 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5295 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5296 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5297 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5298 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5299 TmpInst.addOperand(Inst.getOperand(1)); // lane
5300 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5301 TmpInst.addOperand(Inst.getOperand(5));
5302 Inst = TmpInst;
5303 return true;
5304 }
5305 // Handle NEON VLD complex aliases.
5306 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5307 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5308 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5309 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5310 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5311 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5312 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5313 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005314 MCInst TmpInst;
5315 // Shuffle the operands around so the lane index operand is in the
5316 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005317 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005318 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5319 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5320 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5321 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5322 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5323 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5324 TmpInst.addOperand(Inst.getOperand(1)); // lane
5325 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5326 TmpInst.addOperand(Inst.getOperand(6));
5327 Inst = TmpInst;
5328 return true;
5329 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005330
5331 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5332 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5333 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
5334 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5335 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
5336 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5337 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5338 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32: {
5339 MCInst TmpInst;
5340 // Shuffle the operands around so the lane index operand is in the
5341 // right place.
5342 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5343 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5344 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5345 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5346 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5347 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5348 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5349 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5350 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5351 TmpInst.addOperand(Inst.getOperand(1)); // lane
5352 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5353 TmpInst.addOperand(Inst.getOperand(6));
5354 Inst = TmpInst;
5355 return true;
5356 }
5357
5358 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5359 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5360 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5361 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5362 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5363 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5364 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5365 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00005366 MCInst TmpInst;
5367 // Shuffle the operands around so the lane index operand is in the
5368 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005369 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbachdda976b2011-12-02 22:01:52 +00005370 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5371 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5372 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5373 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5374 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5375 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5376 TmpInst.addOperand(Inst.getOperand(1)); // lane
5377 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5378 TmpInst.addOperand(Inst.getOperand(5));
5379 Inst = TmpInst;
5380 return true;
5381 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005382
5383 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5384 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5385 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
5386 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5387 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
5388 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5389 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5390 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32: {
5391 MCInst TmpInst;
5392 // Shuffle the operands around so the lane index operand is in the
5393 // right place.
5394 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5395 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5396 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5397 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5398 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5399 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5400 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5401 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5402 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5403 TmpInst.addOperand(Inst.getOperand(1)); // lane
5404 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5405 TmpInst.addOperand(Inst.getOperand(5));
5406 Inst = TmpInst;
5407 return true;
5408 }
5409
5410 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5411 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
5412 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5413 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5414 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbache7dcbc82011-12-02 18:52:30 +00005415 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00005416 MCInst TmpInst;
5417 // Shuffle the operands around so the lane index operand is in the
5418 // right place.
Jim Grosbacheb538222011-12-02 22:34:51 +00005419 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach04945c42011-12-02 00:35:16 +00005420 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5421 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5422 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5423 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5424 TmpInst.addOperand(Inst.getOperand(1)); // lane
5425 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5426 TmpInst.addOperand(Inst.getOperand(5));
5427 Inst = TmpInst;
5428 return true;
5429 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00005430
5431 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5432 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
5433 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5434 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5435 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
5436 case ARM::VLD2LNdAsm_U32: {
5437 MCInst TmpInst;
5438 // Shuffle the operands around so the lane index operand is in the
5439 // right place.
5440 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
5441 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5442 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5443 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5444 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5445 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5446 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg()+1));
5447 TmpInst.addOperand(Inst.getOperand(1)); // lane
5448 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5449 TmpInst.addOperand(Inst.getOperand(5));
5450 Inst = TmpInst;
5451 return true;
5452 }
Jim Grosbach485e5622011-12-13 22:45:11 +00005453 // Handle the Thumb2 mode MOV complex aliases.
5454 case ARM::t2MOVsi:
5455 case ARM::t2MOVSsi: {
5456 // Which instruction to expand to depends on the CCOut operand and
5457 // whether we're in an IT block if the register operands are low
5458 // registers.
5459 bool isNarrow = false;
5460 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5461 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5462 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5463 isNarrow = true;
5464 MCInst TmpInst;
5465 unsigned newOpc;
5466 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5467 default: llvm_unreachable("unexpected opcode!");
5468 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5469 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5470 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5471 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5472 }
5473 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5474 if (Ammount == 32) Ammount = 0;
5475 TmpInst.setOpcode(newOpc);
5476 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5477 if (isNarrow)
5478 TmpInst.addOperand(MCOperand::CreateReg(
5479 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5480 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5481 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5482 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5483 TmpInst.addOperand(Inst.getOperand(4));
5484 if (!isNarrow)
5485 TmpInst.addOperand(MCOperand::CreateReg(
5486 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5487 Inst = TmpInst;
5488 return true;
5489 }
5490 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00005491 case ARM::ASRr:
5492 case ARM::LSRr:
5493 case ARM::LSLr:
5494 case ARM::RORr: {
5495 ARM_AM::ShiftOpc ShiftTy;
5496 switch(Inst.getOpcode()) {
5497 default: llvm_unreachable("unexpected opcode!");
5498 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5499 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5500 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5501 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5502 }
5503 // A shift by zero is a plain MOVr, not a MOVsi.
5504 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5505 MCInst TmpInst;
5506 TmpInst.setOpcode(ARM::MOVsr);
5507 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5508 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5509 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5510 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5511 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5512 TmpInst.addOperand(Inst.getOperand(4));
5513 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5514 Inst = TmpInst;
5515 return true;
5516 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00005517 case ARM::ASRi:
5518 case ARM::LSRi:
5519 case ARM::LSLi:
5520 case ARM::RORi: {
5521 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005522 switch(Inst.getOpcode()) {
5523 default: llvm_unreachable("unexpected opcode!");
5524 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5525 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5526 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5527 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5528 }
5529 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005530 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00005531 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5532 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005533 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00005534 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00005535 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5536 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00005537 if (Opc == ARM::MOVsi)
5538 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00005539 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5540 TmpInst.addOperand(Inst.getOperand(4));
5541 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5542 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005543 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00005544 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00005545 case ARM::RRXi: {
5546 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5547 MCInst TmpInst;
5548 TmpInst.setOpcode(ARM::MOVsi);
5549 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5550 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5551 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5552 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5553 TmpInst.addOperand(Inst.getOperand(3));
5554 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5555 Inst = TmpInst;
5556 return true;
5557 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00005558 case ARM::t2LDMIA_UPD: {
5559 // If this is a load of a single register, then we should use
5560 // a post-indexed LDR instruction instead, per the ARM ARM.
5561 if (Inst.getNumOperands() != 5)
5562 return false;
5563 MCInst TmpInst;
5564 TmpInst.setOpcode(ARM::t2LDR_POST);
5565 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5566 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5567 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5568 TmpInst.addOperand(MCOperand::CreateImm(4));
5569 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5570 TmpInst.addOperand(Inst.getOperand(3));
5571 Inst = TmpInst;
5572 return true;
5573 }
5574 case ARM::t2STMDB_UPD: {
5575 // If this is a store of a single register, then we should use
5576 // a pre-indexed STR instruction instead, per the ARM ARM.
5577 if (Inst.getNumOperands() != 5)
5578 return false;
5579 MCInst TmpInst;
5580 TmpInst.setOpcode(ARM::t2STR_PRE);
5581 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5582 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5583 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5584 TmpInst.addOperand(MCOperand::CreateImm(-4));
5585 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5586 TmpInst.addOperand(Inst.getOperand(3));
5587 Inst = TmpInst;
5588 return true;
5589 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005590 case ARM::LDMIA_UPD:
5591 // If this is a load of a single register via a 'pop', then we should use
5592 // a post-indexed LDR instruction instead, per the ARM ARM.
5593 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5594 Inst.getNumOperands() == 5) {
5595 MCInst TmpInst;
5596 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5597 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5598 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5599 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5600 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5601 TmpInst.addOperand(MCOperand::CreateImm(4));
5602 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5603 TmpInst.addOperand(Inst.getOperand(3));
5604 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005605 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005606 }
5607 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00005608 case ARM::STMDB_UPD:
5609 // If this is a store of a single register via a 'push', then we should use
5610 // a pre-indexed STR instruction instead, per the ARM ARM.
5611 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5612 Inst.getNumOperands() == 5) {
5613 MCInst TmpInst;
5614 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5615 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5616 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5617 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5618 TmpInst.addOperand(MCOperand::CreateImm(-4));
5619 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5620 TmpInst.addOperand(Inst.getOperand(3));
5621 Inst = TmpInst;
5622 }
5623 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00005624 case ARM::t2ADDri12:
5625 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5626 // mnemonic was used (not "addw"), encoding T3 is preferred.
5627 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5628 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5629 break;
5630 Inst.setOpcode(ARM::t2ADDri);
5631 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5632 break;
5633 case ARM::t2SUBri12:
5634 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5635 // mnemonic was used (not "subw"), encoding T3 is preferred.
5636 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5637 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5638 break;
5639 Inst.setOpcode(ARM::t2SUBri);
5640 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5641 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005642 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00005643 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5644 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5645 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5646 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005647 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005648 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005649 return true;
5650 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00005651 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005652 case ARM::tSUBi8:
5653 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5654 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5655 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5656 // to encoding T1 if <Rd> is omitted."
Jim Grosbachafad0532011-11-10 23:42:14 +00005657 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005658 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00005659 return true;
5660 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005661 break;
Jim Grosbache489bab2011-12-05 22:16:39 +00005662 case ARM::t2ADDrr: {
5663 // If the destination and first source operand are the same, and
5664 // there's no setting of the flags, use encoding T2 instead of T3.
5665 // Note that this is only for ADD, not SUB. This mirrors the system
5666 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5667 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5668 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbachb8c719c2011-12-05 22:27:04 +00005669 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5670 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00005671 break;
5672 MCInst TmpInst;
5673 TmpInst.setOpcode(ARM::tADDhirr);
5674 TmpInst.addOperand(Inst.getOperand(0));
5675 TmpInst.addOperand(Inst.getOperand(0));
5676 TmpInst.addOperand(Inst.getOperand(2));
5677 TmpInst.addOperand(Inst.getOperand(3));
5678 TmpInst.addOperand(Inst.getOperand(4));
5679 Inst = TmpInst;
5680 return true;
5681 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005682 case ARM::tB:
5683 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005684 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005685 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005686 return true;
5687 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005688 break;
5689 case ARM::t2B:
5690 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00005691 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005692 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00005693 return true;
5694 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00005695 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00005696 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005697 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00005698 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00005699 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00005700 return true;
5701 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00005702 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005703 case ARM::tBcc:
5704 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00005705 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00005706 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00005707 return true;
5708 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00005709 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005710 case ARM::tLDMIA: {
5711 // If the register list contains any high registers, or if the writeback
5712 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5713 // instead if we're in Thumb2. Otherwise, this should have generated
5714 // an error in validateInstruction().
5715 unsigned Rn = Inst.getOperand(0).getReg();
5716 bool hasWritebackToken =
5717 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5718 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5719 bool listContainsBase;
5720 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5721 (!listContainsBase && !hasWritebackToken) ||
5722 (listContainsBase && hasWritebackToken)) {
5723 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5724 assert (isThumbTwo());
5725 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5726 // If we're switching to the updating version, we need to insert
5727 // the writeback tied operand.
5728 if (hasWritebackToken)
5729 Inst.insert(Inst.begin(),
5730 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00005731 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00005732 }
5733 break;
5734 }
Jim Grosbach099c9762011-09-16 20:50:13 +00005735 case ARM::tSTMIA_UPD: {
5736 // If the register list contains any high registers, we need to use
5737 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5738 // should have generated an error in validateInstruction().
5739 unsigned Rn = Inst.getOperand(0).getReg();
5740 bool listContainsBase;
5741 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5742 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5743 assert (isThumbTwo());
5744 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00005745 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00005746 }
5747 break;
5748 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005749 case ARM::tPOP: {
5750 bool listContainsBase;
5751 // If the register list contains any high registers, we need to use
5752 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5753 // should have generated an error in validateInstruction().
5754 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005755 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005756 assert (isThumbTwo());
5757 Inst.setOpcode(ARM::t2LDMIA_UPD);
5758 // Add the base register and writeback operands.
5759 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5760 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005761 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005762 }
5763 case ARM::tPUSH: {
5764 bool listContainsBase;
5765 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00005766 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005767 assert (isThumbTwo());
5768 Inst.setOpcode(ARM::t2STMDB_UPD);
5769 // Add the base register and writeback operands.
5770 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5771 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00005772 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00005773 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005774 case ARM::t2MOVi: {
5775 // If we can use the 16-bit encoding and the user didn't explicitly
5776 // request the 32-bit variant, transform it here.
5777 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5778 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00005779 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5780 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5781 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005782 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5783 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5784 // The operands aren't in the same order for tMOVi8...
5785 MCInst TmpInst;
5786 TmpInst.setOpcode(ARM::tMOVi8);
5787 TmpInst.addOperand(Inst.getOperand(0));
5788 TmpInst.addOperand(Inst.getOperand(4));
5789 TmpInst.addOperand(Inst.getOperand(1));
5790 TmpInst.addOperand(Inst.getOperand(2));
5791 TmpInst.addOperand(Inst.getOperand(3));
5792 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005793 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005794 }
5795 break;
5796 }
5797 case ARM::t2MOVr: {
5798 // If we can use the 16-bit encoding and the user didn't explicitly
5799 // request the 32-bit variant, transform it here.
5800 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5801 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5802 Inst.getOperand(2).getImm() == ARMCC::AL &&
5803 Inst.getOperand(4).getReg() == ARM::CPSR &&
5804 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5805 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5806 // The operands aren't the same for tMOV[S]r... (no cc_out)
5807 MCInst TmpInst;
5808 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5809 TmpInst.addOperand(Inst.getOperand(0));
5810 TmpInst.addOperand(Inst.getOperand(1));
5811 TmpInst.addOperand(Inst.getOperand(2));
5812 TmpInst.addOperand(Inst.getOperand(3));
5813 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005814 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00005815 }
5816 break;
5817 }
Jim Grosbach82213192011-09-19 20:29:33 +00005818 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00005819 case ARM::t2SXTB:
5820 case ARM::t2UXTH:
5821 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00005822 // If we can use the 16-bit encoding and the user didn't explicitly
5823 // request the 32-bit variant, transform it here.
5824 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5825 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5826 Inst.getOperand(2).getImm() == 0 &&
5827 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5828 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00005829 unsigned NewOpc;
5830 switch (Inst.getOpcode()) {
5831 default: llvm_unreachable("Illegal opcode!");
5832 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5833 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5834 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5835 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5836 }
Jim Grosbach82213192011-09-19 20:29:33 +00005837 // The operands aren't the same for thumb1 (no rotate operand).
5838 MCInst TmpInst;
5839 TmpInst.setOpcode(NewOpc);
5840 TmpInst.addOperand(Inst.getOperand(0));
5841 TmpInst.addOperand(Inst.getOperand(1));
5842 TmpInst.addOperand(Inst.getOperand(3));
5843 TmpInst.addOperand(Inst.getOperand(4));
5844 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00005845 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00005846 }
5847 break;
5848 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005849 case ARM::t2IT: {
5850 // The mask bits for all but the first condition are represented as
5851 // the low bit of the condition code value implies 't'. We currently
5852 // always have 1 implies 't', so XOR toggle the bits if the low bit
5853 // of the condition code is zero. The encoding also expects the low
5854 // bit of the condition to be encoded as bit 4 of the mask operand,
5855 // so mask that in if needed
5856 MCOperand &MO = Inst.getOperand(1);
5857 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00005858 unsigned OrigMask = Mask;
5859 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005860 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005861 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5862 for (unsigned i = 3; i != TZ; --i)
5863 Mask ^= 1 << i;
5864 } else
5865 Mask |= 0x10;
5866 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00005867
5868 // Set up the IT block state according to the IT instruction we just
5869 // matched.
5870 assert(!inITBlock() && "nested IT blocks?!");
5871 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5872 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5873 ITState.CurPosition = 0;
5874 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005875 break;
5876 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005877 }
Jim Grosbachafad0532011-11-10 23:42:14 +00005878 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005879}
5880
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005881unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5882 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5883 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005884 unsigned Opc = Inst.getOpcode();
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00005885 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005886 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5887 assert(MCID.hasOptionalDef() &&
5888 "optionally flag setting instruction missing optional def operand");
5889 assert(MCID.NumOperands == Inst.getNumOperands() &&
5890 "operand count mismatch!");
5891 // Find the optional-def operand (cc_out).
5892 unsigned OpNo;
5893 for (OpNo = 0;
5894 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5895 ++OpNo)
5896 ;
5897 // If we're parsing Thumb1, reject it completely.
5898 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5899 return Match_MnemonicFail;
5900 // If we're parsing Thumb2, which form is legal depends on whether we're
5901 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005902 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5903 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005904 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00005905 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5906 inITBlock())
5907 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005908 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005909 // Some high-register supporting Thumb1 encodings only allow both registers
5910 // to be from r0-r7 when in Thumb2.
5911 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5912 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5913 isARMLowRegister(Inst.getOperand(2).getReg()))
5914 return Match_RequiresThumb2;
5915 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00005916 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005917 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5918 isARMLowRegister(Inst.getOperand(1).getReg()))
5919 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005920 return Match_Success;
5921}
5922
Chris Lattner9487de62010-10-28 21:28:01 +00005923bool ARMAsmParser::
5924MatchAndEmitInstruction(SMLoc IDLoc,
5925 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5926 MCStreamer &Out) {
5927 MCInst Inst;
5928 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00005929 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00005930 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00005931 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00005932 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005933 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005934 // Context sensitive operand constraints aren't handled by the matcher,
5935 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005936 if (validateInstruction(Inst, Operands)) {
5937 // Still progress the IT block, otherwise one wrong condition causes
5938 // nasty cascading errors.
5939 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005940 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005941 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005942
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005943 // Some instructions need post-processing to, for example, tweak which
Jim Grosbachafad0532011-11-10 23:42:14 +00005944 // encoding is selected. Loop on it while changes happen so the
5945 // individual transformations can chain off each other. E.g.,
5946 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5947 while (processInstruction(Inst, Operands))
5948 ;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00005949
Jim Grosbacha0d34d32011-09-02 23:22:08 +00005950 // Only move forward at the very end so that everything in validate
5951 // and process gets a consistent answer about whether we're in an IT
5952 // block.
5953 forwardITPosition();
5954
Chris Lattner9487de62010-10-28 21:28:01 +00005955 Out.EmitInstruction(Inst);
5956 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005957 case Match_MissingFeature:
5958 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5959 return true;
5960 case Match_InvalidOperand: {
5961 SMLoc ErrorLoc = IDLoc;
5962 if (ErrorInfo != ~0U) {
5963 if (ErrorInfo >= Operands.size())
5964 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00005965
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005966 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5967 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5968 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005969
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005970 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00005971 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005972 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005973 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00005974 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00005975 // The converter function will have already emited a diagnostic.
5976 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00005977 case Match_RequiresNotITBlock:
5978 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00005979 case Match_RequiresITBlock:
5980 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00005981 case Match_RequiresV6:
5982 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5983 case Match_RequiresThumb2:
5984 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00005985 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005986
Eric Christopher91d7b902010-10-29 09:26:59 +00005987 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00005988 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00005989}
5990
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005991/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00005992bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5993 StringRef IDVal = DirectiveID.getIdentifier();
5994 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005995 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00005996 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005997 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00005998 else if (IDVal == ".arm")
5999 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006000 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006001 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006002 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006003 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00006004 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006005 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00006006 else if (IDVal == ".unreq")
6007 return parseDirectiveUnreq(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00006008 return true;
6009}
6010
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006011/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00006012/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006013bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00006014 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6015 for (;;) {
6016 const MCExpr *Value;
6017 if (getParser().ParseExpression(Value))
6018 return true;
6019
Chris Lattnerc35681b2010-01-19 19:46:13 +00006020 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00006021
6022 if (getLexer().is(AsmToken::EndOfStatement))
6023 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00006024
Kevin Enderbyccab3172009-09-15 00:27:25 +00006025 // FIXME: Improve diagnostic.
6026 if (getLexer().isNot(AsmToken::Comma))
6027 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006028 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006029 }
6030 }
6031
Sean Callanana83fd7d2010-01-19 20:27:46 +00006032 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006033 return false;
6034}
6035
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006036/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00006037/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006038bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00006039 if (getLexer().isNot(AsmToken::EndOfStatement))
6040 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006041 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006042
Jim Grosbach7f882392011-12-07 18:04:19 +00006043 if (!isThumb())
6044 SwitchMode();
6045 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6046 return false;
6047}
6048
6049/// parseDirectiveARM
6050/// ::= .arm
6051bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6052 if (getLexer().isNot(AsmToken::EndOfStatement))
6053 return Error(L, "unexpected token in directive");
6054 Parser.Lex();
6055
6056 if (isThumb())
6057 SwitchMode();
6058 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006059 return false;
6060}
6061
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006062/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00006063/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006064bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006065 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6066 bool isMachO = MAI.hasSubsectionsViaSymbols();
6067 StringRef Name;
6068
6069 // Darwin asm has function name after .thumb_func direction
6070 // ELF doesn't
6071 if (isMachO) {
6072 const AsmToken &Tok = Parser.getTok();
6073 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6074 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbach42ba6282011-11-10 20:48:53 +00006075 Name = Tok.getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006076 Parser.Lex(); // Consume the identifier token.
6077 }
6078
Jim Grosbach42ba6282011-11-10 20:48:53 +00006079 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby146dcf22009-10-15 20:48:48 +00006080 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006081 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006082
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006083 // FIXME: assuming function name will be the line following .thumb_func
6084 if (!isMachO) {
Jim Grosbach42ba6282011-11-10 20:48:53 +00006085 Name = Parser.getTok().getIdentifier();
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00006086 }
6087
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00006088 // Mark symbol as a thumb symbol.
6089 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6090 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00006091 return false;
6092}
6093
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006094/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00006095/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006096bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006097 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006098 if (Tok.isNot(AsmToken::Identifier))
6099 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00006100 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00006101 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00006102 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006103 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00006104 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00006105 else
6106 return Error(L, "unrecognized syntax mode in .syntax directive");
6107
6108 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006109 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006110 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006111
6112 // TODO tell the MC streamer the mode
6113 // getParser().getStreamer().Emit???();
6114 return false;
6115}
6116
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006117/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00006118/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00006119bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00006120 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006121 if (Tok.isNot(AsmToken::Integer))
6122 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00006123 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00006124 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006125 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00006126 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00006127 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006128 else
6129 return Error(L, "invalid operand to .code directive");
6130
6131 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00006132 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00006133 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00006134
Evan Cheng284b4672011-07-08 22:36:29 +00006135 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006136 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006137 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006138 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00006139 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00006140 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00006141 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00006142 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00006143 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00006144
Kevin Enderby146dcf22009-10-15 20:48:48 +00006145 return false;
6146}
6147
Jim Grosbachab5830e2011-12-14 02:16:11 +00006148/// parseDirectiveReq
6149/// ::= name .req registername
6150bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6151 Parser.Lex(); // Eat the '.req' token.
6152 unsigned Reg;
6153 SMLoc SRegLoc, ERegLoc;
6154 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6155 Parser.EatToEndOfStatement();
6156 return Error(SRegLoc, "register name expected");
6157 }
6158
6159 // Shouldn't be anything else.
6160 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6161 Parser.EatToEndOfStatement();
6162 return Error(Parser.getTok().getLoc(),
6163 "unexpected input in .req directive.");
6164 }
6165
6166 Parser.Lex(); // Consume the EndOfStatement
6167
6168 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6169 return Error(SRegLoc, "redefinition of '" + Name +
6170 "' does not match original.");
6171
6172 return false;
6173}
6174
6175/// parseDirectiveUneq
6176/// ::= .unreq registername
6177bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6178 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6179 Parser.EatToEndOfStatement();
6180 return Error(L, "unexpected input in .unreq directive.");
6181 }
6182 RegisterReqs.erase(Parser.getTok().getIdentifier());
6183 Parser.Lex(); // Eat the identifier.
6184 return false;
6185}
6186
Sean Callanan643a5572010-04-07 20:29:34 +00006187extern "C" void LLVMInitializeARMAsmLexer();
6188
Kevin Enderby8be42bd2009-10-30 22:55:57 +00006189/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00006190extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00006191 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6192 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00006193 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00006194}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006195
Chris Lattner3e4582a2010-09-06 19:11:01 +00006196#define GET_REGISTER_MATCHER
6197#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00006198#include "ARMGenAsmMatcher.inc"