blob: 752d351837a619dd18bccdee9f51af6fdeb48f45 [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"
Owen Andersona098d152011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000036
Kevin Enderbyccab3172009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000039namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000042
Evan Cheng11424442011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbached16ec42011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbached16ec42011-08-29 22:24:09 +000075
76
Kevin Enderbyccab3172009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyccab3172009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d6022d2011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +000097
Jim Grosbacheab1c0d2011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000103
Evan Cheng4d1ca962011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000107 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000110 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloy21efa7d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng284b4672011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Cheng91111d22011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000123 }
James Molloy21efa7d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000127
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000130
Chris Lattner3e4582a2010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000133
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbach861e49c2011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach48399582011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach2d6ef442011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopescdd20af2011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach27c1e252011-07-21 17:23:04 +0000149 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
150 StringRef Op, int Low, int High);
151 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
152 return parsePKHImm(O, "lsl", 0, 31);
153 }
154 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
155 return parsePKHImm(O, "asr", 1, 32);
156 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach833b9d32011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach864b6092011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachd3595712011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbache7fbce72011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbach7db8d692011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachc086f682011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach9c0b86a2011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson16d33f32011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd564bf32011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd886f8c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachd3595712011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach5b96b802011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheb09f492011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachcd4dd252011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach8e048492011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000200
201 bool validateInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach8ba76c62011-08-11 17:35:48 +0000203 void processInstruction(MCInst &Inst,
204 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach7283da92011-08-16 21:12:37 +0000205 bool shouldOmitCCOutOperand(StringRef Mnemonic,
206 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000207
Kevin Enderbyccab3172009-09-15 00:27:25 +0000208public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000209 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000210 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000211 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000212 Match_RequiresV6,
213 Match_RequiresThumb2
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000214 };
215
Evan Cheng91111d22011-07-09 05:47:46 +0000216 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng11424442011-07-26 00:24:13 +0000217 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000218 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000219
Evan Cheng4d1ca962011-07-08 01:53:10 +0000220 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000221 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000222
223 // Not in an ITBlock to start with.
224 ITState.CurPosition = ~0U;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000225 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000226
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000227 // Implementation of the MCTargetAsmParser interface:
228 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
229 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbachedaa35a2011-07-26 18:25:39 +0000230 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000231 bool ParseDirective(AsmToken DirectiveID);
232
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000233 unsigned checkTargetMatchPredicate(MCInst &Inst);
234
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000235 bool MatchAndEmitInstruction(SMLoc IDLoc,
236 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
237 MCStreamer &Out);
Kevin Enderbyccab3172009-09-15 00:27:25 +0000238};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000239} // end anonymous namespace
240
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000241namespace {
242
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000243/// ARMOperand - Instances of this class represent a parsed ARM machine
244/// instruction.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000245class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000246 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000247 k_CondCode,
248 k_CCOut,
249 k_ITCondMask,
250 k_CoprocNum,
251 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000252 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000253 k_Immediate,
254 k_FPImmediate,
255 k_MemBarrierOpt,
256 k_Memory,
257 k_PostIndexRegister,
258 k_MSRMask,
259 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000260 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000261 k_Register,
262 k_RegisterList,
263 k_DPRRegisterList,
264 k_SPRRegisterList,
265 k_ShiftedRegister,
266 k_ShiftedImmediate,
267 k_ShifterImmediate,
268 k_RotateImmediate,
269 k_BitfieldDescriptor,
270 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000271 } Kind;
272
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000273 SMLoc StartLoc, EndLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000274 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000275
276 union {
277 struct {
Daniel Dunbard8042b72010-08-11 06:36:53 +0000278 ARMCC::CondCodes Val;
279 } CC;
280
281 struct {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000282 unsigned Val;
283 } Cop;
284
285 struct {
Jim Grosbach48399582011-10-12 17:34:41 +0000286 unsigned Val;
287 } CoprocOption;
288
289 struct {
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000290 unsigned Mask:4;
291 } ITMask;
292
293 struct {
294 ARM_MB::MemBOpt Val;
295 } MBOpt;
296
297 struct {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000298 ARM_PROC::IFlags Val;
299 } IFlags;
300
301 struct {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000302 unsigned Val;
303 } MMask;
304
305 struct {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000306 const char *Data;
307 unsigned Length;
308 } Tok;
309
310 struct {
311 unsigned RegNum;
312 } Reg;
313
Bill Wendlingb884a8e2010-11-06 22:19:43 +0000314 struct {
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000315 unsigned Val;
316 } VectorIndex;
317
318 struct {
Kevin Enderbyf5079942009-10-13 22:19:02 +0000319 const MCExpr *Val;
320 } Imm;
Jim Grosbach624bcc72010-10-29 14:46:02 +0000321
Jim Grosbache7fbce72011-10-03 23:38:36 +0000322 struct {
323 unsigned Val; // encoded 8-bit representation
324 } FPImm;
325
Daniel Dunbar2be732a2011-01-10 15:26:21 +0000326 /// Combined record for all forms of ARM address expressions.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000327 struct {
328 unsigned BaseRegNum;
Jim Grosbachd3595712011-08-03 23:50:40 +0000329 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
330 // was specified.
331 const MCConstantExpr *OffsetImm; // Offset immediate value
332 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
333 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbacha95ec992011-10-11 17:29:55 +0000334 unsigned ShiftImm; // shift for OffsetReg.
335 unsigned Alignment; // 0 = no alignment specified
336 // n = alignment in bytes (8, 16, or 32)
Jim Grosbachd3595712011-08-03 23:50:40 +0000337 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbach871dff72011-10-11 15:59:20 +0000338 } Memory;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000339
340 struct {
Jim Grosbachd3595712011-08-03 23:50:40 +0000341 unsigned RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +0000342 bool isAdd;
343 ARM_AM::ShiftOpc ShiftTy;
344 unsigned ShiftImm;
Jim Grosbachd3595712011-08-03 23:50:40 +0000345 } PostIdxReg;
346
347 struct {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000348 bool isASR;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000349 unsigned Imm;
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000350 } ShifterImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000351 struct {
352 ARM_AM::ShiftOpc ShiftTy;
353 unsigned SrcReg;
354 unsigned ShiftReg;
355 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000356 } RegShiftedReg;
Owen Andersonb595ed02011-07-21 18:54:16 +0000357 struct {
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned SrcReg;
360 unsigned ShiftImm;
Jim Grosbachac798e12011-07-25 20:49:51 +0000361 } RegShiftedImm;
Jim Grosbach833b9d32011-07-27 20:15:40 +0000362 struct {
363 unsigned Imm;
364 } RotImm;
Jim Grosbach864b6092011-07-28 21:34:26 +0000365 struct {
366 unsigned LSB;
367 unsigned Width;
368 } Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000369 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000370
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000371 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
372public:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000373 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
374 Kind = o.Kind;
375 StartLoc = o.StartLoc;
376 EndLoc = o.EndLoc;
377 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000378 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000379 CC = o.CC;
380 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000381 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000382 ITMask = o.ITMask;
383 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000384 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000385 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000386 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000387 case k_CCOut:
388 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000389 Reg = o.Reg;
390 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000391 case k_RegisterList:
392 case k_DPRRegisterList:
393 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000394 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000395 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000396 case k_CoprocNum:
397 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000398 Cop = o.Cop;
399 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000400 case k_CoprocOption:
401 CoprocOption = o.CoprocOption;
402 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000403 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000404 Imm = o.Imm;
405 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000406 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +0000407 FPImm = o.FPImm;
408 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000409 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000410 MBOpt = o.MBOpt;
411 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000412 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000413 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000414 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000415 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000416 PostIdxReg = o.PostIdxReg;
417 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000418 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000419 MMask = o.MMask;
420 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000421 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000422 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000423 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000424 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000425 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000426 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000427 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000428 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000429 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000430 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000431 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000432 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000433 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000434 RotImm = o.RotImm;
435 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000436 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000437 Bitfield = o.Bitfield;
438 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000439 case k_VectorIndex:
440 VectorIndex = o.VectorIndex;
441 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000442 }
443 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000444
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000445 /// getStartLoc - Get the location of the first token of this operand.
446 SMLoc getStartLoc() const { return StartLoc; }
447 /// getEndLoc - Get the location of the last token of this operand.
448 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000449
Daniel Dunbard8042b72010-08-11 06:36:53 +0000450 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000451 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000452 return CC.Val;
453 }
454
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000455 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000456 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000457 return Cop.Val;
458 }
459
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000460 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000461 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000462 return StringRef(Tok.Data, Tok.Length);
463 }
464
465 unsigned getReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000466 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000467 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000468 }
469
Bill Wendlingbed94652010-11-09 23:28:44 +0000470 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000471 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
472 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000473 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000474 }
475
Kevin Enderbyf5079942009-10-13 22:19:02 +0000476 const MCExpr *getImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000477 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000478 return Imm.Val;
479 }
480
Jim Grosbache7fbce72011-10-03 23:38:36 +0000481 unsigned getFPImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000482 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbache7fbce72011-10-03 23:38:36 +0000483 return FPImm.Val;
484 }
485
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000486 unsigned getVectorIndex() const {
487 assert(Kind == k_VectorIndex && "Invalid access!");
488 return VectorIndex.Val;
489 }
490
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000491 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000492 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000493 return MBOpt.Val;
494 }
495
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000496 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000497 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000498 return IFlags.Val;
499 }
500
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000501 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000502 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000503 return MMask.Val;
504 }
505
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000506 bool isCoprocNum() const { return Kind == k_CoprocNum; }
507 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000508 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000509 bool isCondCode() const { return Kind == k_CondCode; }
510 bool isCCOut() const { return Kind == k_CCOut; }
511 bool isITMask() const { return Kind == k_ITCondMask; }
512 bool isITCondCode() const { return Kind == k_CondCode; }
513 bool isImm() const { return Kind == k_Immediate; }
514 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000515 bool isImm8s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000516 if (Kind != k_Immediate)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000517 return false;
518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
519 if (!CE) return false;
520 int64_t Value = CE->getValue();
521 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
522 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000523 bool isImm0_1020s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000524 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000525 return false;
526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
527 if (!CE) return false;
528 int64_t Value = CE->getValue();
529 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
530 }
531 bool isImm0_508s4() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000532 if (Kind != k_Immediate)
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000533 return false;
534 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
535 if (!CE) return false;
536 int64_t Value = CE->getValue();
537 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
538 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000539 bool isImm0_255() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000540 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000541 return false;
542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
543 if (!CE) return false;
544 int64_t Value = CE->getValue();
545 return Value >= 0 && Value < 256;
546 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000547 bool isImm0_7() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000548 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +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 >= 0 && Value < 8;
554 }
555 bool isImm0_15() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000556 if (Kind != k_Immediate)
Jim Grosbach31756c22011-07-13 22:01:08 +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 >= 0 && Value < 16;
562 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000563 bool isImm0_31() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000564 if (Kind != k_Immediate)
Jim Grosbach72e7c4f2011-07-21 23:26:25 +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 >= 0 && Value < 32;
570 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000571 bool isImm1_16() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000572 if (Kind != k_Immediate)
Jim Grosbach475c6db2011-07-25 23:09:14 +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 < 17;
578 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000579 bool isImm1_32() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000580 if (Kind != k_Immediate)
Jim Grosbach801e0a32011-07-22 23:16:18 +0000581 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 < 33;
586 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000587 bool isImm0_65535() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000588 if (Kind != k_Immediate)
Jim Grosbach975b6412011-07-13 20:10:10 +0000589 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 < 65536;
594 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000595 bool isImm0_65535Expr() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000596 if (Kind != k_Immediate)
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000597 return false;
598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 // If it's not a constant expression, it'll generate a fixup and be
600 // handled later.
601 if (!CE) return true;
602 int64_t Value = CE->getValue();
603 return Value >= 0 && Value < 65536;
604 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000605 bool isImm24bit() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbachf1637842011-07-26 16:24:27 +0000607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value <= 0xffffff;
612 }
Jim Grosbach46dd4132011-08-17 21:51:27 +0000613 bool isImmThumbSR() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbach46dd4132011-08-17 21:51:27 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value > 0 && Value < 33;
620 }
Jim Grosbach27c1e252011-07-21 17:23:04 +0000621 bool isPKHLSLImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value >= 0 && Value < 32;
628 }
629 bool isPKHASRImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000630 if (Kind != k_Immediate)
Jim Grosbach27c1e252011-07-21 17:23:04 +0000631 return false;
632 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
633 if (!CE) return false;
634 int64_t Value = CE->getValue();
635 return Value > 0 && Value <= 32;
636 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000637 bool isARMSOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000638 if (Kind != k_Immediate)
Jim Grosbach9720dcf2011-07-19 16:50:30 +0000639 return false;
640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return ARM_AM::getSOImmVal(Value) != -1;
644 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000645 bool isT2SOImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000646 if (Kind != k_Immediate)
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000647 return false;
648 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
649 if (!CE) return false;
650 int64_t Value = CE->getValue();
651 return ARM_AM::getT2SOImmVal(Value) != -1;
652 }
Jim Grosbach0a547702011-07-22 17:44:50 +0000653 bool isSetEndImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000654 if (Kind != k_Immediate)
Jim Grosbach0a547702011-07-22 17:44:50 +0000655 return false;
656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value == 1 || Value == 0;
660 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000661 bool isReg() const { return Kind == k_Register; }
662 bool isRegList() const { return Kind == k_RegisterList; }
663 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
664 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
665 bool isToken() const { return Kind == k_Token; }
666 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
667 bool isMemory() const { return Kind == k_Memory; }
668 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
669 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
670 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
671 bool isRotImm() const { return Kind == k_RotateImmediate; }
672 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
673 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +0000674 bool isPostIdxReg() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000675 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +0000676 }
Jim Grosbacha95ec992011-10-11 17:29:55 +0000677 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachc11b7c32011-10-10 23:06:42 +0000678 if (!isMemory())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000679 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000680 // No offset of any kind.
Jim Grosbacha95ec992011-10-11 17:29:55 +0000681 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
682 (alignOK || Memory.Alignment == 0);
683 }
684 bool isAlignedMemory() const {
685 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000686 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000687 bool isAddrMode2() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000688 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000689 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000690 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +0000691 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000692 if (!Memory.OffsetImm) return true;
693 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +0000694 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +0000695 }
Jim Grosbachcd17c122011-08-04 23:01:30 +0000696 bool isAM2OffsetImm() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000697 if (Kind != k_Immediate)
Jim Grosbachcd17c122011-08-04 23:01:30 +0000698 return false;
699 // Immediate offset in range [-4095, 4095].
700 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
701 if (!CE) return false;
702 int64_t Val = CE->getValue();
703 return Val > -4096 && Val < 4096;
704 }
Jim Grosbach5b96b802011-08-10 20:29:19 +0000705 bool isAddrMode3() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000706 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000707 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +0000708 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000709 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000710 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000711 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000712 if (!Memory.OffsetImm) return true;
713 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5b96b802011-08-10 20:29:19 +0000714 return Val > -256 && Val < 256;
715 }
716 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000717 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000718 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000719 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +0000720 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
721 // Immediate offset in range [-255, 255].
722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
723 if (!CE) return false;
724 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +0000725 // Special case, #-0 is INT32_MIN.
726 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +0000727 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000728 bool isAddrMode5() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000729 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000730 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +0000731 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +0000732 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +0000733 if (!Memory.OffsetImm) return true;
734 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000735 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
736 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +0000737 }
Jim Grosbach05541f42011-09-19 22:21:13 +0000738 bool isMemTBB() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000739 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000740 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +0000741 return false;
742 return true;
743 }
744 bool isMemTBH() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000745 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000746 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
747 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +0000748 return false;
749 return true;
750 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000751 bool isMemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000752 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +0000753 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +0000754 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +0000755 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000756 bool isT2MemRegOffset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000757 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
758 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000759 return false;
760 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +0000761 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000762 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +0000763 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +0000764 return false;
765 return true;
766 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000767 bool isMemThumbRR() const {
768 // Thumb reg+reg addressing is simple. Just two registers, a base and
769 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbach871dff72011-10-11 15:59:20 +0000770 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000771 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +0000772 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +0000773 return isARMLowRegister(Memory.BaseRegNum) &&
774 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000775 }
776 bool isMemThumbRIs4() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000777 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000778 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +0000779 return false;
780 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +0000781 if (!Memory.OffsetImm) return true;
782 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000783 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
784 }
Jim Grosbach26d35872011-08-19 18:55:51 +0000785 bool isMemThumbRIs2() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000786 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000787 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +0000788 return false;
789 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +0000790 if (!Memory.OffsetImm) return true;
791 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +0000792 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
793 }
Jim Grosbacha32c7532011-08-19 18:49:59 +0000794 bool isMemThumbRIs1() const {
Jim Grosbach871dff72011-10-11 15:59:20 +0000795 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +0000796 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +0000797 return false;
798 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +0000799 if (!Memory.OffsetImm) return true;
800 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +0000801 return Val >= 0 && Val <= 31;
802 }
Jim Grosbach23983d62011-08-19 18:13:48 +0000803 bool isMemThumbSPI() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000804 if (!isMemory() || Memory.OffsetRegNum != 0 ||
805 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +0000806 return false;
807 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000808 if (!Memory.OffsetImm) return true;
809 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +0000810 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +0000811 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000812 bool isMemImm8s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000813 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +0000814 return false;
815 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000816 if (!Memory.OffsetImm) return true;
817 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7db8d692011-09-08 22:07:06 +0000818 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
819 }
Jim Grosbacha05627e2011-09-09 18:37:27 +0000820 bool isMemImm0_1020s4Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000821 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +0000822 return false;
823 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +0000824 if (!Memory.OffsetImm) return true;
825 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +0000826 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
827 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000828 bool isMemImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000829 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000830 return false;
831 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000832 if (!Memory.OffsetImm) return true;
833 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +0000834 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +0000835 }
Jim Grosbach2392c532011-09-07 23:39:14 +0000836 bool isMemPosImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000837 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +0000838 return false;
839 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +0000840 if (!Memory.OffsetImm) return true;
841 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +0000842 return Val >= 0 && Val < 256;
843 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000844 bool isMemNegImm8Offset() const {
Jim Grosbacha95ec992011-10-11 17:29:55 +0000845 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000846 return false;
847 // Immediate offset in range [-255, -1].
Jim Grosbach871dff72011-10-11 15:59:20 +0000848 if (!Memory.OffsetImm) return true;
849 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000850 return Val > -256 && Val < 0;
851 }
852 bool isMemUImm12Offset() const {
853 // If we have an immediate that's not a constant, treat it as a label
854 // reference needing a fixup. If it is a constant, it's something else
855 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000856 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000857 return true;
858
Jim Grosbacha95ec992011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000860 return false;
861 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000862 if (!Memory.OffsetImm) return true;
863 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +0000864 return (Val >= 0 && Val < 4096);
865 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000866 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +0000867 // If we have an immediate that's not a constant, treat it as a label
868 // reference needing a fixup. If it is a constant, it's something else
869 // and we reject it.
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000870 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +0000871 return true;
872
Jim Grosbacha95ec992011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +0000874 return false;
875 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +0000876 if (!Memory.OffsetImm) return true;
877 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +0000878 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000879 }
880 bool isPostIdxImm8() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000881 if (Kind != k_Immediate)
Jim Grosbachd3595712011-08-03 23:50:40 +0000882 return false;
883 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
884 if (!CE) return false;
885 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +0000886 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +0000887 }
Jim Grosbach93981412011-10-11 21:55:36 +0000888 bool isPostIdxImm8s4() const {
889 if (Kind != k_Immediate)
890 return false;
891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
892 if (!CE) return false;
893 int64_t Val = CE->getValue();
894 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
895 (Val == INT32_MIN);
896 }
Jim Grosbachd3595712011-08-03 23:50:40 +0000897
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000898 bool isMSRMask() const { return Kind == k_MSRMask; }
899 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000900
Jim Grosbach741cd732011-10-17 22:26:03 +0000901 // NEON operands.
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000902 bool isVectorIndex8() const {
903 if (Kind != k_VectorIndex) return false;
904 return VectorIndex.Val < 8;
905 }
906 bool isVectorIndex16() const {
907 if (Kind != k_VectorIndex) return false;
908 return VectorIndex.Val < 4;
909 }
910 bool isVectorIndex32() const {
911 if (Kind != k_VectorIndex) return false;
912 return VectorIndex.Val < 2;
913 }
914
Jim Grosbach741cd732011-10-17 22:26:03 +0000915 bool isNEONi8splat() const {
916 if (Kind != k_Immediate)
917 return false;
918 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
919 // Must be a constant.
920 if (!CE) return false;
921 int64_t Value = CE->getValue();
922 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
923 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +0000924 return Value >= 0 && Value < 256;
925 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000926
Jim Grosbachcda32ae2011-10-17 23:09:09 +0000927 bool isNEONi16splat() const {
928 if (Kind != k_Immediate)
929 return false;
930 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
931 // Must be a constant.
932 if (!CE) return false;
933 int64_t Value = CE->getValue();
934 // i16 value in the range [0,255] or [0x0100, 0xff00]
935 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
936 }
937
Jim Grosbach8211c052011-10-18 00:22:00 +0000938 bool isNEONi32splat() const {
939 if (Kind != k_Immediate)
940 return false;
941 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
942 // Must be a constant.
943 if (!CE) return false;
944 int64_t Value = CE->getValue();
945 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
946 return (Value >= 0 && Value < 256) ||
947 (Value >= 0x0100 && Value <= 0xff00) ||
948 (Value >= 0x010000 && Value <= 0xff0000) ||
949 (Value >= 0x01000000 && Value <= 0xff000000);
950 }
951
952 bool isNEONi32vmov() const {
953 if (Kind != k_Immediate)
954 return false;
955 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
956 // Must be a constant.
957 if (!CE) return false;
958 int64_t Value = CE->getValue();
959 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
960 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
961 return (Value >= 0 && Value < 256) ||
962 (Value >= 0x0100 && Value <= 0xff00) ||
963 (Value >= 0x010000 && Value <= 0xff0000) ||
964 (Value >= 0x01000000 && Value <= 0xff000000) ||
965 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
966 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
967 }
968
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000969 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +0000970 // Add as immediates when possible. Null MCExpr = 0.
971 if (Expr == 0)
972 Inst.addOperand(MCOperand::CreateImm(0));
973 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000974 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
975 else
976 Inst.addOperand(MCOperand::CreateExpr(Expr));
977 }
978
Daniel Dunbard8042b72010-08-11 06:36:53 +0000979 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +0000980 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000981 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +0000982 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
983 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +0000984 }
985
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000986 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
987 assert(N == 1 && "Invalid number of operands!");
988 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
989 }
990
Jim Grosbach48399582011-10-12 17:34:41 +0000991 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
992 assert(N == 1 && "Invalid number of operands!");
993 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
994 }
995
996 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
997 assert(N == 1 && "Invalid number of operands!");
998 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
999 }
1000
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001001 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1002 assert(N == 1 && "Invalid number of operands!");
1003 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1004 }
1005
1006 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1007 assert(N == 1 && "Invalid number of operands!");
1008 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1009 }
1010
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001011 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1012 assert(N == 1 && "Invalid number of operands!");
1013 Inst.addOperand(MCOperand::CreateReg(getReg()));
1014 }
1015
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001016 void addRegOperands(MCInst &Inst, unsigned N) const {
1017 assert(N == 1 && "Invalid number of operands!");
1018 Inst.addOperand(MCOperand::CreateReg(getReg()));
1019 }
1020
Jim Grosbachac798e12011-07-25 20:49:51 +00001021 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001022 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001023 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1024 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1025 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001026 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001027 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001028 }
1029
Jim Grosbachac798e12011-07-25 20:49:51 +00001030 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001031 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001032 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1033 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Andersonb595ed02011-07-21 18:54:16 +00001034 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001035 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001036 }
1037
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001038 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001039 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001040 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1041 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001042 }
1043
Bill Wendling8d2aa032010-11-08 23:49:57 +00001044 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001045 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001046 const SmallVectorImpl<unsigned> &RegList = getRegList();
1047 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001048 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1049 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001050 }
1051
Bill Wendling9898ac92010-11-17 04:32:08 +00001052 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1053 addRegListOperands(Inst, N);
1054 }
1055
1056 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1057 addRegListOperands(Inst, N);
1058 }
1059
Jim Grosbach833b9d32011-07-27 20:15:40 +00001060 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
1062 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1063 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1064 }
1065
Jim Grosbach864b6092011-07-28 21:34:26 +00001066 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1067 assert(N == 1 && "Invalid number of operands!");
1068 // Munge the lsb/width into a bitfield mask.
1069 unsigned lsb = Bitfield.LSB;
1070 unsigned width = Bitfield.Width;
1071 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1072 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1073 (32 - (lsb + width)));
1074 Inst.addOperand(MCOperand::CreateImm(Mask));
1075 }
1076
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001077 void addImmOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 addExpr(Inst, getImm());
1080 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001081
Jim Grosbache7fbce72011-10-03 23:38:36 +00001082 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1085 }
1086
Jim Grosbach7db8d692011-09-08 22:07:06 +00001087 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 // FIXME: We really want to scale the value here, but the LDRD/STRD
1090 // instruction don't encode operands that way yet.
1091 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1092 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1093 }
1094
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001095 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
1097 // The immediate is scaled by four in the encoding and is stored
1098 // in the MCInst as such. Lop off the low two bits here.
1099 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1100 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1101 }
1102
1103 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1104 assert(N == 1 && "Invalid number of operands!");
1105 // The immediate is scaled by four in the encoding and is stored
1106 // in the MCInst as such. Lop off the low two bits here.
1107 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1108 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1109 }
1110
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001111 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 addExpr(Inst, getImm());
1114 }
1115
Jim Grosbach31756c22011-07-13 22:01:08 +00001116 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 addExpr(Inst, getImm());
1119 }
1120
1121 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 addExpr(Inst, getImm());
1124 }
1125
Jim Grosbach72e7c4f2011-07-21 23:26:25 +00001126 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1127 assert(N == 1 && "Invalid number of operands!");
1128 addExpr(Inst, getImm());
1129 }
1130
Jim Grosbach475c6db2011-07-25 23:09:14 +00001131 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1132 assert(N == 1 && "Invalid number of operands!");
1133 // The constant encodes as the immediate-1, and we store in the instruction
1134 // the bits as encoded, so subtract off one here.
1135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1136 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1137 }
1138
Jim Grosbach801e0a32011-07-22 23:16:18 +00001139 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
1141 // The constant encodes as the immediate-1, and we store in the instruction
1142 // the bits as encoded, so subtract off one here.
1143 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1144 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1145 }
1146
Jim Grosbach975b6412011-07-13 20:10:10 +00001147 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 addExpr(Inst, getImm());
1150 }
1151
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00001152 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 addExpr(Inst, getImm());
1155 }
1156
Jim Grosbachf1637842011-07-26 16:24:27 +00001157 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1158 assert(N == 1 && "Invalid number of operands!");
1159 addExpr(Inst, getImm());
1160 }
1161
Jim Grosbach46dd4132011-08-17 21:51:27 +00001162 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1163 assert(N == 1 && "Invalid number of operands!");
1164 // The constant encodes as the immediate, except for 32, which encodes as
1165 // zero.
1166 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1167 unsigned Imm = CE->getValue();
1168 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1169 }
1170
Jim Grosbach27c1e252011-07-21 17:23:04 +00001171 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1172 assert(N == 1 && "Invalid number of operands!");
1173 addExpr(Inst, getImm());
1174 }
1175
1176 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1179 // the instruction as well.
1180 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1181 int Val = CE->getValue();
1182 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1183 }
1184
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001185 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 addExpr(Inst, getImm());
1188 }
1189
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001190 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
1192 addExpr(Inst, getImm());
1193 }
1194
Jim Grosbach0a547702011-07-22 17:44:50 +00001195 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
1197 addExpr(Inst, getImm());
1198 }
1199
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001200 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
1202 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1203 }
1204
Jim Grosbachd3595712011-08-03 23:50:40 +00001205 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1206 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001207 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00001208 }
1209
Jim Grosbacha95ec992011-10-11 17:29:55 +00001210 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 2 && "Invalid number of operands!");
1212 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1213 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1214 }
1215
Jim Grosbachd3595712011-08-03 23:50:40 +00001216 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1217 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001218 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1219 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00001220 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1221 // Special case for #-0
1222 if (Val == INT32_MIN) Val = 0;
1223 if (Val < 0) Val = -Val;
1224 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1225 } else {
1226 // For register offset, we encode the shift type and negation flag
1227 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001228 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1229 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001230 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001231 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1232 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001233 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001234 }
1235
Jim Grosbachcd17c122011-08-04 23:01:30 +00001236 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 2 && "Invalid number of operands!");
1238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1239 assert(CE && "non-constant AM2OffsetImm operand!");
1240 int32_t Val = CE->getValue();
1241 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1242 // Special case for #-0
1243 if (Val == INT32_MIN) Val = 0;
1244 if (Val < 0) Val = -Val;
1245 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1246 Inst.addOperand(MCOperand::CreateReg(0));
1247 Inst.addOperand(MCOperand::CreateImm(Val));
1248 }
1249
Jim Grosbach5b96b802011-08-10 20:29:19 +00001250 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1251 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001252 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1253 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001254 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1255 // Special case for #-0
1256 if (Val == INT32_MIN) Val = 0;
1257 if (Val < 0) Val = -Val;
1258 Val = ARM_AM::getAM3Opc(AddSub, Val);
1259 } else {
1260 // For register offset, we encode the shift type and negation flag
1261 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00001262 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001263 }
Jim Grosbach871dff72011-10-11 15:59:20 +00001264 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1265 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00001266 Inst.addOperand(MCOperand::CreateImm(Val));
1267 }
1268
1269 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001271 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00001272 int32_t Val =
1273 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1274 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1275 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001276 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001277 }
1278
1279 // Constant offset.
1280 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1281 int32_t Val = CE->getValue();
1282 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1283 // Special case for #-0
1284 if (Val == INT32_MIN) Val = 0;
1285 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001286 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00001287 Inst.addOperand(MCOperand::CreateReg(0));
1288 Inst.addOperand(MCOperand::CreateImm(Val));
1289 }
1290
Jim Grosbachd3595712011-08-03 23:50:40 +00001291 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 2 && "Invalid number of operands!");
1293 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001294 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001295 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1296 // Special case for #-0
1297 if (Val == INT32_MIN) Val = 0;
1298 if (Val < 0) Val = -Val;
1299 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00001300 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001301 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001302 }
1303
Jim Grosbach7db8d692011-09-08 22:07:06 +00001304 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1305 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001306 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1307 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00001308 Inst.addOperand(MCOperand::CreateImm(Val));
1309 }
1310
Jim Grosbacha05627e2011-09-09 18:37:27 +00001311 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1312 assert(N == 2 && "Invalid number of operands!");
1313 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00001314 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1315 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00001316 Inst.addOperand(MCOperand::CreateImm(Val));
1317 }
1318
Jim Grosbachd3595712011-08-03 23:50:40 +00001319 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1320 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001321 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1322 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001323 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001324 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001325
Jim Grosbach2392c532011-09-07 23:39:14 +00001326 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1327 addMemImm8OffsetOperands(Inst, N);
1328 }
1329
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001330 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00001331 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001332 }
1333
1334 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1335 assert(N == 2 && "Invalid number of operands!");
1336 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001337 if (Kind == k_Immediate) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001338 addExpr(Inst, getImm());
1339 Inst.addOperand(MCOperand::CreateImm(0));
1340 return;
1341 }
1342
1343 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001344 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1345 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001346 Inst.addOperand(MCOperand::CreateImm(Val));
1347 }
1348
Jim Grosbachd3595712011-08-03 23:50:40 +00001349 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1350 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00001351 // If this is an immediate, it's a label reference.
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001352 if (Kind == k_Immediate) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001353 addExpr(Inst, getImm());
1354 Inst.addOperand(MCOperand::CreateImm(0));
1355 return;
1356 }
1357
1358 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001359 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1360 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001361 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00001362 }
Bill Wendling811c9362010-11-30 07:44:32 +00001363
Jim Grosbach05541f42011-09-19 22:21:13 +00001364 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001366 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1367 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001368 }
1369
1370 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1371 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001372 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1373 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00001374 }
1375
Jim Grosbachd3595712011-08-03 23:50:40 +00001376 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1377 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001378 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1379 Memory.ShiftImm, Memory.ShiftType);
1380 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1381 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001382 Inst.addOperand(MCOperand::CreateImm(Val));
1383 }
1384
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001385 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001387 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1388 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1389 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001390 }
1391
Jim Grosbachd3595712011-08-03 23:50:40 +00001392 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1393 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001394 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1395 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00001396 }
1397
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001398 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1399 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001400 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1401 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001402 Inst.addOperand(MCOperand::CreateImm(Val));
1403 }
1404
Jim Grosbach26d35872011-08-19 18:55:51 +00001405 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1406 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001407 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1408 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00001409 Inst.addOperand(MCOperand::CreateImm(Val));
1410 }
1411
Jim Grosbacha32c7532011-08-19 18:49:59 +00001412 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1413 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001414 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1415 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00001416 Inst.addOperand(MCOperand::CreateImm(Val));
1417 }
1418
Jim Grosbach23983d62011-08-19 18:13:48 +00001419 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00001421 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1422 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00001423 Inst.addOperand(MCOperand::CreateImm(Val));
1424 }
1425
Jim Grosbachd3595712011-08-03 23:50:40 +00001426 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
1428 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1429 assert(CE && "non-constant post-idx-imm8 operand!");
1430 int Imm = CE->getValue();
1431 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00001432 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00001433 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1434 Inst.addOperand(MCOperand::CreateImm(Imm));
1435 }
1436
Jim Grosbach93981412011-10-11 21:55:36 +00001437 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1438 assert(N == 1 && "Invalid number of operands!");
1439 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1440 assert(CE && "non-constant post-idx-imm8s4 operand!");
1441 int Imm = CE->getValue();
1442 bool isAdd = Imm >= 0;
1443 if (Imm == INT32_MIN) Imm = 0;
1444 // Immediate is scaled by 4.
1445 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1446 Inst.addOperand(MCOperand::CreateImm(Imm));
1447 }
1448
Jim Grosbachd3595712011-08-03 23:50:40 +00001449 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 2 && "Invalid number of operands!");
1451 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00001452 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1453 }
1454
1455 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 2 && "Invalid number of operands!");
1457 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1458 // The sign, shift type, and shift amount are encoded in a single operand
1459 // using the AM2 encoding helpers.
1460 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1461 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1462 PostIdxReg.ShiftTy);
1463 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00001464 }
1465
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001466 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
1468 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1469 }
1470
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001471 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1472 assert(N == 1 && "Invalid number of operands!");
1473 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1474 }
1475
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001476 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1477 assert(N == 1 && "Invalid number of operands!");
1478 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1479 }
1480
1481 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1482 assert(N == 1 && "Invalid number of operands!");
1483 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1484 }
1485
1486 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1487 assert(N == 1 && "Invalid number of operands!");
1488 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1489 }
1490
Jim Grosbach741cd732011-10-17 22:26:03 +00001491 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 // The immediate encodes the type of constant as well as the value.
1494 // Mask in that this is an i8 splat.
1495 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1496 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1497 }
1498
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001499 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 // The immediate encodes the type of constant as well as the value.
1502 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1503 unsigned Value = CE->getValue();
1504 if (Value >= 256)
1505 Value = (Value >> 8) | 0xa00;
1506 else
1507 Value |= 0x800;
1508 Inst.addOperand(MCOperand::CreateImm(Value));
1509 }
1510
Jim Grosbach8211c052011-10-18 00:22:00 +00001511 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1512 assert(N == 1 && "Invalid number of operands!");
1513 // The immediate encodes the type of constant as well as the value.
1514 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1515 unsigned Value = CE->getValue();
1516 if (Value >= 256 && Value <= 0xff00)
1517 Value = (Value >> 8) | 0x200;
1518 else if (Value > 0xffff && Value <= 0xff0000)
1519 Value = (Value >> 16) | 0x400;
1520 else if (Value > 0xffffff)
1521 Value = (Value >> 24) | 0x600;
1522 Inst.addOperand(MCOperand::CreateImm(Value));
1523 }
1524
1525 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 // The immediate encodes the type of constant as well as the value.
1528 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1529 unsigned Value = CE->getValue();
1530 if (Value >= 256 && Value <= 0xffff)
1531 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1532 else if (Value > 0xffff && Value <= 0xffffff)
1533 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1534 else if (Value > 0xffffff)
1535 Value = (Value >> 24) | 0x600;
1536 Inst.addOperand(MCOperand::CreateImm(Value));
1537 }
1538
Jim Grosbach602aa902011-07-13 15:34:57 +00001539 virtual void print(raw_ostream &OS) const;
Daniel Dunbarebace222010-08-11 06:37:04 +00001540
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001541 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001542 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001543 Op->ITMask.Mask = Mask;
1544 Op->StartLoc = S;
1545 Op->EndLoc = S;
1546 return Op;
1547 }
1548
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001549 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001550 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001551 Op->CC.Val = CC;
1552 Op->StartLoc = S;
1553 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001554 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001555 }
1556
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001557 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001558 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001559 Op->Cop.Val = CopVal;
1560 Op->StartLoc = S;
1561 Op->EndLoc = S;
1562 return Op;
1563 }
1564
1565 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001566 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001567 Op->Cop.Val = CopVal;
1568 Op->StartLoc = S;
1569 Op->EndLoc = S;
1570 return Op;
1571 }
1572
Jim Grosbach48399582011-10-12 17:34:41 +00001573 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1574 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1575 Op->Cop.Val = Val;
1576 Op->StartLoc = S;
1577 Op->EndLoc = E;
1578 return Op;
1579 }
1580
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001581 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001582 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001583 Op->Reg.RegNum = RegNum;
1584 Op->StartLoc = S;
1585 Op->EndLoc = S;
1586 return Op;
1587 }
1588
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001589 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001590 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001591 Op->Tok.Data = Str.data();
1592 Op->Tok.Length = Str.size();
1593 Op->StartLoc = S;
1594 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001595 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001596 }
1597
Bill Wendling2063b842010-11-18 23:43:05 +00001598 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001599 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001600 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001601 Op->StartLoc = S;
1602 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001603 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001604 }
1605
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001606 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1607 unsigned SrcReg,
1608 unsigned ShiftReg,
1609 unsigned ShiftImm,
1610 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001611 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00001612 Op->RegShiftedReg.ShiftTy = ShTy;
1613 Op->RegShiftedReg.SrcReg = SrcReg;
1614 Op->RegShiftedReg.ShiftReg = ShiftReg;
1615 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001616 Op->StartLoc = S;
1617 Op->EndLoc = E;
1618 return Op;
1619 }
1620
Owen Andersonb595ed02011-07-21 18:54:16 +00001621 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1622 unsigned SrcReg,
1623 unsigned ShiftImm,
1624 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001625 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00001626 Op->RegShiftedImm.ShiftTy = ShTy;
1627 Op->RegShiftedImm.SrcReg = SrcReg;
1628 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00001629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001634 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001635 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001636 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001637 Op->ShifterImm.isASR = isASR;
1638 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001639 Op->StartLoc = S;
1640 Op->EndLoc = E;
1641 return Op;
1642 }
1643
Jim Grosbach833b9d32011-07-27 20:15:40 +00001644 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001645 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00001646 Op->RotImm.Imm = Imm;
1647 Op->StartLoc = S;
1648 Op->EndLoc = E;
1649 return Op;
1650 }
1651
Jim Grosbach864b6092011-07-28 21:34:26 +00001652 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1653 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001654 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00001655 Op->Bitfield.LSB = LSB;
1656 Op->Bitfield.Width = Width;
1657 Op->StartLoc = S;
1658 Op->EndLoc = E;
1659 return Op;
1660 }
1661
Bill Wendling2cae3272010-11-09 22:44:22 +00001662 static ARMOperand *
Bill Wendlingbed94652010-11-09 23:28:44 +00001663 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001664 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001665 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001666
Jim Grosbach75461af2011-09-13 22:56:44 +00001667 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001668 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00001669 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng9eec7642011-07-25 21:32:49 +00001670 contains(Regs.front().first))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001671 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00001672
1673 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendlingbed94652010-11-09 23:28:44 +00001674 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001675 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling0ab0f672010-11-18 21:50:54 +00001676 Op->Registers.push_back(I->first);
Bill Wendling20b5ea982010-11-19 00:38:19 +00001677 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00001678 Op->StartLoc = StartLoc;
1679 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00001680 return Op;
1681 }
1682
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001683 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1684 MCContext &Ctx) {
1685 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1686 Op->VectorIndex.Val = Idx;
1687 Op->StartLoc = S;
1688 Op->EndLoc = E;
1689 return Op;
1690 }
1691
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001692 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001693 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001694 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001695 Op->StartLoc = S;
1696 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001697 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00001698 }
1699
Jim Grosbache7fbce72011-10-03 23:38:36 +00001700 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001701 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbache7fbce72011-10-03 23:38:36 +00001702 Op->FPImm.Val = Val;
1703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
1707
Jim Grosbachd3595712011-08-03 23:50:40 +00001708 static ARMOperand *CreateMem(unsigned BaseRegNum,
1709 const MCConstantExpr *OffsetImm,
1710 unsigned OffsetRegNum,
1711 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00001712 unsigned ShiftImm,
Jim Grosbacha95ec992011-10-11 17:29:55 +00001713 unsigned Alignment,
Jim Grosbachd3595712011-08-03 23:50:40 +00001714 bool isNegative,
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001715 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001716 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00001717 Op->Memory.BaseRegNum = BaseRegNum;
1718 Op->Memory.OffsetImm = OffsetImm;
1719 Op->Memory.OffsetRegNum = OffsetRegNum;
1720 Op->Memory.ShiftType = ShiftType;
1721 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00001722 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00001723 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00001724 Op->StartLoc = S;
1725 Op->EndLoc = E;
1726 return Op;
1727 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001728
Jim Grosbachc320c852011-08-05 21:28:30 +00001729 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1730 ARM_AM::ShiftOpc ShiftTy,
1731 unsigned ShiftImm,
Jim Grosbachd3595712011-08-03 23:50:40 +00001732 SMLoc S, SMLoc E) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001733 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00001734 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00001735 Op->PostIdxReg.isAdd = isAdd;
1736 Op->PostIdxReg.ShiftTy = ShiftTy;
1737 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00001738 Op->StartLoc = S;
1739 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00001740 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001741 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001742
1743 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001744 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001745 Op->MBOpt.Val = Opt;
1746 Op->StartLoc = S;
1747 Op->EndLoc = S;
1748 return Op;
1749 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001750
1751 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001752 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001753 Op->IFlags.Val = IFlags;
1754 Op->StartLoc = S;
1755 Op->EndLoc = S;
1756 return Op;
1757 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001758
1759 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001760 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001761 Op->MMask.Val = MMask;
1762 Op->StartLoc = S;
1763 Op->EndLoc = S;
1764 return Op;
1765 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001766};
1767
1768} // end anonymous namespace.
1769
Jim Grosbach602aa902011-07-13 15:34:57 +00001770void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001771 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001772 case k_FPImmediate:
Jim Grosbache7fbce72011-10-03 23:38:36 +00001773 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1774 << ") >";
1775 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001776 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00001777 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001778 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001779 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001780 OS << "<ccout " << getReg() << ">";
1781 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001782 case k_ITCondMask: {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001783 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1784 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1785 "(tee)", "(eee)" };
1786 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1787 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1788 break;
1789 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001790 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001791 OS << "<coprocessor number: " << getCoproc() << ">";
1792 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001793 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001794 OS << "<coprocessor register: " << getCoproc() << ">";
1795 break;
Jim Grosbach48399582011-10-12 17:34:41 +00001796 case k_CoprocOption:
1797 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1798 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001799 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00001800 OS << "<mask: " << getMSRMask() << ">";
1801 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001802 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001803 getImm()->print(OS);
1804 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001805 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00001806 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1807 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001808 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001809 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00001810 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00001811 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001812 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001813 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00001814 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1815 << PostIdxReg.RegNum;
1816 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1817 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1818 << PostIdxReg.ShiftImm;
1819 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00001820 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001821 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00001822 OS << "<ARM_PROC::";
1823 unsigned IFlags = getProcIFlags();
1824 for (int i=2; i >= 0; --i)
1825 if (IFlags & (1 << i))
1826 OS << ARM_PROC::IFlagsToString(1 << i);
1827 OS << ">";
1828 break;
1829 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001830 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00001831 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001832 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001833 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001834 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1835 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001836 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001837 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00001838 OS << "<so_reg_reg "
Jim Grosbachac798e12011-07-25 20:49:51 +00001839 << RegShiftedReg.SrcReg
1840 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1841 << ", " << RegShiftedReg.ShiftReg << ", "
1842 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001843 << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001844 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001845 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00001846 OS << "<so_reg_imm "
Jim Grosbachac798e12011-07-25 20:49:51 +00001847 << RegShiftedImm.SrcReg
1848 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1849 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Andersonb595ed02011-07-21 18:54:16 +00001850 << ">";
1851 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001852 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00001853 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1854 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001855 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00001856 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1857 << ", width: " << Bitfield.Width << ">";
1858 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001859 case k_RegisterList:
1860 case k_DPRRegisterList:
1861 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00001862 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001863
Bill Wendlingbed94652010-11-09 23:28:44 +00001864 const SmallVectorImpl<unsigned> &RegList = getRegList();
1865 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001866 I = RegList.begin(), E = RegList.end(); I != E; ) {
1867 OS << *I;
1868 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00001869 }
1870
1871 OS << ">";
1872 break;
1873 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001874 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001875 OS << "'" << getToken() << "'";
1876 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001877 case k_VectorIndex:
1878 OS << "<vectorindex " << getVectorIndex() << ">";
1879 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00001880 }
1881}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001882
1883/// @name Auto-generated Match Functions
1884/// {
1885
1886static unsigned MatchRegisterName(StringRef Name);
1887
1888/// }
1889
Bob Wilsonfb0bd042011-02-03 21:46:10 +00001890bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1891 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001892 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00001893
1894 return (RegNo == (unsigned)-1);
1895}
1896
Kevin Enderby8be42bd2009-10-30 22:55:57 +00001897/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00001898/// and if it is a register name the token is eaten and the register number is
1899/// returned. Otherwise return -1.
1900///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00001901int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00001902 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00001903 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00001904
Chris Lattner44e5981c2010-10-30 04:09:10 +00001905 // FIXME: Validate register for the current architecture; we have to do
1906 // validation later, so maybe there is no need for this here.
Owen Andersona098d152011-01-13 22:50:36 +00001907 std::string upperCase = Tok.getString().str();
1908 std::string lowerCase = LowercaseString(upperCase);
1909 unsigned RegNum = MatchRegisterName(lowerCase);
1910 if (!RegNum) {
1911 RegNum = StringSwitch<unsigned>(lowerCase)
1912 .Case("r13", ARM::SP)
1913 .Case("r14", ARM::LR)
1914 .Case("r15", ARM::PC)
1915 .Case("ip", ARM::R12)
1916 .Default(0);
1917 }
1918 if (!RegNum) return -1;
Bob Wilsonfb0bd042011-02-03 21:46:10 +00001919
Chris Lattner44e5981c2010-10-30 04:09:10 +00001920 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001921
1922#if 0
1923 // Also check for an index operand. This is only legal for vector registers,
1924 // but that'll get caught OK in operand matching, so we don't need to
1925 // explicitly filter everything else out here.
1926 if (Parser.getTok().is(AsmToken::LBrac)) {
1927 SMLoc SIdx = Parser.getTok().getLoc();
1928 Parser.Lex(); // Eat left bracket token.
1929
1930 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001931 if (getParser().ParseExpression(ImmVal))
1932 return MatchOperand_ParseFail;
1933 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1934 if (!MCE) {
1935 TokError("immediate value expected for vector index");
1936 return MatchOperand_ParseFail;
1937 }
1938
1939 SMLoc E = Parser.getTok().getLoc();
1940 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1941 Error(E, "']' expected");
1942 return MatchOperand_ParseFail;
1943 }
1944
1945 Parser.Lex(); // Eat right bracket token.
1946
1947 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1948 SIdx, E,
1949 getContext()));
1950 }
1951#endif
1952
Chris Lattner44e5981c2010-10-30 04:09:10 +00001953 return RegNum;
1954}
Jim Grosbach99710a82010-11-01 16:44:21 +00001955
Jim Grosbachbb24c592011-07-13 18:49:30 +00001956// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1957// If a recoverable error occurs, return 1. If an irrecoverable error
1958// occurs, return -1. An irrecoverable error is one where tokens have been
1959// consumed in the process of trying to parse the shifter (i.e., when it is
1960// indeed a shifter operand, but malformed).
Jim Grosbach0d6022d2011-07-26 20:41:24 +00001961int ARMAsmParser::tryParseShiftRegister(
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001962 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1963 SMLoc S = Parser.getTok().getLoc();
1964 const AsmToken &Tok = Parser.getTok();
1965 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1966
1967 std::string upperCase = Tok.getString().str();
1968 std::string lowerCase = LowercaseString(upperCase);
1969 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1970 .Case("lsl", ARM_AM::lsl)
1971 .Case("lsr", ARM_AM::lsr)
1972 .Case("asr", ARM_AM::asr)
1973 .Case("ror", ARM_AM::ror)
1974 .Case("rrx", ARM_AM::rrx)
1975 .Default(ARM_AM::no_shift);
1976
1977 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00001978 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001979
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001980 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001981
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001982 // The source register for the shift has already been added to the
1983 // operand list, so we need to pop it off and combine it into the shifted
1984 // register operand instead.
Benjamin Kramer1757e7a2011-07-14 18:41:22 +00001985 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001986 if (!PrevOp->isReg())
1987 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1988 int SrcReg = PrevOp->getReg();
1989 int64_t Imm = 0;
1990 int ShiftReg = 0;
1991 if (ShiftTy == ARM_AM::rrx) {
1992 // RRX Doesn't have an explicit shift amount. The encoder expects
1993 // the shift register to be the same as the source register. Seems odd,
1994 // but OK.
1995 ShiftReg = SrcReg;
1996 } else {
1997 // Figure out if this is shifted by a constant or a register (for non-RRX).
1998 if (Parser.getTok().is(AsmToken::Hash)) {
1999 Parser.Lex(); // Eat hash.
2000 SMLoc ImmLoc = Parser.getTok().getLoc();
2001 const MCExpr *ShiftExpr = 0;
Jim Grosbachbb24c592011-07-13 18:49:30 +00002002 if (getParser().ParseExpression(ShiftExpr)) {
2003 Error(ImmLoc, "invalid immediate shift value");
2004 return -1;
2005 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002006 // The expression must be evaluatable as an immediate.
2007 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00002008 if (!CE) {
2009 Error(ImmLoc, "invalid immediate shift value");
2010 return -1;
2011 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002012 // Range check the immediate.
2013 // lsl, ror: 0 <= imm <= 31
2014 // lsr, asr: 0 <= imm <= 32
2015 Imm = CE->getValue();
2016 if (Imm < 0 ||
2017 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2018 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00002019 Error(ImmLoc, "immediate shift value out of range");
2020 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002021 }
2022 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002023 ShiftReg = tryParseRegister();
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002024 SMLoc L = Parser.getTok().getLoc();
Jim Grosbachbb24c592011-07-13 18:49:30 +00002025 if (ShiftReg == -1) {
2026 Error (L, "expected immediate or register in shift operand");
2027 return -1;
2028 }
2029 } else {
2030 Error (Parser.getTok().getLoc(),
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002031 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00002032 return -1;
2033 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002034 }
2035
Owen Andersonb595ed02011-07-21 18:54:16 +00002036 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2037 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00002038 ShiftReg, Imm,
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002039 S, Parser.getTok().getLoc()));
Owen Andersonb595ed02011-07-21 18:54:16 +00002040 else
2041 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2042 S, Parser.getTok().getLoc()));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002043
Jim Grosbachbb24c592011-07-13 18:49:30 +00002044 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002045}
2046
2047
Bill Wendling2063b842010-11-18 23:43:05 +00002048/// Try to parse a register name. The token must be an Identifier when called.
2049/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2050/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002051///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002052/// TODO this is likely to change to allow different register types and or to
2053/// parse for a specific register type.
Bill Wendling2063b842010-11-18 23:43:05 +00002054bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002055tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002056 SMLoc S = Parser.getTok().getLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002057 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00002058 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00002059 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00002060
Bill Wendling2063b842010-11-18 23:43:05 +00002061 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002062
Chris Lattner44e5981c2010-10-30 04:09:10 +00002063 const AsmToken &ExclaimTok = Parser.getTok();
2064 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00002065 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2066 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00002067 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002068 return false;
2069 }
2070
2071 // Also check for an index operand. This is only legal for vector registers,
2072 // but that'll get caught OK in operand matching, so we don't need to
2073 // explicitly filter everything else out here.
2074 if (Parser.getTok().is(AsmToken::LBrac)) {
2075 SMLoc SIdx = Parser.getTok().getLoc();
2076 Parser.Lex(); // Eat left bracket token.
2077
2078 const MCExpr *ImmVal;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002079 if (getParser().ParseExpression(ImmVal))
2080 return MatchOperand_ParseFail;
2081 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2082 if (!MCE) {
2083 TokError("immediate value expected for vector index");
2084 return MatchOperand_ParseFail;
2085 }
2086
2087 SMLoc E = Parser.getTok().getLoc();
2088 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2089 Error(E, "']' expected");
2090 return MatchOperand_ParseFail;
2091 }
2092
2093 Parser.Lex(); // Eat right bracket token.
2094
2095 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2096 SIdx, E,
2097 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00002098 }
2099
Bill Wendling2063b842010-11-18 23:43:05 +00002100 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002101}
2102
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002103/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2104/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2105/// "c5", ...
2106static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002107 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2108 // but efficient.
2109 switch (Name.size()) {
2110 default: break;
2111 case 2:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002112 if (Name[0] != CoprocOp)
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002113 return -1;
2114 switch (Name[1]) {
2115 default: return -1;
2116 case '0': return 0;
2117 case '1': return 1;
2118 case '2': return 2;
2119 case '3': return 3;
2120 case '4': return 4;
2121 case '5': return 5;
2122 case '6': return 6;
2123 case '7': return 7;
2124 case '8': return 8;
2125 case '9': return 9;
2126 }
2127 break;
2128 case 3:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002129 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002130 return -1;
2131 switch (Name[2]) {
2132 default: return -1;
2133 case '0': return 10;
2134 case '1': return 11;
2135 case '2': return 12;
2136 case '3': return 13;
2137 case '4': return 14;
2138 case '5': return 15;
2139 }
2140 break;
2141 }
2142
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002143 return -1;
2144}
2145
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002146/// parseITCondCode - Try to parse a condition code for an IT instruction.
2147ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2148parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2149 SMLoc S = Parser.getTok().getLoc();
2150 const AsmToken &Tok = Parser.getTok();
2151 if (!Tok.is(AsmToken::Identifier))
2152 return MatchOperand_NoMatch;
2153 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2154 .Case("eq", ARMCC::EQ)
2155 .Case("ne", ARMCC::NE)
2156 .Case("hs", ARMCC::HS)
2157 .Case("cs", ARMCC::HS)
2158 .Case("lo", ARMCC::LO)
2159 .Case("cc", ARMCC::LO)
2160 .Case("mi", ARMCC::MI)
2161 .Case("pl", ARMCC::PL)
2162 .Case("vs", ARMCC::VS)
2163 .Case("vc", ARMCC::VC)
2164 .Case("hi", ARMCC::HI)
2165 .Case("ls", ARMCC::LS)
2166 .Case("ge", ARMCC::GE)
2167 .Case("lt", ARMCC::LT)
2168 .Case("gt", ARMCC::GT)
2169 .Case("le", ARMCC::LE)
2170 .Case("al", ARMCC::AL)
2171 .Default(~0U);
2172 if (CC == ~0U)
2173 return MatchOperand_NoMatch;
2174 Parser.Lex(); // Eat the token.
2175
2176 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2177
2178 return MatchOperand_Success;
2179}
2180
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002181/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002182/// token must be an Identifier when called, and if it is a coprocessor
2183/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002184ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002185parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002186 SMLoc S = Parser.getTok().getLoc();
2187 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002188 if (Tok.isNot(AsmToken::Identifier))
2189 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002190
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002191 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002192 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002193 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002194
2195 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002196 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002197 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002198}
2199
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002200/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002201/// token must be an Identifier when called, and if it is a coprocessor
2202/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002203ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002204parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002205 SMLoc S = Parser.getTok().getLoc();
2206 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00002207 if (Tok.isNot(AsmToken::Identifier))
2208 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002209
2210 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2211 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002212 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002213
2214 Parser.Lex(); // Eat identifier token.
2215 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002216 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00002217}
2218
Jim Grosbach48399582011-10-12 17:34:41 +00002219/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2220/// coproc_option : '{' imm0_255 '}'
2221ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2222parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2223 SMLoc S = Parser.getTok().getLoc();
2224
2225 // If this isn't a '{', this isn't a coprocessor immediate operand.
2226 if (Parser.getTok().isNot(AsmToken::LCurly))
2227 return MatchOperand_NoMatch;
2228 Parser.Lex(); // Eat the '{'
2229
2230 const MCExpr *Expr;
2231 SMLoc Loc = Parser.getTok().getLoc();
2232 if (getParser().ParseExpression(Expr)) {
2233 Error(Loc, "illegal expression");
2234 return MatchOperand_ParseFail;
2235 }
2236 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2237 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2238 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2239 return MatchOperand_ParseFail;
2240 }
2241 int Val = CE->getValue();
2242
2243 // Check for and consume the closing '}'
2244 if (Parser.getTok().isNot(AsmToken::RCurly))
2245 return MatchOperand_ParseFail;
2246 SMLoc E = Parser.getTok().getLoc();
2247 Parser.Lex(); // Eat the '}'
2248
2249 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2250 return MatchOperand_Success;
2251}
2252
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002253// For register list parsing, we need to map from raw GPR register numbering
2254// to the enumeration values. The enumeration values aren't sorted by
2255// register number due to our using "sp", "lr" and "pc" as canonical names.
2256static unsigned getNextRegister(unsigned Reg) {
2257 // If this is a GPR, we need to do it manually, otherwise we can rely
2258 // on the sort ordering of the enumeration since the other reg-classes
2259 // are sane.
2260 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2261 return Reg + 1;
2262 switch(Reg) {
2263 default: assert(0 && "Invalid GPR number!");
2264 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2265 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2266 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2267 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2268 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2269 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2270 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2271 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2272 }
2273}
2274
2275/// Parse a register list.
Bill Wendling2063b842010-11-18 23:43:05 +00002276bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002277parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00002278 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00002279 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00002280 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002281 Parser.Lex(); // Eat '{' token.
2282 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00002283
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002284 // Check the first register in the list to see what register class
2285 // this is a list of.
2286 int Reg = tryParseRegister();
2287 if (Reg == -1)
2288 return Error(RegLoc, "register expected");
2289
2290 MCRegisterClass *RC;
2291 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2292 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2293 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2294 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2295 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2296 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2297 else
2298 return Error(RegLoc, "invalid register in register list");
2299
2300 // The reglist instructions have at most 16 registers, so reserve
2301 // space for that many.
Jim Grosbache3a6a822011-09-13 20:35:57 +00002302 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002303 // Store the first register.
2304 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbya2b99102009-10-09 21:12:28 +00002305
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002306 // This starts immediately after the first register token in the list,
2307 // so we can see either a comma or a minus (range separator) as a legal
2308 // next token.
2309 while (Parser.getTok().is(AsmToken::Comma) ||
2310 Parser.getTok().is(AsmToken::Minus)) {
2311 if (Parser.getTok().is(AsmToken::Minus)) {
2312 Parser.Lex(); // Eat the comma.
2313 SMLoc EndLoc = Parser.getTok().getLoc();
2314 int EndReg = tryParseRegister();
2315 if (EndReg == -1)
2316 return Error(EndLoc, "register expected");
2317 // If the register is the same as the start reg, there's nothing
2318 // more to do.
2319 if (Reg == EndReg)
2320 continue;
2321 // The register must be in the same register class as the first.
2322 if (!RC->contains(EndReg))
2323 return Error(EndLoc, "invalid register in register list");
2324 // Ranges must go from low to high.
2325 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2326 return Error(EndLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00002327
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002328 // Add all the registers in the range to the register list.
2329 while (Reg != EndReg) {
2330 Reg = getNextRegister(Reg);
2331 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2332 }
2333 continue;
2334 }
2335 Parser.Lex(); // Eat the comma.
2336 RegLoc = Parser.getTok().getLoc();
2337 int OldReg = Reg;
2338 Reg = tryParseRegister();
2339 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00002340 return Error(RegLoc, "register expected");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002341 // The register must be in the same register class as the first.
2342 if (!RC->contains(Reg))
2343 return Error(RegLoc, "invalid register in register list");
2344 // List must be monotonically increasing.
2345 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2346 return Error(RegLoc, "register list not in ascending order");
2347 // VFP register lists must also be contiguous.
2348 // It's OK to use the enumeration values directly here rather, as the
2349 // VFP register classes have the enum sorted properly.
2350 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2351 Reg != OldReg + 1)
2352 return Error(RegLoc, "non-contiguous register range");
2353 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge18980a2010-11-06 22:36:58 +00002354 }
2355
Jim Grosbach3ac26b12011-09-14 18:08:35 +00002356 SMLoc E = Parser.getTok().getLoc();
2357 if (Parser.getTok().isNot(AsmToken::RCurly))
2358 return Error(E, "'}' expected");
2359 Parser.Lex(); // Eat '}' token.
2360
Bill Wendling2063b842010-11-18 23:43:05 +00002361 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2362 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00002363}
2364
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002365/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbach861e49c2011-02-12 01:34:40 +00002366ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002367parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002368 SMLoc S = Parser.getTok().getLoc();
2369 const AsmToken &Tok = Parser.getTok();
2370 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2371 StringRef OptStr = Tok.getString();
2372
2373 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2374 .Case("sy", ARM_MB::SY)
2375 .Case("st", ARM_MB::ST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002376 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002377 .Case("ish", ARM_MB::ISH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002378 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002379 .Case("ishst", ARM_MB::ISHST)
2380 .Case("nsh", ARM_MB::NSH)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002381 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002382 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach44c3f082011-07-13 23:40:38 +00002383 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002384 .Case("osh", ARM_MB::OSH)
2385 .Case("oshst", ARM_MB::OSHST)
2386 .Default(~0U);
2387
2388 if (Opt == ~0U)
Jim Grosbach861e49c2011-02-12 01:34:40 +00002389 return MatchOperand_NoMatch;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002390
2391 Parser.Lex(); // Eat identifier token.
2392 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00002393 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002394}
2395
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002396/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002397ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002398parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002399 SMLoc S = Parser.getTok().getLoc();
2400 const AsmToken &Tok = Parser.getTok();
2401 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2402 StringRef IFlagsStr = Tok.getString();
2403
Owen Anderson10c5b122011-10-05 17:16:40 +00002404 // An iflags string of "none" is interpreted to mean that none of the AIF
2405 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002406 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00002407 if (IFlagsStr != "none") {
2408 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2409 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2410 .Case("a", ARM_PROC::A)
2411 .Case("i", ARM_PROC::I)
2412 .Case("f", ARM_PROC::F)
2413 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002414
Owen Anderson10c5b122011-10-05 17:16:40 +00002415 // If some specific iflag is already set, it means that some letter is
2416 // present more than once, this is not acceptable.
2417 if (Flag == ~0U || (IFlags & Flag))
2418 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002419
Owen Anderson10c5b122011-10-05 17:16:40 +00002420 IFlags |= Flag;
2421 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002422 }
2423
2424 Parser.Lex(); // Eat identifier token.
2425 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2426 return MatchOperand_Success;
2427}
2428
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002429/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002430ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach2d6ef442011-07-25 20:14:50 +00002431parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002432 SMLoc S = Parser.getTok().getLoc();
2433 const AsmToken &Tok = Parser.getTok();
2434 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2435 StringRef Mask = Tok.getString();
2436
James Molloy21efa7d2011-09-28 14:21:38 +00002437 if (isMClass()) {
2438 // See ARMv6-M 10.1.1
2439 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2440 .Case("apsr", 0)
2441 .Case("iapsr", 1)
2442 .Case("eapsr", 2)
2443 .Case("xpsr", 3)
2444 .Case("ipsr", 5)
2445 .Case("epsr", 6)
2446 .Case("iepsr", 7)
2447 .Case("msp", 8)
2448 .Case("psp", 9)
2449 .Case("primask", 16)
2450 .Case("basepri", 17)
2451 .Case("basepri_max", 18)
2452 .Case("faultmask", 19)
2453 .Case("control", 20)
2454 .Default(~0U);
2455
2456 if (FlagsVal == ~0U)
2457 return MatchOperand_NoMatch;
2458
2459 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2460 // basepri, basepri_max and faultmask only valid for V7m.
2461 return MatchOperand_NoMatch;
2462
2463 Parser.Lex(); // Eat identifier token.
2464 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2465 return MatchOperand_Success;
2466 }
2467
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002468 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2469 size_t Start = 0, Next = Mask.find('_');
2470 StringRef Flags = "";
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002471 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002472 if (Next != StringRef::npos)
2473 Flags = Mask.slice(Next+1, Mask.size());
2474
2475 // FlagsVal contains the complete mask:
2476 // 3-0: Mask
2477 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2478 unsigned FlagsVal = 0;
2479
2480 if (SpecReg == "apsr") {
2481 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00002482 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002483 .Case("g", 0x4) // same as CPSR_s
2484 .Case("nzcvqg", 0xc) // same as CPSR_fs
2485 .Default(~0U);
2486
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002487 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002488 if (!Flags.empty())
2489 return MatchOperand_NoMatch;
2490 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00002491 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00002492 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002493 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00002494 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2495 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002496 for (int i = 0, e = Flags.size(); i != e; ++i) {
2497 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2498 .Case("c", 1)
2499 .Case("x", 2)
2500 .Case("s", 4)
2501 .Case("f", 8)
2502 .Default(~0U);
2503
2504 // If some specific flag is already set, it means that some letter is
2505 // present more than once, this is not acceptable.
2506 if (FlagsVal == ~0U || (FlagsVal & Flag))
2507 return MatchOperand_NoMatch;
2508 FlagsVal |= Flag;
2509 }
2510 } else // No match for special register.
2511 return MatchOperand_NoMatch;
2512
2513 // Special register without flags are equivalent to "fc" flags.
2514 if (!FlagsVal)
2515 FlagsVal = 0x9;
2516
2517 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2518 if (SpecReg == "spsr")
2519 FlagsVal |= 16;
2520
2521 Parser.Lex(); // Eat identifier token.
2522 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2523 return MatchOperand_Success;
2524}
2525
Jim Grosbach27c1e252011-07-21 17:23:04 +00002526ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2527parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2528 int Low, int High) {
2529 const AsmToken &Tok = Parser.getTok();
2530 if (Tok.isNot(AsmToken::Identifier)) {
2531 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2532 return MatchOperand_ParseFail;
2533 }
2534 StringRef ShiftName = Tok.getString();
2535 std::string LowerOp = LowercaseString(Op);
2536 std::string UpperOp = UppercaseString(Op);
2537 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2538 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2539 return MatchOperand_ParseFail;
2540 }
2541 Parser.Lex(); // Eat shift type token.
2542
2543 // There must be a '#' and a shift amount.
2544 if (Parser.getTok().isNot(AsmToken::Hash)) {
2545 Error(Parser.getTok().getLoc(), "'#' expected");
2546 return MatchOperand_ParseFail;
2547 }
2548 Parser.Lex(); // Eat hash token.
2549
2550 const MCExpr *ShiftAmount;
2551 SMLoc Loc = Parser.getTok().getLoc();
2552 if (getParser().ParseExpression(ShiftAmount)) {
2553 Error(Loc, "illegal expression");
2554 return MatchOperand_ParseFail;
2555 }
2556 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2557 if (!CE) {
2558 Error(Loc, "constant expression expected");
2559 return MatchOperand_ParseFail;
2560 }
2561 int Val = CE->getValue();
2562 if (Val < Low || Val > High) {
2563 Error(Loc, "immediate value out of range");
2564 return MatchOperand_ParseFail;
2565 }
2566
2567 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2568
2569 return MatchOperand_Success;
2570}
2571
Jim Grosbach0a547702011-07-22 17:44:50 +00002572ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2573parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2574 const AsmToken &Tok = Parser.getTok();
2575 SMLoc S = Tok.getLoc();
2576 if (Tok.isNot(AsmToken::Identifier)) {
2577 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2578 return MatchOperand_ParseFail;
2579 }
2580 int Val = StringSwitch<int>(Tok.getString())
2581 .Case("be", 1)
2582 .Case("le", 0)
2583 .Default(-1);
2584 Parser.Lex(); // Eat the token.
2585
2586 if (Val == -1) {
2587 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2588 return MatchOperand_ParseFail;
2589 }
2590 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2591 getContext()),
2592 S, Parser.getTok().getLoc()));
2593 return MatchOperand_Success;
2594}
2595
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002596/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2597/// instructions. Legal values are:
2598/// lsl #n 'n' in [0,31]
2599/// asr #n 'n' in [1,32]
2600/// n == 32 encoded as n == 0.
2601ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2602parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2603 const AsmToken &Tok = Parser.getTok();
2604 SMLoc S = Tok.getLoc();
2605 if (Tok.isNot(AsmToken::Identifier)) {
2606 Error(S, "shift operator 'asr' or 'lsl' expected");
2607 return MatchOperand_ParseFail;
2608 }
2609 StringRef ShiftName = Tok.getString();
2610 bool isASR;
2611 if (ShiftName == "lsl" || ShiftName == "LSL")
2612 isASR = false;
2613 else if (ShiftName == "asr" || ShiftName == "ASR")
2614 isASR = true;
2615 else {
2616 Error(S, "shift operator 'asr' or 'lsl' expected");
2617 return MatchOperand_ParseFail;
2618 }
2619 Parser.Lex(); // Eat the operator.
2620
2621 // A '#' and a shift amount.
2622 if (Parser.getTok().isNot(AsmToken::Hash)) {
2623 Error(Parser.getTok().getLoc(), "'#' expected");
2624 return MatchOperand_ParseFail;
2625 }
2626 Parser.Lex(); // Eat hash token.
2627
2628 const MCExpr *ShiftAmount;
2629 SMLoc E = Parser.getTok().getLoc();
2630 if (getParser().ParseExpression(ShiftAmount)) {
2631 Error(E, "malformed shift expression");
2632 return MatchOperand_ParseFail;
2633 }
2634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2635 if (!CE) {
2636 Error(E, "shift amount must be an immediate");
2637 return MatchOperand_ParseFail;
2638 }
2639
2640 int64_t Val = CE->getValue();
2641 if (isASR) {
2642 // Shift amount must be in [1,32]
2643 if (Val < 1 || Val > 32) {
2644 Error(E, "'asr' shift amount must be in range [1,32]");
2645 return MatchOperand_ParseFail;
2646 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00002647 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2648 if (isThumb() && Val == 32) {
2649 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2650 return MatchOperand_ParseFail;
2651 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002652 if (Val == 32) Val = 0;
2653 } else {
2654 // Shift amount must be in [1,32]
2655 if (Val < 0 || Val > 31) {
2656 Error(E, "'lsr' shift amount must be in range [0,31]");
2657 return MatchOperand_ParseFail;
2658 }
2659 }
2660
2661 E = Parser.getTok().getLoc();
2662 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2663
2664 return MatchOperand_Success;
2665}
2666
Jim Grosbach833b9d32011-07-27 20:15:40 +00002667/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2668/// of instructions. Legal values are:
2669/// ror #n 'n' in {0, 8, 16, 24}
2670ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2671parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2672 const AsmToken &Tok = Parser.getTok();
2673 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00002674 if (Tok.isNot(AsmToken::Identifier))
2675 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002676 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00002677 if (ShiftName != "ror" && ShiftName != "ROR")
2678 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00002679 Parser.Lex(); // Eat the operator.
2680
2681 // A '#' and a rotate amount.
2682 if (Parser.getTok().isNot(AsmToken::Hash)) {
2683 Error(Parser.getTok().getLoc(), "'#' expected");
2684 return MatchOperand_ParseFail;
2685 }
2686 Parser.Lex(); // Eat hash token.
2687
2688 const MCExpr *ShiftAmount;
2689 SMLoc E = Parser.getTok().getLoc();
2690 if (getParser().ParseExpression(ShiftAmount)) {
2691 Error(E, "malformed rotate expression");
2692 return MatchOperand_ParseFail;
2693 }
2694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2695 if (!CE) {
2696 Error(E, "rotate amount must be an immediate");
2697 return MatchOperand_ParseFail;
2698 }
2699
2700 int64_t Val = CE->getValue();
2701 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2702 // normally, zero is represented in asm by omitting the rotate operand
2703 // entirely.
2704 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2705 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2706 return MatchOperand_ParseFail;
2707 }
2708
2709 E = Parser.getTok().getLoc();
2710 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2711
2712 return MatchOperand_Success;
2713}
2714
Jim Grosbach864b6092011-07-28 21:34:26 +00002715ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2716parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2717 SMLoc S = Parser.getTok().getLoc();
2718 // The bitfield descriptor is really two operands, the LSB and the width.
2719 if (Parser.getTok().isNot(AsmToken::Hash)) {
2720 Error(Parser.getTok().getLoc(), "'#' expected");
2721 return MatchOperand_ParseFail;
2722 }
2723 Parser.Lex(); // Eat hash token.
2724
2725 const MCExpr *LSBExpr;
2726 SMLoc E = Parser.getTok().getLoc();
2727 if (getParser().ParseExpression(LSBExpr)) {
2728 Error(E, "malformed immediate expression");
2729 return MatchOperand_ParseFail;
2730 }
2731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2732 if (!CE) {
2733 Error(E, "'lsb' operand must be an immediate");
2734 return MatchOperand_ParseFail;
2735 }
2736
2737 int64_t LSB = CE->getValue();
2738 // The LSB must be in the range [0,31]
2739 if (LSB < 0 || LSB > 31) {
2740 Error(E, "'lsb' operand must be in the range [0,31]");
2741 return MatchOperand_ParseFail;
2742 }
2743 E = Parser.getTok().getLoc();
2744
2745 // Expect another immediate operand.
2746 if (Parser.getTok().isNot(AsmToken::Comma)) {
2747 Error(Parser.getTok().getLoc(), "too few operands");
2748 return MatchOperand_ParseFail;
2749 }
2750 Parser.Lex(); // Eat hash token.
2751 if (Parser.getTok().isNot(AsmToken::Hash)) {
2752 Error(Parser.getTok().getLoc(), "'#' expected");
2753 return MatchOperand_ParseFail;
2754 }
2755 Parser.Lex(); // Eat hash token.
2756
2757 const MCExpr *WidthExpr;
2758 if (getParser().ParseExpression(WidthExpr)) {
2759 Error(E, "malformed immediate expression");
2760 return MatchOperand_ParseFail;
2761 }
2762 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2763 if (!CE) {
2764 Error(E, "'width' operand must be an immediate");
2765 return MatchOperand_ParseFail;
2766 }
2767
2768 int64_t Width = CE->getValue();
2769 // The LSB must be in the range [1,32-lsb]
2770 if (Width < 1 || Width > 32 - LSB) {
2771 Error(E, "'width' operand must be in the range [1,32-lsb]");
2772 return MatchOperand_ParseFail;
2773 }
2774 E = Parser.getTok().getLoc();
2775
2776 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2777
2778 return MatchOperand_Success;
2779}
2780
Jim Grosbachd3595712011-08-03 23:50:40 +00002781ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2782parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2783 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00002784 // postidx_reg := '+' register {, shift}
2785 // | '-' register {, shift}
2786 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00002787
2788 // This method must return MatchOperand_NoMatch without consuming any tokens
2789 // in the case where there is no match, as other alternatives take other
2790 // parse methods.
2791 AsmToken Tok = Parser.getTok();
2792 SMLoc S = Tok.getLoc();
2793 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00002794 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00002795 int Reg = -1;
2796 if (Tok.is(AsmToken::Plus)) {
2797 Parser.Lex(); // Eat the '+' token.
2798 haveEaten = true;
2799 } else if (Tok.is(AsmToken::Minus)) {
2800 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00002801 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00002802 haveEaten = true;
2803 }
2804 if (Parser.getTok().is(AsmToken::Identifier))
2805 Reg = tryParseRegister();
2806 if (Reg == -1) {
2807 if (!haveEaten)
2808 return MatchOperand_NoMatch;
2809 Error(Parser.getTok().getLoc(), "register expected");
2810 return MatchOperand_ParseFail;
2811 }
2812 SMLoc E = Parser.getTok().getLoc();
2813
Jim Grosbachc320c852011-08-05 21:28:30 +00002814 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2815 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00002816 if (Parser.getTok().is(AsmToken::Comma)) {
2817 Parser.Lex(); // Eat the ','.
2818 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2819 return MatchOperand_ParseFail;
2820 }
Jim Grosbachc320c852011-08-05 21:28:30 +00002821
2822 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2823 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00002824
2825 return MatchOperand_Success;
2826}
2827
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00002828ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2829parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2830 // Check for a post-index addressing register operand. Specifically:
2831 // am3offset := '+' register
2832 // | '-' register
2833 // | register
2834 // | # imm
2835 // | # + imm
2836 // | # - imm
2837
2838 // This method must return MatchOperand_NoMatch without consuming any tokens
2839 // in the case where there is no match, as other alternatives take other
2840 // parse methods.
2841 AsmToken Tok = Parser.getTok();
2842 SMLoc S = Tok.getLoc();
2843
2844 // Do immediates first, as we always parse those if we have a '#'.
2845 if (Parser.getTok().is(AsmToken::Hash)) {
2846 Parser.Lex(); // Eat the '#'.
2847 // Explicitly look for a '-', as we need to encode negative zero
2848 // differently.
2849 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2850 const MCExpr *Offset;
2851 if (getParser().ParseExpression(Offset))
2852 return MatchOperand_ParseFail;
2853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2854 if (!CE) {
2855 Error(S, "constant expression expected");
2856 return MatchOperand_ParseFail;
2857 }
2858 SMLoc E = Tok.getLoc();
2859 // Negative zero is encoded as the flag value INT32_MIN.
2860 int32_t Val = CE->getValue();
2861 if (isNegative && Val == 0)
2862 Val = INT32_MIN;
2863
2864 Operands.push_back(
2865 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2866
2867 return MatchOperand_Success;
2868 }
2869
2870
2871 bool haveEaten = false;
2872 bool isAdd = true;
2873 int Reg = -1;
2874 if (Tok.is(AsmToken::Plus)) {
2875 Parser.Lex(); // Eat the '+' token.
2876 haveEaten = true;
2877 } else if (Tok.is(AsmToken::Minus)) {
2878 Parser.Lex(); // Eat the '-' token.
2879 isAdd = false;
2880 haveEaten = true;
2881 }
2882 if (Parser.getTok().is(AsmToken::Identifier))
2883 Reg = tryParseRegister();
2884 if (Reg == -1) {
2885 if (!haveEaten)
2886 return MatchOperand_NoMatch;
2887 Error(Parser.getTok().getLoc(), "register expected");
2888 return MatchOperand_ParseFail;
2889 }
2890 SMLoc E = Parser.getTok().getLoc();
2891
2892 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2893 0, S, E));
2894
2895 return MatchOperand_Success;
2896}
2897
Jim Grosbach7db8d692011-09-08 22:07:06 +00002898/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2899/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2900/// when they refer multiple MIOperands inside a single one.
2901bool ARMAsmParser::
2902cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2903 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2904 // Rt, Rt2
2905 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2906 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2907 // Create a writeback register dummy placeholder.
2908 Inst.addOperand(MCOperand::CreateReg(0));
2909 // addr
2910 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2911 // pred
2912 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2913 return true;
2914}
2915
2916/// cvtT2StrdPre - Convert parsed operands to MCInst.
2917/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2918/// when they refer multiple MIOperands inside a single one.
2919bool ARMAsmParser::
2920cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2921 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2922 // Create a writeback register dummy placeholder.
2923 Inst.addOperand(MCOperand::CreateReg(0));
2924 // Rt, Rt2
2925 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2926 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2927 // addr
2928 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2929 // pred
2930 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2931 return true;
2932}
2933
Jim Grosbachc086f682011-09-08 00:39:19 +00002934/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2935/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2936/// when they refer multiple MIOperands inside a single one.
2937bool ARMAsmParser::
2938cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2939 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2940 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2941
2942 // Create a writeback register dummy placeholder.
2943 Inst.addOperand(MCOperand::CreateImm(0));
2944
2945 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2946 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2947 return true;
2948}
2949
Jim Grosbach9c0b86a2011-09-16 21:55:56 +00002950/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2951/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2952/// when they refer multiple MIOperands inside a single one.
2953bool ARMAsmParser::
2954cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2955 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2956 // Create a writeback register dummy placeholder.
2957 Inst.addOperand(MCOperand::CreateImm(0));
2958 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2959 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2960 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2961 return true;
2962}
2963
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002964/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002965/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2966/// when they refer multiple MIOperands inside a single one.
2967bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002968cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002969 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2970 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2971
2972 // Create a writeback register dummy placeholder.
2973 Inst.addOperand(MCOperand::CreateImm(0));
2974
Jim Grosbachd3595712011-08-03 23:50:40 +00002975 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002976 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2977 return true;
2978}
2979
Owen Anderson16d33f32011-08-26 20:43:14 +00002980/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2981/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2982/// when they refer multiple MIOperands inside a single one.
2983bool ARMAsmParser::
2984cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2985 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2986 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2987
2988 // Create a writeback register dummy placeholder.
2989 Inst.addOperand(MCOperand::CreateImm(0));
2990
2991 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2992 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2993 return true;
2994}
2995
2996
Jim Grosbachd564bf32011-08-11 19:22:40 +00002997/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2998/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2999/// when they refer multiple MIOperands inside a single one.
3000bool ARMAsmParser::
3001cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3002 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3003 // Create a writeback register dummy placeholder.
3004 Inst.addOperand(MCOperand::CreateImm(0));
3005 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3006 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3007 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3008 return true;
3009}
3010
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003011/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003012/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3013/// when they refer multiple MIOperands inside a single one.
3014bool ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003015cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003016 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3017 // Create a writeback register dummy placeholder.
3018 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd564bf32011-08-11 19:22:40 +00003019 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3020 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3021 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbachd3595712011-08-03 23:50:40 +00003022 return true;
3023}
3024
Jim Grosbachd886f8c2011-08-11 21:17:22 +00003025/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3026/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3027/// when they refer multiple MIOperands inside a single one.
3028bool ARMAsmParser::
3029cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3030 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3031 // Create a writeback register dummy placeholder.
3032 Inst.addOperand(MCOperand::CreateImm(0));
3033 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3034 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3035 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3036 return true;
3037}
3038
Jim Grosbachd3595712011-08-03 23:50:40 +00003039/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3040/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3041/// when they refer multiple MIOperands inside a single one.
3042bool ARMAsmParser::
3043cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3044 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3045 // Rt
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003046 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003047 // Create a writeback register dummy placeholder.
3048 Inst.addOperand(MCOperand::CreateImm(0));
3049 // addr
3050 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3051 // offset
3052 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3053 // pred
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00003054 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3055 return true;
3056}
3057
Jim Grosbachd3595712011-08-03 23:50:40 +00003058/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003059/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3060/// when they refer multiple MIOperands inside a single one.
3061bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003062cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3063 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3064 // Rt
Owen Andersonb0e68992011-07-28 17:18:57 +00003065 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003066 // Create a writeback register dummy placeholder.
3067 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003068 // addr
3069 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3070 // offset
3071 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3072 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003073 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3074 return true;
3075}
3076
Jim Grosbachd3595712011-08-03 23:50:40 +00003077/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003078/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3079/// when they refer multiple MIOperands inside a single one.
3080bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003081cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3082 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003083 // Create a writeback register dummy placeholder.
3084 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbachd3595712011-08-03 23:50:40 +00003085 // Rt
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003086 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbachd3595712011-08-03 23:50:40 +00003087 // addr
3088 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3089 // offset
3090 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3091 // pred
3092 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3093 return true;
3094}
3095
3096/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3097/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3098/// when they refer multiple MIOperands inside a single one.
3099bool ARMAsmParser::
3100cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3101 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3102 // Create a writeback register dummy placeholder.
3103 Inst.addOperand(MCOperand::CreateImm(0));
3104 // Rt
3105 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3106 // addr
3107 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3108 // offset
3109 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3110 // pred
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00003111 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3112 return true;
3113}
3114
Jim Grosbach5b96b802011-08-10 20:29:19 +00003115/// cvtLdrdPre - Convert parsed operands to MCInst.
3116/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3117/// when they refer multiple MIOperands inside a single one.
3118bool ARMAsmParser::
3119cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3120 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3121 // Rt, Rt2
3122 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3123 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3124 // Create a writeback register dummy placeholder.
3125 Inst.addOperand(MCOperand::CreateImm(0));
3126 // addr
3127 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3128 // pred
3129 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3130 return true;
3131}
3132
Jim Grosbacheb09f492011-08-11 20:28:23 +00003133/// cvtStrdPre - Convert parsed operands to MCInst.
3134/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3135/// when they refer multiple MIOperands inside a single one.
3136bool ARMAsmParser::
3137cvtStrdPre(MCInst &Inst, unsigned Opcode,
3138 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3139 // Create a writeback register dummy placeholder.
3140 Inst.addOperand(MCOperand::CreateImm(0));
3141 // Rt, Rt2
3142 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3143 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3144 // addr
3145 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3146 // pred
3147 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3148 return true;
3149}
3150
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003151/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3152/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3153/// when they refer multiple MIOperands inside a single one.
3154bool ARMAsmParser::
3155cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3156 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3157 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3158 // Create a writeback register dummy placeholder.
3159 Inst.addOperand(MCOperand::CreateImm(0));
3160 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3161 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3162 return true;
3163}
3164
Jim Grosbach8e048492011-08-19 22:07:46 +00003165/// cvtThumbMultiple- Convert parsed operands to MCInst.
3166/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3167/// when they refer multiple MIOperands inside a single one.
3168bool ARMAsmParser::
3169cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3170 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3171 // The second source operand must be the same register as the destination
3172 // operand.
3173 if (Operands.size() == 6 &&
Jim Grosbach459422d2011-08-19 22:30:46 +00003174 (((ARMOperand*)Operands[3])->getReg() !=
3175 ((ARMOperand*)Operands[5])->getReg()) &&
3176 (((ARMOperand*)Operands[3])->getReg() !=
3177 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach8e048492011-08-19 22:07:46 +00003178 Error(Operands[3]->getStartLoc(),
Jim Grosbach459422d2011-08-19 22:30:46 +00003179 "destination register must match source register");
Jim Grosbach8e048492011-08-19 22:07:46 +00003180 return false;
3181 }
3182 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3183 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3184 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach459422d2011-08-19 22:30:46 +00003185 // If we have a three-operand form, use that, else the second source operand
3186 // is just the destination operand again.
3187 if (Operands.size() == 6)
3188 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3189 else
3190 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach8e048492011-08-19 22:07:46 +00003191 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3192
3193 return true;
3194}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00003195
Bill Wendlinge18980a2010-11-06 22:36:58 +00003196/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003197/// or an error. The first token must be a '[' when called.
Bill Wendling2063b842010-11-18 23:43:05 +00003198bool ARMAsmParser::
Jim Grosbachd3595712011-08-03 23:50:40 +00003199parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003200 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00003201 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003202 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003203 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003204 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003205
Sean Callanan936b0d32010-01-19 21:44:56 +00003206 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003207 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00003208 if (BaseRegNum == -1)
3209 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003210
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003211 // The next token must either be a comma or a closing bracket.
3212 const AsmToken &Tok = Parser.getTok();
3213 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00003214 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00003215
Jim Grosbachd3595712011-08-03 23:50:40 +00003216 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003217 E = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003218 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003219
Jim Grosbachd3595712011-08-03 23:50:40 +00003220 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003221 0, 0, false, S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00003222
Jim Grosbach40700e02011-09-19 18:42:21 +00003223 // If there's a pre-indexing writeback marker, '!', just add it as a token
3224 // operand. It's rather odd, but syntactically valid.
3225 if (Parser.getTok().is(AsmToken::Exclaim)) {
3226 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3227 Parser.Lex(); // Eat the '!'.
3228 }
3229
Jim Grosbachd3595712011-08-03 23:50:40 +00003230 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003231 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003232
Jim Grosbachd3595712011-08-03 23:50:40 +00003233 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3234 Parser.Lex(); // Eat the comma.
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003235
Jim Grosbacha95ec992011-10-11 17:29:55 +00003236 // If we have a ':', it's an alignment specifier.
3237 if (Parser.getTok().is(AsmToken::Colon)) {
3238 Parser.Lex(); // Eat the ':'.
3239 E = Parser.getTok().getLoc();
3240
3241 const MCExpr *Expr;
3242 if (getParser().ParseExpression(Expr))
3243 return true;
3244
3245 // The expression has to be a constant. Memory references with relocations
3246 // don't come through here, as they use the <label> forms of the relevant
3247 // instructions.
3248 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3249 if (!CE)
3250 return Error (E, "constant expression expected");
3251
3252 unsigned Align = 0;
3253 switch (CE->getValue()) {
3254 default:
3255 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3256 case 64: Align = 8; break;
3257 case 128: Align = 16; break;
3258 case 256: Align = 32; break;
3259 }
3260
3261 // Now we should have the closing ']'
3262 E = Parser.getTok().getLoc();
3263 if (Parser.getTok().isNot(AsmToken::RBrac))
3264 return Error(E, "']' expected");
3265 Parser.Lex(); // Eat right bracket token.
3266
3267 // Don't worry about range checking the value here. That's handled by
3268 // the is*() predicates.
3269 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3270 ARM_AM::no_shift, 0, Align,
3271 false, S, E));
3272
3273 // If there's a pre-indexing writeback marker, '!', just add it as a token
3274 // operand.
3275 if (Parser.getTok().is(AsmToken::Exclaim)) {
3276 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3277 Parser.Lex(); // Eat the '!'.
3278 }
3279
3280 return false;
3281 }
3282
3283 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbachd3595712011-08-03 23:50:40 +00003284 // offset.
3285 if (Parser.getTok().is(AsmToken::Hash)) {
3286 Parser.Lex(); // Eat the '#'.
3287 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00003288
Owen Anderson967674d2011-08-29 19:36:44 +00003289 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00003290 const MCExpr *Offset;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003291 if (getParser().ParseExpression(Offset))
3292 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00003293
3294 // The expression has to be a constant. Memory references with relocations
3295 // don't come through here, as they use the <label> forms of the relevant
3296 // instructions.
3297 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3298 if (!CE)
3299 return Error (E, "constant expression expected");
3300
Owen Anderson967674d2011-08-29 19:36:44 +00003301 // If the constant was #-0, represent it as INT32_MIN.
3302 int32_t Val = CE->getValue();
3303 if (isNegative && Val == 0)
3304 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3305
Jim Grosbachd3595712011-08-03 23:50:40 +00003306 // Now we should have the closing ']'
3307 E = Parser.getTok().getLoc();
3308 if (Parser.getTok().isNot(AsmToken::RBrac))
3309 return Error(E, "']' expected");
3310 Parser.Lex(); // Eat right bracket token.
3311
3312 // Don't worry about range checking the value here. That's handled by
3313 // the is*() predicates.
3314 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003315 ARM_AM::no_shift, 0, 0,
3316 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00003317
3318 // If there's a pre-indexing writeback marker, '!', just add it as a token
3319 // operand.
3320 if (Parser.getTok().is(AsmToken::Exclaim)) {
3321 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3322 Parser.Lex(); // Eat the '!'.
3323 }
3324
3325 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003326 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003327
3328 // The register offset is optionally preceded by a '+' or '-'
3329 bool isNegative = false;
3330 if (Parser.getTok().is(AsmToken::Minus)) {
3331 isNegative = true;
3332 Parser.Lex(); // Eat the '-'.
3333 } else if (Parser.getTok().is(AsmToken::Plus)) {
3334 // Nothing to do.
3335 Parser.Lex(); // Eat the '+'.
3336 }
3337
3338 E = Parser.getTok().getLoc();
3339 int OffsetRegNum = tryParseRegister();
3340 if (OffsetRegNum == -1)
3341 return Error(E, "register expected");
3342
3343 // If there's a shift operator, handle it.
3344 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003345 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00003346 if (Parser.getTok().is(AsmToken::Comma)) {
3347 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00003348 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00003349 return true;
3350 }
3351
3352 // Now we should have the closing ']'
3353 E = Parser.getTok().getLoc();
3354 if (Parser.getTok().isNot(AsmToken::RBrac))
3355 return Error(E, "']' expected");
3356 Parser.Lex(); // Eat right bracket token.
3357
3358 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00003359 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00003360 S, E));
3361
Jim Grosbachc320c852011-08-05 21:28:30 +00003362 // If there's a pre-indexing writeback marker, '!', just add it as a token
3363 // operand.
3364 if (Parser.getTok().is(AsmToken::Exclaim)) {
3365 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3366 Parser.Lex(); // Eat the '!'.
3367 }
Jim Grosbachd3595712011-08-03 23:50:40 +00003368
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003369 return false;
3370}
3371
Jim Grosbachd3595712011-08-03 23:50:40 +00003372/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003373/// ( lsl | lsr | asr | ror ) , # shift_amount
3374/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00003375/// return true if it parses a shift otherwise it returns false.
3376bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3377 unsigned &Amount) {
3378 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00003379 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003380 if (Tok.isNot(AsmToken::Identifier))
3381 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00003382 StringRef ShiftName = Tok.getString();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003383 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003384 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003385 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003386 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003387 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003388 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003389 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003390 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003391 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003392 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003393 else
Jim Grosbachd3595712011-08-03 23:50:40 +00003394 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00003395 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003396
Jim Grosbachd3595712011-08-03 23:50:40 +00003397 // rrx stands alone.
3398 Amount = 0;
3399 if (St != ARM_AM::rrx) {
3400 Loc = Parser.getTok().getLoc();
3401 // A '#' and a shift amount.
3402 const AsmToken &HashTok = Parser.getTok();
3403 if (HashTok.isNot(AsmToken::Hash))
3404 return Error(HashTok.getLoc(), "'#' expected");
3405 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003406
Jim Grosbachd3595712011-08-03 23:50:40 +00003407 const MCExpr *Expr;
3408 if (getParser().ParseExpression(Expr))
3409 return true;
3410 // Range check the immediate.
3411 // lsl, ror: 0 <= imm <= 31
3412 // lsr, asr: 0 <= imm <= 32
3413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3414 if (!CE)
3415 return Error(Loc, "shift amount must be an immediate");
3416 int64_t Imm = CE->getValue();
3417 if (Imm < 0 ||
3418 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3419 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3420 return Error(Loc, "immediate shift value out of range");
3421 Amount = Imm;
3422 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003423
3424 return false;
3425}
3426
Jim Grosbache7fbce72011-10-03 23:38:36 +00003427/// parseFPImm - A floating point immediate expression operand.
3428ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3429parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3430 SMLoc S = Parser.getTok().getLoc();
3431
3432 if (Parser.getTok().isNot(AsmToken::Hash))
3433 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00003434
3435 // Disambiguate the VMOV forms that can accept an FP immediate.
3436 // vmov.f32 <sreg>, #imm
3437 // vmov.f64 <dreg>, #imm
3438 // vmov.f32 <dreg>, #imm @ vector f32x2
3439 // vmov.f32 <qreg>, #imm @ vector f32x4
3440 //
3441 // There are also the NEON VMOV instructions which expect an
3442 // integer constant. Make sure we don't try to parse an FPImm
3443 // for these:
3444 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3445 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3446 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3447 TyOp->getToken() != ".f64"))
3448 return MatchOperand_NoMatch;
3449
Jim Grosbache7fbce72011-10-03 23:38:36 +00003450 Parser.Lex(); // Eat the '#'.
3451
3452 // Handle negation, as that still comes through as a separate token.
3453 bool isNegative = false;
3454 if (Parser.getTok().is(AsmToken::Minus)) {
3455 isNegative = true;
3456 Parser.Lex();
3457 }
3458 const AsmToken &Tok = Parser.getTok();
3459 if (Tok.is(AsmToken::Real)) {
3460 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3461 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3462 // If we had a '-' in front, toggle the sign bit.
3463 IntVal ^= (uint64_t)isNegative << 63;
3464 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3465 Parser.Lex(); // Eat the token.
3466 if (Val == -1) {
3467 TokError("floating point value out of range");
3468 return MatchOperand_ParseFail;
3469 }
3470 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3471 return MatchOperand_Success;
3472 }
3473 if (Tok.is(AsmToken::Integer)) {
3474 int64_t Val = Tok.getIntVal();
3475 Parser.Lex(); // Eat the token.
3476 if (Val > 255 || Val < 0) {
3477 TokError("encoded floating point value out of range");
3478 return MatchOperand_ParseFail;
3479 }
3480 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3481 return MatchOperand_Success;
3482 }
3483
3484 TokError("invalid floating point immediate");
3485 return MatchOperand_ParseFail;
3486}
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003487/// Parse a arm instruction operand. For now this parses the operand regardless
3488/// of the mnemonic.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003489bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003490 StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003491 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003492
3493 // Check if the current operand has a custom associated parser, if so, try to
3494 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00003495 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3496 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003497 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00003498 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3499 // there was a match, but an error occurred, in which case, just return that
3500 // the operand parsing failed.
3501 if (ResTy == MatchOperand_ParseFail)
3502 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003503
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003504 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00003505 default:
3506 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00003507 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003508 case AsmToken::Identifier: {
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003509 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003510 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling2063b842010-11-18 23:43:05 +00003511 return false;
Jim Grosbach0d6022d2011-07-26 20:41:24 +00003512 int Res = tryParseShiftRegister(Operands);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003513 if (Res == 0) // success
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003514 return false;
Jim Grosbachbb24c592011-07-13 18:49:30 +00003515 else if (Res == -1) // irrecoverable error
3516 return true;
Jim Grosbach4ab23b52011-10-03 21:12:43 +00003517 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3518 S = Parser.getTok().getLoc();
3519 Parser.Lex();
3520 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3521 return false;
3522 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003523
3524 // Fall though for the Identifier case that is not a register or a
3525 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00003526 }
Kevin Enderbyb084be92011-01-13 20:32:36 +00003527 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3528 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00003529 // This was not a register so parse other operands that start with an
3530 // identifier (like labels) as expressions and create them as immediates.
3531 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003532 S = Parser.getTok().getLoc();
Kevin Enderby146dcf22009-10-15 20:48:48 +00003533 if (getParser().ParseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003534 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003535 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003536 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3537 return false;
3538 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003539 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003540 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00003541 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003542 return parseRegisterList(Operands);
Owen Andersonf02d98d2011-08-29 17:17:09 +00003543 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00003544 // #42 -> immediate.
3545 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003546 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00003547 Parser.Lex();
Owen Andersonf02d98d2011-08-29 17:17:09 +00003548 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby146dcf22009-10-15 20:48:48 +00003549 const MCExpr *ImmVal;
3550 if (getParser().ParseExpression(ImmVal))
Bill Wendling2063b842010-11-18 23:43:05 +00003551 return true;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3553 if (!CE) {
3554 Error(S, "constant expression expected");
3555 return MatchOperand_ParseFail;
3556 }
3557 int32_t Val = CE->getValue();
3558 if (isNegative && Val == 0)
3559 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan7ad0ad02010-04-02 22:27:05 +00003560 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00003561 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3562 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00003563 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003564 case AsmToken::Colon: {
3565 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00003566 // FIXME: Check it's an expression prefix,
3567 // e.g. (FOO - :lower16:BAR) isn't legal.
3568 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003569 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003570 return true;
3571
Evan Cheng965b3c72011-01-13 07:58:56 +00003572 const MCExpr *SubExprVal;
3573 if (getParser().ParseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00003574 return true;
3575
Evan Cheng965b3c72011-01-13 07:58:56 +00003576 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3577 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00003578 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00003579 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00003580 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003581 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00003582 }
3583}
3584
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003585// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00003586// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003587bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00003588 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003589
3590 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00003591 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00003592 Parser.Lex(); // Eat ':'
3593
3594 if (getLexer().isNot(AsmToken::Identifier)) {
3595 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3596 return true;
3597 }
3598
3599 StringRef IDVal = Parser.getTok().getIdentifier();
3600 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003601 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003602 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00003603 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00003604 } else {
3605 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3606 return true;
3607 }
3608 Parser.Lex();
3609
3610 if (getLexer().isNot(AsmToken::Colon)) {
3611 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3612 return true;
3613 }
3614 Parser.Lex(); // Eat the last ':'
3615 return false;
3616}
3617
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003618/// \brief Given a mnemonic, split out possible predication code and carry
3619/// setting letters to form a canonical mnemonic and flags.
3620//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003621// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003622// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003623StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003624 unsigned &PredicationCode,
3625 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003626 unsigned &ProcessorIMod,
3627 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003628 PredicationCode = ARMCC::AL;
3629 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003630 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003631
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003632 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003633 //
3634 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003635 if ((Mnemonic == "movs" && isThumb()) ||
3636 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3637 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3638 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3639 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3640 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3641 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3642 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003643 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003644
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003645 // First, split out any predication code. Ignore mnemonics we know aren't
3646 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00003647 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00003648 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00003649 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00003650 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00003651 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3652 .Case("eq", ARMCC::EQ)
3653 .Case("ne", ARMCC::NE)
3654 .Case("hs", ARMCC::HS)
3655 .Case("cs", ARMCC::HS)
3656 .Case("lo", ARMCC::LO)
3657 .Case("cc", ARMCC::LO)
3658 .Case("mi", ARMCC::MI)
3659 .Case("pl", ARMCC::PL)
3660 .Case("vs", ARMCC::VS)
3661 .Case("vc", ARMCC::VC)
3662 .Case("hi", ARMCC::HI)
3663 .Case("ls", ARMCC::LS)
3664 .Case("ge", ARMCC::GE)
3665 .Case("lt", ARMCC::LT)
3666 .Case("gt", ARMCC::GT)
3667 .Case("le", ARMCC::LE)
3668 .Case("al", ARMCC::AL)
3669 .Default(~0U);
3670 if (CC != ~0U) {
3671 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3672 PredicationCode = CC;
3673 }
Bill Wendling193961b2010-10-29 23:50:21 +00003674 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003675
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003676 // Next, determine if we have a carry setting bit. We explicitly ignore all
3677 // the instructions we know end in 's'.
3678 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00003679 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00003680 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3681 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3682 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00003683 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3684 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003685 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3686 CarrySetting = true;
3687 }
3688
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003689 // The "cps" instruction can have a interrupt mode operand which is glued into
3690 // the mnemonic. Check if this is the case, split it and parse the imod op
3691 if (Mnemonic.startswith("cps")) {
3692 // Split out any imod code.
3693 unsigned IMod =
3694 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3695 .Case("ie", ARM_PROC::IE)
3696 .Case("id", ARM_PROC::ID)
3697 .Default(~0U);
3698 if (IMod != ~0U) {
3699 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3700 ProcessorIMod = IMod;
3701 }
3702 }
3703
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003704 // The "it" instruction has the condition mask on the end of the mnemonic.
3705 if (Mnemonic.startswith("it")) {
3706 ITMask = Mnemonic.slice(2, Mnemonic.size());
3707 Mnemonic = Mnemonic.slice(0, 2);
3708 }
3709
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003710 return Mnemonic;
3711}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003712
3713/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3714/// inclusion of carry set or predication code operands.
3715//
3716// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003717void ARMAsmParser::
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003718getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00003719 bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003720 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3721 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003722 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003723 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003724 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00003725 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003726 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00003727 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00003728 Mnemonic == "mla" || Mnemonic == "smlal" ||
3729 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00003730 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003731 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00003732 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003733
Daniel Dunbar09264122011-01-11 19:06:29 +00003734 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3735 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3736 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3737 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbach803898f2011-09-06 20:27:04 +00003738 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3739 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach25977222011-08-19 23:24:36 +00003740 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach93981412011-10-11 21:55:36 +00003741 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3742 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3743 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbachb9d4e372011-08-26 22:21:51 +00003744 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3745 !isThumb()) ||
Jim Grosbachb908b7a2011-09-10 00:15:36 +00003746 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003747 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003748 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003749 CanAcceptPredicationCode = true;
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003750
Jim Grosbach6c45b752011-09-16 16:39:25 +00003751 if (isThumb()) {
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003752 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbachb98ab912011-06-30 22:10:46 +00003753 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopescf99dc72011-01-20 16:35:57 +00003754 CanAcceptPredicationCode = false;
Jim Grosbach6c45b752011-09-16 16:39:25 +00003755 }
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003756}
3757
Jim Grosbach7283da92011-08-16 21:12:37 +00003758bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3759 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003760 // FIXME: This is all horribly hacky. We really need a better way to deal
3761 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00003762
3763 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3764 // another does not. Specifically, the MOVW instruction does not. So we
3765 // special case it here and remove the defaulted (non-setting) cc_out
3766 // operand if that's the instruction we're trying to match.
3767 //
3768 // We do this as post-processing of the explicit operands rather than just
3769 // conditionally adding the cc_out in the first place because we need
3770 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00003771 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbach7283da92011-08-16 21:12:37 +00003772 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3773 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3774 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3775 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00003776
3777 // Register-register 'add' for thumb does not have a cc_out operand
3778 // when there are only two register operands.
3779 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3780 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3781 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3782 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3783 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003784 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003785 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3786 // have to check the immediate range here since Thumb2 has a variant
3787 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003788 if (((isThumb() && Mnemonic == "add") ||
3789 (isThumbTwo() && Mnemonic == "sub")) &&
3790 Operands.size() == 6 &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003791 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3792 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3793 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003794 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3795 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3796 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003797 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003798 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3799 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003800 // selecting via the generic "add" mnemonic, so to know that we
3801 // should remove the cc_out operand, we have to explicitly check that
3802 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00003803 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3804 Operands.size() == 6 &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003805 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3806 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3807 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3808 // Nest conditions rather than one big 'if' statement for readability.
3809 //
3810 // If either register is a high reg, it's either one of the SP
3811 // variants (handled above) or a 32-bit encoding, so we just
3812 // check against T3.
3813 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3814 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3815 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3816 return false;
3817 // If both registers are low, we're in an IT block, and the immediate is
3818 // in range, we should use encoding T1 instead, which has a cc_out.
3819 if (inITBlock() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00003820 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003821 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3822 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3823 return false;
3824
3825 // Otherwise, we use encoding T4, which does not have a cc_out
3826 // operand.
3827 return true;
3828 }
3829
Jim Grosbach9c8b9932011-09-14 21:00:40 +00003830 // The thumb2 multiply instruction doesn't have a CCOut register, so
3831 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3832 // use the 16-bit encoding or not.
3833 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3834 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3835 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3836 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3837 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3838 // If the registers aren't low regs, the destination reg isn't the
3839 // same as one of the source regs, or the cc_out operand is zero
3840 // outside of an IT block, we have to use the 32-bit encoding, so
3841 // remove the cc_out operand.
3842 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3843 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3844 !inITBlock() ||
3845 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3846 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3847 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3848 static_cast<ARMOperand*>(Operands[4])->getReg())))
3849 return true;
3850
3851
Jim Grosbach1d3c1372011-09-01 00:28:52 +00003852
Jim Grosbach4b701af2011-08-24 21:42:27 +00003853 // Register-register 'add/sub' for thumb does not have a cc_out operand
3854 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3855 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3856 // right, this will result in better diagnostics (which operand is off)
3857 // anyway.
3858 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3859 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach0a0b3072011-08-24 21:22:15 +00003860 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3861 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3862 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3863 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00003864
Jim Grosbach7283da92011-08-16 21:12:37 +00003865 return false;
3866}
3867
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003868/// Parse an arm instruction mnemonic followed by its operands.
3869bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3870 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3871 // Create the leading tokens for the mnemonic, split by '.' characters.
3872 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003873 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003874
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003875 // Split out the predication code and carry setting flag from the mnemonic.
3876 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003877 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00003878 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003879 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003880 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003881 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003882
Jim Grosbach1c171b12011-08-25 17:23:55 +00003883 // In Thumb1, only the branch (B) instruction can be predicated.
3884 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3885 Parser.EatToEndOfStatement();
3886 return Error(NameLoc, "conditional execution not supported in Thumb1");
3887 }
3888
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003889 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3890
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003891 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3892 // is the mask as it will be for the IT encoding if the conditional
3893 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3894 // where the conditional bit0 is zero, the instruction post-processing
3895 // will adjust the mask accordingly.
3896 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00003897 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3898 if (ITMask.size() > 3) {
3899 Parser.EatToEndOfStatement();
3900 return Error(Loc, "too many conditions on IT instruction");
3901 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003902 unsigned Mask = 8;
3903 for (unsigned i = ITMask.size(); i != 0; --i) {
3904 char pos = ITMask[i - 1];
3905 if (pos != 't' && pos != 'e') {
3906 Parser.EatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00003907 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003908 }
3909 Mask >>= 1;
3910 if (ITMask[i - 1] == 't')
3911 Mask |= 8;
3912 }
Jim Grosbached16ec42011-08-29 22:24:09 +00003913 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003914 }
3915
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003916 // FIXME: This is all a pretty gross hack. We should automatically handle
3917 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00003918
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003919 // Next, add the CCOut and ConditionCode operands, if needed.
3920 //
3921 // For mnemonics which can ever incorporate a carry setting bit or predication
3922 // code, our matching model involves us always generating CCOut and
3923 // ConditionCode operands to match the mnemonic "as written" and then we let
3924 // the matcher deal with finding the right instruction or generating an
3925 // appropriate error.
3926 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003927 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003928
Jim Grosbach03a8a162011-07-14 22:04:21 +00003929 // If we had a carry-set on an instruction that can't do that, issue an
3930 // error.
3931 if (!CanAcceptCarrySet && CarrySetting) {
3932 Parser.EatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00003933 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00003934 "' can not set flags, but 's' suffix specified");
3935 }
Jim Grosbach0a547702011-07-22 17:44:50 +00003936 // If we had a predication code on an instruction that can't do that, issue an
3937 // error.
3938 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3939 Parser.EatToEndOfStatement();
3940 return Error(NameLoc, "instruction '" + Mnemonic +
3941 "' is not predicable, but condition code specified");
3942 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00003943
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003944 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00003945 if (CanAcceptCarrySet) {
3946 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003947 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00003948 Loc));
3949 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003950
3951 // Add the predication code operand, if necessary.
3952 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00003953 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3954 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00003955 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00003956 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00003957 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003958
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003959 // Add the processor imod operand, if necessary.
3960 if (ProcessorIMod) {
3961 Operands.push_back(ARMOperand::CreateImm(
3962 MCConstantExpr::Create(ProcessorIMod, getContext()),
3963 NameLoc, NameLoc));
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003964 }
3965
Daniel Dunbar188b47b2010-08-11 06:37:20 +00003966 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003967 while (Next != StringRef::npos) {
3968 Start = Next;
3969 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003970 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003971
Jim Grosbach838ed3a2011-08-24 22:19:48 +00003972 // For now, we're only parsing Thumb1 (for the most part), so
3973 // just ignore ".n" qualifiers. We'll use them to restrict
3974 // matching when we do Thumb2.
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00003975 if (ExtraToken != ".n") {
3976 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3977 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3978 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00003979 }
3980
3981 // Read the remaining operands.
3982 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003983 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003984 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00003985 Parser.EatToEndOfStatement();
3986 return true;
3987 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003988
3989 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00003990 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003991
3992 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003993 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnera2a9d162010-09-11 16:18:25 +00003994 Parser.EatToEndOfStatement();
3995 return true;
3996 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003997 }
3998 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00003999
Chris Lattnera2a9d162010-09-11 16:18:25 +00004000 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004001 SMLoc Loc = getLexer().getLoc();
Chris Lattnera2a9d162010-09-11 16:18:25 +00004002 Parser.EatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00004003 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00004004 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004005
Chris Lattner91689c12010-09-08 05:10:46 +00004006 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004007
Jim Grosbach7283da92011-08-16 21:12:37 +00004008 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4009 // do and don't have a cc_out optional-def operand. With some spot-checks
4010 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00004011 // parse and adjust accordingly before actually matching. We shouldn't ever
4012 // try to remove a cc_out operand that was explicitly set on the the
4013 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4014 // table driven matcher doesn't fit well with the ARM instruction set.
4015 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00004016 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4017 Operands.erase(Operands.begin() + 1);
4018 delete Op;
4019 }
4020
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004021 // ARM mode 'blx' need special handling, as the register operand version
4022 // is predicable, but the label operand version is not. So, we can't rely
4023 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00004024 // a k_CondCode operand in the list. If we're trying to match the label
4025 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00004026 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4027 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4028 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4029 Operands.erase(Operands.begin() + 1);
4030 delete Op;
4031 }
Jim Grosbach8cffa282011-08-11 23:51:13 +00004032
4033 // The vector-compare-to-zero instructions have a literal token "#0" at
4034 // the end that comes to here as an immediate operand. Convert it to a
4035 // token to play nicely with the matcher.
4036 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4037 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4038 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4039 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4041 if (CE && CE->getValue() == 0) {
4042 Operands.erase(Operands.begin() + 5);
4043 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4044 delete Op;
4045 }
4046 }
Jim Grosbach46b66462011-10-03 22:30:24 +00004047 // VCMP{E} does the same thing, but with a different operand count.
4048 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4049 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4050 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4051 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4052 if (CE && CE->getValue() == 0) {
4053 Operands.erase(Operands.begin() + 4);
4054 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4055 delete Op;
4056 }
4057 }
Jim Grosbachc3c32d92011-08-22 23:47:13 +00004058 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4059 // end. Convert it to a token here.
4060 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4061 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4062 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4063 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4064 if (CE && CE->getValue() == 0) {
4065 Operands.erase(Operands.begin() + 5);
4066 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4067 delete Op;
4068 }
4069 }
4070
Chris Lattnerf29c0b62010-01-14 22:21:20 +00004071 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00004072}
4073
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004074// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004075
4076// return 'true' if register list contains non-low GPR registers,
4077// 'false' otherwise. If Reg is in the register list or is HiReg, set
4078// 'containsReg' to true.
4079static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4080 unsigned HiReg, bool &containsReg) {
4081 containsReg = false;
4082 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4083 unsigned OpReg = Inst.getOperand(i).getReg();
4084 if (OpReg == Reg)
4085 containsReg = true;
4086 // Anything other than a low register isn't legal here.
4087 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4088 return true;
4089 }
4090 return false;
4091}
4092
Jim Grosbacha31f2232011-09-07 18:05:34 +00004093// Check if the specified regisgter is in the register list of the inst,
4094// starting at the indicated operand number.
4095static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4096 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4097 unsigned OpReg = Inst.getOperand(i).getReg();
4098 if (OpReg == Reg)
4099 return true;
4100 }
4101 return false;
4102}
4103
Jim Grosbached16ec42011-08-29 22:24:09 +00004104// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4105// the ARMInsts array) instead. Getting that here requires awkward
4106// API changes, though. Better way?
4107namespace llvm {
4108extern MCInstrDesc ARMInsts[];
4109}
4110static MCInstrDesc &getInstDesc(unsigned Opcode) {
4111 return ARMInsts[Opcode];
4112}
4113
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004114// FIXME: We would really like to be able to tablegen'erate this.
4115bool ARMAsmParser::
4116validateInstruction(MCInst &Inst,
4117 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004118 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4119 SMLoc Loc = Operands[0]->getStartLoc();
4120 // Check the IT block state first.
Owen Anderson44ae2da2011-09-13 17:59:19 +00004121 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4122 // being allowed in IT blocks, but not being predicable. It just always
4123 // executes.
4124 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbached16ec42011-08-29 22:24:09 +00004125 unsigned bit = 1;
4126 if (ITState.FirstCond)
4127 ITState.FirstCond = false;
4128 else
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004129 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00004130 // The instruction must be predicable.
4131 if (!MCID.isPredicable())
4132 return Error(Loc, "instructions in IT block must be predicable");
4133 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4134 unsigned ITCond = bit ? ITState.Cond :
4135 ARMCC::getOppositeCondition(ITState.Cond);
4136 if (Cond != ITCond) {
4137 // Find the condition code Operand to get its SMLoc information.
4138 SMLoc CondLoc;
4139 for (unsigned i = 1; i < Operands.size(); ++i)
4140 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4141 CondLoc = Operands[i]->getStartLoc();
4142 return Error(CondLoc, "incorrect condition in IT block; got '" +
4143 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4144 "', but expected '" +
4145 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4146 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00004147 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004148 } else if (isThumbTwo() && MCID.isPredicable() &&
4149 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004150 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4151 Inst.getOpcode() != ARM::t2B)
Jim Grosbached16ec42011-08-29 22:24:09 +00004152 return Error(Loc, "predicated instructions must be in IT block");
4153
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004154 switch (Inst.getOpcode()) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00004155 case ARM::LDRD:
4156 case ARM::LDRD_PRE:
4157 case ARM::LDRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004158 case ARM::LDREXD: {
4159 // Rt2 must be Rt + 1.
4160 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4161 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4162 if (Rt2 != Rt + 1)
4163 return Error(Operands[3]->getStartLoc(),
4164 "destination operands must be sequential");
4165 return false;
4166 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00004167 case ARM::STRD: {
4168 // Rt2 must be Rt + 1.
4169 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4170 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4171 if (Rt2 != Rt + 1)
4172 return Error(Operands[3]->getStartLoc(),
4173 "source operands must be sequential");
4174 return false;
4175 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00004176 case ARM::STRD_PRE:
4177 case ARM::STRD_POST:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004178 case ARM::STREXD: {
4179 // Rt2 must be Rt + 1.
4180 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4181 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4182 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00004183 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004184 "source operands must be sequential");
4185 return false;
4186 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00004187 case ARM::SBFX:
4188 case ARM::UBFX: {
4189 // width must be in range [1, 32-lsb]
4190 unsigned lsb = Inst.getOperand(2).getImm();
4191 unsigned widthm1 = Inst.getOperand(3).getImm();
4192 if (widthm1 >= 32 - lsb)
4193 return Error(Operands[5]->getStartLoc(),
4194 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00004195 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00004196 }
Jim Grosbach90103cc2011-08-18 21:50:53 +00004197 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00004198 // If we're parsing Thumb2, the .w variant is available and handles
4199 // most cases that are normally illegal for a Thumb1 LDM
4200 // instruction. We'll make the transformation in processInstruction()
4201 // if necessary.
4202 //
Jim Grosbach90103cc2011-08-18 21:50:53 +00004203 // Thumb LDM instructions are writeback iff the base register is not
4204 // in the register list.
4205 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach139acd22011-08-22 23:01:07 +00004206 bool hasWritebackToken =
4207 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4208 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbach169b2be2011-08-23 18:13:04 +00004209 bool listContainsBase;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004210 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00004211 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4212 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004213 // If we should have writeback, then there should be a '!' token.
Jim Grosbacha31f2232011-09-07 18:05:34 +00004214 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00004215 return Error(Operands[2]->getStartLoc(),
4216 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00004217 // If we should not have writeback, there must not be a '!'. This is
4218 // true even for the 32-bit wide encodings.
Jim Grosbach169b2be2011-08-23 18:13:04 +00004219 if (listContainsBase && hasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00004220 return Error(Operands[3]->getStartLoc(),
4221 "writeback operator '!' not allowed when base register "
4222 "in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00004223
4224 break;
4225 }
Jim Grosbacha31f2232011-09-07 18:05:34 +00004226 case ARM::t2LDMIA_UPD: {
4227 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4228 return Error(Operands[4]->getStartLoc(),
4229 "writeback operator '!' not allowed when base register "
4230 "in register list");
4231 break;
4232 }
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004233 case ARM::tPOP: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004234 bool listContainsBase;
4235 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4236 return Error(Operands[2]->getStartLoc(),
4237 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004238 break;
4239 }
4240 case ARM::tPUSH: {
Jim Grosbach169b2be2011-08-23 18:13:04 +00004241 bool listContainsBase;
4242 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4243 return Error(Operands[2]->getStartLoc(),
4244 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00004245 break;
4246 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00004247 case ARM::tSTMIA_UPD: {
4248 bool listContainsBase;
Jim Grosbach099c9762011-09-16 20:50:13 +00004249 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00004250 return Error(Operands[4]->getStartLoc(),
4251 "registers must be in range r0-r7");
4252 break;
4253 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004254 }
4255
4256 return false;
4257}
4258
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004259void ARMAsmParser::
4260processInstruction(MCInst &Inst,
4261 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4262 switch (Inst.getOpcode()) {
4263 case ARM::LDMIA_UPD:
4264 // If this is a load of a single register via a 'pop', then we should use
4265 // a post-indexed LDR instruction instead, per the ARM ARM.
4266 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4267 Inst.getNumOperands() == 5) {
4268 MCInst TmpInst;
4269 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4270 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4271 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4272 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4273 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4274 TmpInst.addOperand(MCOperand::CreateImm(4));
4275 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4276 TmpInst.addOperand(Inst.getOperand(3));
4277 Inst = TmpInst;
4278 }
4279 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00004280 case ARM::STMDB_UPD:
4281 // If this is a store of a single register via a 'push', then we should use
4282 // a pre-indexed STR instruction instead, per the ARM ARM.
4283 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4284 Inst.getNumOperands() == 5) {
4285 MCInst TmpInst;
4286 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4287 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4288 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4289 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4290 TmpInst.addOperand(MCOperand::CreateImm(-4));
4291 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4292 TmpInst.addOperand(Inst.getOperand(3));
4293 Inst = TmpInst;
4294 }
4295 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004296 case ARM::tADDi8:
Jim Grosbach6d606fb2011-08-31 17:07:33 +00004297 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4298 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4299 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4300 // to encoding T1 if <Rd> is omitted."
4301 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbache9ab47a2011-08-16 23:57:34 +00004302 Inst.setOpcode(ARM::tADDi3);
4303 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00004304 case ARM::tSUBi8:
4305 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4306 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4307 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4308 // to encoding T1 if <Rd> is omitted."
4309 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4310 Inst.setOpcode(ARM::tSUBi3);
4311 break;
Owen Anderson29cfe6c2011-09-09 21:48:23 +00004312 case ARM::tB:
4313 // A Thumb conditional branch outside of an IT block is a tBcc.
4314 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4315 Inst.setOpcode(ARM::tBcc);
4316 break;
4317 case ARM::t2B:
4318 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4319 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4320 Inst.setOpcode(ARM::t2Bcc);
4321 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00004322 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004323 // If the conditional is AL or we're in an IT block, we really want t2B.
4324 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbach99bc8462011-08-31 21:17:31 +00004325 Inst.setOpcode(ARM::t2B);
4326 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00004327 case ARM::tBcc:
4328 // If the conditional is AL, we really want tB.
4329 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4330 Inst.setOpcode(ARM::tB);
Jim Grosbach6ddb5682011-08-18 16:08:39 +00004331 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00004332 case ARM::tLDMIA: {
4333 // If the register list contains any high registers, or if the writeback
4334 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4335 // instead if we're in Thumb2. Otherwise, this should have generated
4336 // an error in validateInstruction().
4337 unsigned Rn = Inst.getOperand(0).getReg();
4338 bool hasWritebackToken =
4339 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4340 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4341 bool listContainsBase;
4342 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4343 (!listContainsBase && !hasWritebackToken) ||
4344 (listContainsBase && hasWritebackToken)) {
4345 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4346 assert (isThumbTwo());
4347 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4348 // If we're switching to the updating version, we need to insert
4349 // the writeback tied operand.
4350 if (hasWritebackToken)
4351 Inst.insert(Inst.begin(),
4352 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4353 }
4354 break;
4355 }
Jim Grosbach099c9762011-09-16 20:50:13 +00004356 case ARM::tSTMIA_UPD: {
4357 // If the register list contains any high registers, we need to use
4358 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4359 // should have generated an error in validateInstruction().
4360 unsigned Rn = Inst.getOperand(0).getReg();
4361 bool listContainsBase;
4362 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4363 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4364 assert (isThumbTwo());
4365 Inst.setOpcode(ARM::t2STMIA_UPD);
4366 }
4367 break;
4368 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004369 case ARM::t2MOVi: {
4370 // If we can use the 16-bit encoding and the user didn't explicitly
4371 // request the 32-bit variant, transform it here.
4372 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4373 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00004374 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4375 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4376 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbachb908b7a2011-09-10 00:15:36 +00004377 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4378 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4379 // The operands aren't in the same order for tMOVi8...
4380 MCInst TmpInst;
4381 TmpInst.setOpcode(ARM::tMOVi8);
4382 TmpInst.addOperand(Inst.getOperand(0));
4383 TmpInst.addOperand(Inst.getOperand(4));
4384 TmpInst.addOperand(Inst.getOperand(1));
4385 TmpInst.addOperand(Inst.getOperand(2));
4386 TmpInst.addOperand(Inst.getOperand(3));
4387 Inst = TmpInst;
4388 }
4389 break;
4390 }
4391 case ARM::t2MOVr: {
4392 // If we can use the 16-bit encoding and the user didn't explicitly
4393 // request the 32-bit variant, transform it here.
4394 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4395 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4396 Inst.getOperand(2).getImm() == ARMCC::AL &&
4397 Inst.getOperand(4).getReg() == ARM::CPSR &&
4398 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4399 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4400 // The operands aren't the same for tMOV[S]r... (no cc_out)
4401 MCInst TmpInst;
4402 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4403 TmpInst.addOperand(Inst.getOperand(0));
4404 TmpInst.addOperand(Inst.getOperand(1));
4405 TmpInst.addOperand(Inst.getOperand(2));
4406 TmpInst.addOperand(Inst.getOperand(3));
4407 Inst = TmpInst;
4408 }
4409 break;
4410 }
Jim Grosbach82213192011-09-19 20:29:33 +00004411 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00004412 case ARM::t2SXTB:
4413 case ARM::t2UXTH:
4414 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00004415 // If we can use the 16-bit encoding and the user didn't explicitly
4416 // request the 32-bit variant, transform it here.
4417 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4418 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4419 Inst.getOperand(2).getImm() == 0 &&
4420 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4421 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00004422 unsigned NewOpc;
4423 switch (Inst.getOpcode()) {
4424 default: llvm_unreachable("Illegal opcode!");
4425 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4426 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4427 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4428 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4429 }
Jim Grosbach82213192011-09-19 20:29:33 +00004430 // The operands aren't the same for thumb1 (no rotate operand).
4431 MCInst TmpInst;
4432 TmpInst.setOpcode(NewOpc);
4433 TmpInst.addOperand(Inst.getOperand(0));
4434 TmpInst.addOperand(Inst.getOperand(1));
4435 TmpInst.addOperand(Inst.getOperand(3));
4436 TmpInst.addOperand(Inst.getOperand(4));
4437 Inst = TmpInst;
4438 }
4439 break;
4440 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004441 case ARM::t2IT: {
4442 // The mask bits for all but the first condition are represented as
4443 // the low bit of the condition code value implies 't'. We currently
4444 // always have 1 implies 't', so XOR toggle the bits if the low bit
4445 // of the condition code is zero. The encoding also expects the low
4446 // bit of the condition to be encoded as bit 4 of the mask operand,
4447 // so mask that in if needed
4448 MCOperand &MO = Inst.getOperand(1);
4449 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00004450 unsigned OrigMask = Mask;
4451 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004452 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004453 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4454 for (unsigned i = 3; i != TZ; --i)
4455 Mask ^= 1 << i;
4456 } else
4457 Mask |= 0x10;
4458 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00004459
4460 // Set up the IT block state according to the IT instruction we just
4461 // matched.
4462 assert(!inITBlock() && "nested IT blocks?!");
4463 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4464 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4465 ITState.CurPosition = 0;
4466 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00004467 break;
4468 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004469 }
4470}
4471
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004472unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4473 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4474 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004475 unsigned Opc = Inst.getOpcode();
4476 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004477 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4478 assert(MCID.hasOptionalDef() &&
4479 "optionally flag setting instruction missing optional def operand");
4480 assert(MCID.NumOperands == Inst.getNumOperands() &&
4481 "operand count mismatch!");
4482 // Find the optional-def operand (cc_out).
4483 unsigned OpNo;
4484 for (OpNo = 0;
4485 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4486 ++OpNo)
4487 ;
4488 // If we're parsing Thumb1, reject it completely.
4489 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4490 return Match_MnemonicFail;
4491 // If we're parsing Thumb2, which form is legal depends on whether we're
4492 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00004493 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4494 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004495 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00004496 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4497 inITBlock())
4498 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004499 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004500 // Some high-register supporting Thumb1 encodings only allow both registers
4501 // to be from r0-r7 when in Thumb2.
4502 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4503 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4504 isARMLowRegister(Inst.getOperand(2).getReg()))
4505 return Match_RequiresThumb2;
4506 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00004507 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004508 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4509 isARMLowRegister(Inst.getOperand(1).getReg()))
4510 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004511 return Match_Success;
4512}
4513
Chris Lattner9487de62010-10-28 21:28:01 +00004514bool ARMAsmParser::
4515MatchAndEmitInstruction(SMLoc IDLoc,
4516 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4517 MCStreamer &Out) {
4518 MCInst Inst;
4519 unsigned ErrorInfo;
Jim Grosbach120a96a2011-08-15 23:03:29 +00004520 unsigned MatchResult;
Kevin Enderby3164a342010-12-09 19:19:43 +00004521 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby3164a342010-12-09 19:19:43 +00004522 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00004523 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004524 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004525 // Context sensitive operand constraints aren't handled by the matcher,
4526 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004527 if (validateInstruction(Inst, Operands)) {
4528 // Still progress the IT block, otherwise one wrong condition causes
4529 // nasty cascading errors.
4530 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004531 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004532 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00004533
Jim Grosbach8ba76c62011-08-11 17:35:48 +00004534 // Some instructions need post-processing to, for example, tweak which
4535 // encoding is selected.
4536 processInstruction(Inst, Operands);
4537
Jim Grosbacha0d34d32011-09-02 23:22:08 +00004538 // Only move forward at the very end so that everything in validate
4539 // and process gets a consistent answer about whether we're in an IT
4540 // block.
4541 forwardITPosition();
4542
Chris Lattner9487de62010-10-28 21:28:01 +00004543 Out.EmitInstruction(Inst);
4544 return false;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004545 case Match_MissingFeature:
4546 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4547 return true;
4548 case Match_InvalidOperand: {
4549 SMLoc ErrorLoc = IDLoc;
4550 if (ErrorInfo != ~0U) {
4551 if (ErrorInfo >= Operands.size())
4552 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00004553
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004554 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4555 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4556 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004557
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004558 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00004559 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004560 case Match_MnemonicFail:
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004561 return Error(IDLoc, "invalid instruction");
Daniel Dunbar66193402011-02-04 17:12:23 +00004562 case Match_ConversionFail:
Jim Grosbach8e048492011-08-19 22:07:46 +00004563 // The converter function will have already emited a diagnostic.
4564 return true;
Jim Grosbached16ec42011-08-29 22:24:09 +00004565 case Match_RequiresNotITBlock:
4566 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00004567 case Match_RequiresITBlock:
4568 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00004569 case Match_RequiresV6:
4570 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4571 case Match_RequiresThumb2:
4572 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnerd27b05e2010-10-28 21:41:58 +00004573 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00004574
Eric Christopher91d7b902010-10-29 09:26:59 +00004575 llvm_unreachable("Implement any new match types added!");
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004576 return true;
Chris Lattner9487de62010-10-28 21:28:01 +00004577}
4578
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004579/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00004580bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4581 StringRef IDVal = DirectiveID.getIdentifier();
4582 if (IDVal == ".word")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004583 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004584 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004585 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004586 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004587 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004588 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004589 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00004590 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004591 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyccab3172009-09-15 00:27:25 +00004592 return true;
4593}
4594
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004595/// parseDirectiveWord
Kevin Enderbyccab3172009-09-15 00:27:25 +00004596/// ::= .word [ expression (, expression)* ]
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004597bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00004598 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4599 for (;;) {
4600 const MCExpr *Value;
4601 if (getParser().ParseExpression(Value))
4602 return true;
4603
Chris Lattnerc35681b2010-01-19 19:46:13 +00004604 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyccab3172009-09-15 00:27:25 +00004605
4606 if (getLexer().is(AsmToken::EndOfStatement))
4607 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00004608
Kevin Enderbyccab3172009-09-15 00:27:25 +00004609 // FIXME: Improve diagnostic.
4610 if (getLexer().isNot(AsmToken::Comma))
4611 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004612 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004613 }
4614 }
4615
Sean Callanana83fd7d2010-01-19 20:27:46 +00004616 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004617 return false;
4618}
4619
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004620/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00004621/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004622bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby146dcf22009-10-15 20:48:48 +00004623 if (getLexer().isNot(AsmToken::EndOfStatement))
4624 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004625 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004626
4627 // TODO: set thumb mode
4628 // TODO: tell the MC streamer the mode
4629 // getParser().getStreamer().Emit???();
4630 return false;
4631}
4632
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004633/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00004634/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004635bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004636 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4637 bool isMachO = MAI.hasSubsectionsViaSymbols();
4638 StringRef Name;
4639
4640 // Darwin asm has function name after .thumb_func direction
4641 // ELF doesn't
4642 if (isMachO) {
4643 const AsmToken &Tok = Parser.getTok();
4644 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4645 return Error(L, "unexpected token in .thumb_func directive");
4646 Name = Tok.getString();
4647 Parser.Lex(); // Consume the identifier token.
4648 }
4649
Kevin Enderby146dcf22009-10-15 20:48:48 +00004650 if (getLexer().isNot(AsmToken::EndOfStatement))
4651 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004652 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004653
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00004654 // FIXME: assuming function name will be the line following .thumb_func
4655 if (!isMachO) {
4656 Name = Parser.getTok().getString();
4657 }
4658
Jim Grosbachc6db8ce2010-11-05 22:33:53 +00004659 // Mark symbol as a thumb symbol.
4660 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4661 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby146dcf22009-10-15 20:48:48 +00004662 return false;
4663}
4664
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004665/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00004666/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004667bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004668 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004669 if (Tok.isNot(AsmToken::Identifier))
4670 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer92d89982010-07-14 22:38:02 +00004671 StringRef Mode = Tok.getString();
Duncan Sands257eba42010-06-29 13:04:35 +00004672 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callanana83fd7d2010-01-19 20:27:46 +00004673 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004674 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderbye9f2f0c2011-01-27 23:22:36 +00004675 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby146dcf22009-10-15 20:48:48 +00004676 else
4677 return Error(L, "unrecognized syntax mode in .syntax directive");
4678
4679 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004680 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004681 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004682
4683 // TODO tell the MC streamer the mode
4684 // getParser().getStreamer().Emit???();
4685 return false;
4686}
4687
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004688/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00004689/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004690bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00004691 const AsmToken &Tok = Parser.getTok();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004692 if (Tok.isNot(AsmToken::Integer))
4693 return Error(L, "unexpected token in .code directive");
Sean Callanan936b0d32010-01-19 21:44:56 +00004694 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands257eba42010-06-29 13:04:35 +00004695 if (Val == 16)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004696 Parser.Lex();
Duncan Sands257eba42010-06-29 13:04:35 +00004697 else if (Val == 32)
Sean Callanana83fd7d2010-01-19 20:27:46 +00004698 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004699 else
4700 return Error(L, "invalid operand to .code directive");
4701
4702 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan936b0d32010-01-19 21:44:56 +00004703 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004704 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00004705
Evan Cheng284b4672011-07-08 22:36:29 +00004706 if (Val == 16) {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004707 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004708 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004709 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00004710 } else {
Jim Grosbachf471ac32011-09-06 18:46:23 +00004711 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00004712 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00004713 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00004714 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00004715
Kevin Enderby146dcf22009-10-15 20:48:48 +00004716 return false;
4717}
4718
Sean Callanan643a5572010-04-07 20:29:34 +00004719extern "C" void LLVMInitializeARMAsmLexer();
4720
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004721/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00004722extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng11424442011-07-26 00:24:13 +00004723 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4724 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan643a5572010-04-07 20:29:34 +00004725 LLVMInitializeARMAsmLexer();
Kevin Enderbyccab3172009-09-15 00:27:25 +00004726}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004727
Chris Lattner3e4582a2010-09-06 19:11:01 +00004728#define GET_REGISTER_MATCHER
4729#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00004730#include "ARMGenAsmMatcher.inc"