blob: 4f904aa219f848bc2b145697ff9d1605a2ce9eec [file] [log] [blame]
Kevin Enderbyca9c42c2009-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 Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-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 Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-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 Grosbacha1109882011-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 Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-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 Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-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 Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-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 Grosbachc27d4f92011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbacha77295d2011-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 Grosbacheeec0252011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-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 Grosbach2fd2b872011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000200
201 bool validateInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000203 void processInstruction(MCInst &Inst,
204 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000205 bool shouldOmitCCOutOperand(StringRef Mnemonic,
206 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000207
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000208public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000209 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000210 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000211 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000212 Match_RequiresV6,
213 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000214 };
215
Evan Chengffc0e732011-07-09 05:47:46 +0000216 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000217 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000218 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000219
Evan Chengebdeeab2011-07-08 01:53:10 +0000220 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000221 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000222
223 // Not in an ITBlock to start with.
224 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000225 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000226
Jim Grosbach1355cf12011-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 Grosbach189610f2011-07-26 18:25:39 +0000230 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000231 bool ParseDirective(AsmToken DirectiveID);
232
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 unsigned checkTargetMatchPredicate(MCInst &Inst);
234
Jim Grosbach1355cf12011-07-26 17:10:22 +0000235 bool MatchAndEmitInstruction(SMLoc IDLoc,
236 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
237 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000238};
Jim Grosbach16c74252010-10-29 14:46:02 +0000239} // end anonymous namespace
240
Chris Lattner3a697562010-10-28 17:20:03 +0000241namespace {
242
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000243/// ARMOperand - Instances of this class represent a parsed ARM machine
244/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000245class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000246 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000247 k_CondCode,
248 k_CCOut,
249 k_ITCondMask,
250 k_CoprocNum,
251 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000252 k_CoprocOption,
Jim Grosbach21ff17c2011-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 Grosbach460a9052011-10-07 23:56:00 +0000260 k_VectorIndex,
Jim Grosbach21ff17c2011-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 Enderbya7ba3a82009-10-06 22:26:42 +0000271 } Kind;
272
Sean Callanan76264762010-04-02 22:27:05 +0000273 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000274 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000275
276 union {
277 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000278 ARMCC::CondCodes Val;
279 } CC;
280
281 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000282 unsigned Val;
283 } Cop;
284
285 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000286 unsigned Val;
287 } CoprocOption;
288
289 struct {
Jim Grosbach89df9962011-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 Lopesa2b6e412011-02-14 13:09:44 +0000298 ARM_PROC::IFlags Val;
299 } IFlags;
300
301 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000302 unsigned Val;
303 } MMask;
304
305 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000306 const char *Data;
307 unsigned Length;
308 } Tok;
309
310 struct {
311 unsigned RegNum;
312 } Reg;
313
Bill Wendling8155e5b2010-11-06 22:19:43 +0000314 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000315 unsigned Val;
316 } VectorIndex;
317
318 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000319 const MCExpr *Val;
320 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000321
Jim Grosbach9d390362011-10-03 23:38:36 +0000322 struct {
323 unsigned Val; // encoded 8-bit representation
324 } FPImm;
325
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000326 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 struct {
328 unsigned BaseRegNum;
Jim Grosbach7ce05792011-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 Grosbach57dcb852011-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 Grosbach7ce05792011-08-03 23:50:40 +0000337 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000338 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000339
340 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000341 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000342 bool isAdd;
343 ARM_AM::ShiftOpc ShiftTy;
344 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000345 } PostIdxReg;
346
347 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000348 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000349 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000350 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000351 struct {
352 ARM_AM::ShiftOpc ShiftTy;
353 unsigned SrcReg;
354 unsigned ShiftReg;
355 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000356 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000357 struct {
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned SrcReg;
360 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000361 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000362 struct {
363 unsigned Imm;
364 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000365 struct {
366 unsigned LSB;
367 unsigned Width;
368 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000369 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000370
Bill Wendling146018f2010-11-06 21:42:12 +0000371 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
372public:
Sean Callanan76264762010-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 Grosbach21ff17c2011-10-07 23:24:09 +0000378 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000379 CC = o.CC;
380 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000381 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000382 ITMask = o.ITMask;
383 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000384 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000385 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000386 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000387 case k_CCOut:
388 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000389 Reg = o.Reg;
390 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000391 case k_RegisterList:
392 case k_DPRRegisterList:
393 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000394 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_CoprocNum:
397 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000398 Cop = o.Cop;
399 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000400 case k_CoprocOption:
401 CoprocOption = o.CoprocOption;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000404 Imm = o.Imm;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000407 FPImm = o.FPImm;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000410 MBOpt = o.MBOpt;
411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000413 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000414 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000415 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000416 PostIdxReg = o.PostIdxReg;
417 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000418 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000419 MMask = o.MMask;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000422 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000425 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000428 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000431 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000434 RotImm = o.RotImm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000437 Bitfield = o.Bitfield;
438 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000439 case k_VectorIndex:
440 VectorIndex = o.VectorIndex;
441 break;
Sean Callanan76264762010-04-02 22:27:05 +0000442 }
443 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000444
Sean Callanan76264762010-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 Enderbya7ba3a82009-10-06 22:26:42 +0000449
Daniel Dunbar8462b302010-08-11 06:36:53 +0000450 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000452 return CC.Val;
453 }
454
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000455 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000457 return Cop.Val;
458 }
459
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000460 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000462 return StringRef(Tok.Data, Tok.Length);
463 }
464
465 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000466 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000467 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000468 }
469
Bill Wendling5fa22a12010-11-09 23:28:44 +0000470 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
472 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000473 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000474 }
475
Kevin Enderbycfe07242009-10-13 22:19:02 +0000476 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000477 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000478 return Imm.Val;
479 }
480
Jim Grosbach9d390362011-10-03 23:38:36 +0000481 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000483 return FPImm.Val;
484 }
485
Jim Grosbach460a9052011-10-07 23:56:00 +0000486 unsigned getVectorIndex() const {
487 assert(Kind == k_VectorIndex && "Invalid access!");
488 return VectorIndex.Val;
489 }
490
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000491 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000493 return MBOpt.Val;
494 }
495
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000496 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000498 return IFlags.Val;
499 }
500
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000501 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000502 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000503 return MMask.Val;
504 }
505
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 bool isCoprocNum() const { return Kind == k_CoprocNum; }
507 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000508 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-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 Grosbacha77295d2011-09-08 22:07:06 +0000515 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000516 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-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 Grosbach72f39f82011-08-24 21:22:15 +0000523 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-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 Grosbach21ff17c2011-10-07 23:24:09 +0000532 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-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 Grosbach6b8f1e32011-06-27 23:54:06 +0000539 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000540 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-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 Grosbach83ab0702011-07-13 22:01:08 +0000547 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000548 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-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 Grosbach21ff17c2011-10-07 23:24:09 +0000556 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-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 Grosbach7c6e42e2011-07-21 23:26:25 +0000563 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000564 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-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 Grosbachf4943352011-07-25 23:09:14 +0000571 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000572 if (Kind != k_Immediate)
Jim Grosbachf4943352011-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 Grosbach4a5ffb32011-07-22 23:16:18 +0000579 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000580 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-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 Grosbachfff76ee2011-07-13 20:10:10 +0000587 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000588 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-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 Grosbachffa32252011-07-19 19:13:28 +0000595 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000596 if (Kind != k_Immediate)
Jim Grosbachffa32252011-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 Grosbached838482011-07-26 16:24:27 +0000605 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbached838482011-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 Grosbach70939ee2011-08-17 21:51:27 +0000613 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-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 Grosbachf6c05252011-07-21 17:23:04 +0000621 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-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 Grosbach21ff17c2011-10-07 23:24:09 +0000630 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-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 Grosbach6bc1dbc2011-07-19 16:50:30 +0000637 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000638 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-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 Grosbach6b8f1e32011-06-27 23:54:06 +0000645 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000646 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-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 Grosbachc27d4f92011-07-22 17:44:50 +0000653 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000654 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-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 Grosbach21ff17c2011-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 Grosbachf4fa3d62011-08-05 21:28:30 +0000674 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000675 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000676 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000677 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000678 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000679 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000680 // No offset of any kind.
Jim Grosbach57dcb852011-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 Lopesae085542011-03-31 23:26:08 +0000686 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000687 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000688 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000689 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000690 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000691 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000692 if (!Memory.OffsetImm) return true;
693 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000694 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000695 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000696 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000697 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-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 Grosbach2fd2b872011-08-10 20:29:19 +0000705 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000706 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000707 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000708 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000709 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000710 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000711 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000712 if (!Memory.OffsetImm) return true;
713 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000714 return Val > -256 && Val < 256;
715 }
716 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000717 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000718 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-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 Grosbach251bf252011-08-10 21:56:18 +0000725 // Special case, #-0 is INT32_MIN.
726 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000727 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000728 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000729 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000730 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000731 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000732 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000733 if (!Memory.OffsetImm) return true;
734 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000735 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
736 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000737 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000738 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000739 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000740 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000741 return false;
742 return true;
743 }
744 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000745 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000746 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
747 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000748 return false;
749 return true;
750 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000751 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000752 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000753 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000754 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000755 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000756 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000757 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
758 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000759 return false;
760 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000761 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000762 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000763 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000764 return false;
765 return true;
766 }
Jim Grosbach7ce05792011-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 Grosbache53c87b2011-10-11 15:59:20 +0000770 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000771 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000772 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000773 return isARMLowRegister(Memory.BaseRegNum) &&
774 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000775 }
776 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000777 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000778 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000779 return false;
780 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000781 if (!Memory.OffsetImm) return true;
782 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000783 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
784 }
Jim Grosbach38466302011-08-19 18:55:51 +0000785 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000787 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000788 return false;
789 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000790 if (!Memory.OffsetImm) return true;
791 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000792 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
793 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000794 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000795 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000796 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000797 return false;
798 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000799 if (!Memory.OffsetImm) return true;
800 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000801 return Val >= 0 && Val <= 31;
802 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000803 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || Memory.OffsetRegNum != 0 ||
805 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000806 return false;
807 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (!Memory.OffsetImm) return true;
809 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000810 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000811 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000812 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000813 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000814 return false;
815 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000816 if (!Memory.OffsetImm) return true;
817 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000818 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
819 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000820 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000821 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000822 return false;
823 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (!Memory.OffsetImm) return true;
825 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000826 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
827 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000828 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000829 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 return false;
831 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000832 if (!Memory.OffsetImm) return true;
833 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000834 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000835 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000836 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000837 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000838 return false;
839 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000840 if (!Memory.OffsetImm) return true;
841 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000842 return Val >= 0 && Val < 256;
843 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000844 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000846 return false;
847 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000848 if (!Memory.OffsetImm) return true;
849 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-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 Grosbach21ff17c2011-10-07 23:24:09 +0000856 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000857 return true;
858
Jim Grosbach57dcb852011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000860 return false;
861 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000862 if (!Memory.OffsetImm) return true;
863 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000864 return (Val >= 0 && Val < 4096);
865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-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 Grosbach21ff17c2011-10-07 23:24:09 +0000870 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000871 return true;
872
Jim Grosbach57dcb852011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000874 return false;
875 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000876 if (!Memory.OffsetImm) return true;
877 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000878 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000879 }
880 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000881 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-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 Anderson63553c72011-08-29 17:17:09 +0000886 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000887 }
Jim Grosbach2bd01182011-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 Grosbach7ce05792011-08-03 23:50:40 +0000897
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000898 bool isMSRMask() const { return Kind == k_MSRMask; }
899 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000900
Jim Grosbach0e387b22011-10-17 22:26:03 +0000901 // NEON operands.
Jim Grosbach460a9052011-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 Grosbach0e387b22011-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 Grosbach0e387b22011-10-17 22:26:03 +0000924 return Value >= 0 && Value < 256;
925 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000926
Jim Grosbachea461102011-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 Grosbach6248a542011-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
Jim Grosbachf2f5bc62011-10-18 16:18:11 +0000969 bool isNEONi64splat() const {
970 if (Kind != k_Immediate)
971 return false;
972 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
973 // Must be a constant.
974 if (!CE) return false;
975 uint64_t Value = CE->getValue();
976 // i64 value with each byte being either 0 or 0xff.
977 for (unsigned i = 0; i < 8; ++i)
978 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
979 return true;
980 }
981
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000982 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000983 // Add as immediates when possible. Null MCExpr = 0.
984 if (Expr == 0)
985 Inst.addOperand(MCOperand::CreateImm(0));
986 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000987 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
988 else
989 Inst.addOperand(MCOperand::CreateExpr(Expr));
990 }
991
Daniel Dunbar8462b302010-08-11 06:36:53 +0000992 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000993 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000994 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000995 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
996 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000997 }
998
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000999 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
1001 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1002 }
1003
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001004 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1005 assert(N == 1 && "Invalid number of operands!");
1006 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1007 }
1008
1009 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1010 assert(N == 1 && "Invalid number of operands!");
1011 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1012 }
1013
Jim Grosbach89df9962011-08-26 21:43:41 +00001014 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1015 assert(N == 1 && "Invalid number of operands!");
1016 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1017 }
1018
1019 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
1021 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1022 }
1023
Jim Grosbachd67641b2010-12-06 18:21:12 +00001024 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
1026 Inst.addOperand(MCOperand::CreateReg(getReg()));
1027 }
1028
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001029 void addRegOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
1031 Inst.addOperand(MCOperand::CreateReg(getReg()));
1032 }
1033
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001034 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001035 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001036 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1037 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1038 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001039 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001040 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001041 }
1042
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001043 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001044 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001045 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1046 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001047 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001048 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001049 }
1050
Jim Grosbach580f4a92011-07-25 22:20:28 +00001051 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001052 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001053 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1054 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001055 }
1056
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001057 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001058 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001059 const SmallVectorImpl<unsigned> &RegList = getRegList();
1060 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001061 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1062 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001063 }
1064
Bill Wendling0f630752010-11-17 04:32:08 +00001065 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1066 addRegListOperands(Inst, N);
1067 }
1068
1069 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1070 addRegListOperands(Inst, N);
1071 }
1072
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001073 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1076 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1077 }
1078
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001079 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1080 assert(N == 1 && "Invalid number of operands!");
1081 // Munge the lsb/width into a bitfield mask.
1082 unsigned lsb = Bitfield.LSB;
1083 unsigned width = Bitfield.Width;
1084 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1085 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1086 (32 - (lsb + width)));
1087 Inst.addOperand(MCOperand::CreateImm(Mask));
1088 }
1089
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001090 void addImmOperands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
1092 addExpr(Inst, getImm());
1093 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001094
Jim Grosbach9d390362011-10-03 23:38:36 +00001095 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1096 assert(N == 1 && "Invalid number of operands!");
1097 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1098 }
1099
Jim Grosbacha77295d2011-09-08 22:07:06 +00001100 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1101 assert(N == 1 && "Invalid number of operands!");
1102 // FIXME: We really want to scale the value here, but the LDRD/STRD
1103 // instruction don't encode operands that way yet.
1104 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1105 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1106 }
1107
Jim Grosbach72f39f82011-08-24 21:22:15 +00001108 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1109 assert(N == 1 && "Invalid number of operands!");
1110 // The immediate is scaled by four in the encoding and is stored
1111 // in the MCInst as such. Lop off the low two bits here.
1112 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1113 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1114 }
1115
1116 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 // The immediate is scaled by four in the encoding and is stored
1119 // in the MCInst as such. Lop off the low two bits here.
1120 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1121 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1122 }
1123
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001124 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!");
1126 addExpr(Inst, getImm());
1127 }
1128
Jim Grosbach83ab0702011-07-13 22:01:08 +00001129 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 addExpr(Inst, getImm());
1132 }
1133
1134 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
1136 addExpr(Inst, getImm());
1137 }
1138
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001139 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
1141 addExpr(Inst, getImm());
1142 }
1143
Jim Grosbachf4943352011-07-25 23:09:14 +00001144 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
1146 // The constant encodes as the immediate-1, and we store in the instruction
1147 // the bits as encoded, so subtract off one here.
1148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1149 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1150 }
1151
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001152 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
1154 // The constant encodes as the immediate-1, and we store in the instruction
1155 // the bits as encoded, so subtract off one here.
1156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1157 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1158 }
1159
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001160 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 addExpr(Inst, getImm());
1163 }
1164
Jim Grosbachffa32252011-07-19 19:13:28 +00001165 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 addExpr(Inst, getImm());
1168 }
1169
Jim Grosbached838482011-07-26 16:24:27 +00001170 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 addExpr(Inst, getImm());
1173 }
1174
Jim Grosbach70939ee2011-08-17 21:51:27 +00001175 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
1177 // The constant encodes as the immediate, except for 32, which encodes as
1178 // zero.
1179 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1180 unsigned Imm = CE->getValue();
1181 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1182 }
1183
Jim Grosbachf6c05252011-07-21 17:23:04 +00001184 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 addExpr(Inst, getImm());
1187 }
1188
1189 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
1191 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1192 // the instruction as well.
1193 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1194 int Val = CE->getValue();
1195 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1196 }
1197
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001198 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1199 assert(N == 1 && "Invalid number of operands!");
1200 addExpr(Inst, getImm());
1201 }
1202
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001203 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1204 assert(N == 1 && "Invalid number of operands!");
1205 addExpr(Inst, getImm());
1206 }
1207
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001208 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1209 assert(N == 1 && "Invalid number of operands!");
1210 addExpr(Inst, getImm());
1211 }
1212
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001213 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
1215 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1216 }
1217
Jim Grosbach7ce05792011-08-03 23:50:40 +00001218 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1219 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001220 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001221 }
1222
Jim Grosbach57dcb852011-10-11 17:29:55 +00001223 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1224 assert(N == 2 && "Invalid number of operands!");
1225 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1226 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1227 }
1228
Jim Grosbach7ce05792011-08-03 23:50:40 +00001229 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1230 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001231 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1232 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001233 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1234 // Special case for #-0
1235 if (Val == INT32_MIN) Val = 0;
1236 if (Val < 0) Val = -Val;
1237 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1238 } else {
1239 // For register offset, we encode the shift type and negation flag
1240 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001241 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1242 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001243 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001244 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1245 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001246 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001247 }
1248
Jim Grosbach039c2e12011-08-04 23:01:30 +00001249 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 2 && "Invalid number of operands!");
1251 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1252 assert(CE && "non-constant AM2OffsetImm operand!");
1253 int32_t Val = CE->getValue();
1254 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::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1259 Inst.addOperand(MCOperand::CreateReg(0));
1260 Inst.addOperand(MCOperand::CreateImm(Val));
1261 }
1262
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001263 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1264 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001265 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1266 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001267 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1268 // Special case for #-0
1269 if (Val == INT32_MIN) Val = 0;
1270 if (Val < 0) Val = -Val;
1271 Val = ARM_AM::getAM3Opc(AddSub, Val);
1272 } else {
1273 // For register offset, we encode the shift type and negation flag
1274 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001275 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001276 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001277 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1278 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001279 Inst.addOperand(MCOperand::CreateImm(Val));
1280 }
1281
1282 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1283 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001284 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001285 int32_t Val =
1286 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1287 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1288 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001289 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001290 }
1291
1292 // Constant offset.
1293 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1294 int32_t Val = CE->getValue();
1295 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;
Jim Grosbach251bf252011-08-10 21:56:18 +00001299 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001300 Inst.addOperand(MCOperand::CreateReg(0));
1301 Inst.addOperand(MCOperand::CreateImm(Val));
1302 }
1303
Jim Grosbach7ce05792011-08-03 23:50:40 +00001304 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1305 assert(N == 2 && "Invalid number of operands!");
1306 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001307 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001308 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1309 // Special case for #-0
1310 if (Val == INT32_MIN) Val = 0;
1311 if (Val < 0) Val = -Val;
1312 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001313 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001314 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001315 }
1316
Jim Grosbacha77295d2011-09-08 22:07:06 +00001317 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1318 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001319 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1320 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001321 Inst.addOperand(MCOperand::CreateImm(Val));
1322 }
1323
Jim Grosbachb6aed502011-09-09 18:37:27 +00001324 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1325 assert(N == 2 && "Invalid number of operands!");
1326 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001327 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1328 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001329 Inst.addOperand(MCOperand::CreateImm(Val));
1330 }
1331
Jim Grosbach7ce05792011-08-03 23:50:40 +00001332 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1333 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001334 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1335 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001336 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001337 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001338
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001339 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1340 addMemImm8OffsetOperands(Inst, N);
1341 }
1342
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001343 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001344 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001345 }
1346
1347 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1348 assert(N == 2 && "Invalid number of operands!");
1349 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001350 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001351 addExpr(Inst, getImm());
1352 Inst.addOperand(MCOperand::CreateImm(0));
1353 return;
1354 }
1355
1356 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001357 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1358 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001359 Inst.addOperand(MCOperand::CreateImm(Val));
1360 }
1361
Jim Grosbach7ce05792011-08-03 23:50:40 +00001362 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1363 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001364 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001365 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001366 addExpr(Inst, getImm());
1367 Inst.addOperand(MCOperand::CreateImm(0));
1368 return;
1369 }
1370
1371 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001372 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1373 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001374 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001375 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001376
Jim Grosbach7f739be2011-09-19 22:21:13 +00001377 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001379 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1380 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001381 }
1382
1383 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001385 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1386 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001387 }
1388
Jim Grosbach7ce05792011-08-03 23:50:40 +00001389 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1390 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001391 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1392 Memory.ShiftImm, Memory.ShiftType);
1393 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1394 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001395 Inst.addOperand(MCOperand::CreateImm(Val));
1396 }
1397
Jim Grosbachab899c12011-09-07 23:10:15 +00001398 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1399 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001400 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1401 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1402 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001403 }
1404
Jim Grosbach7ce05792011-08-03 23:50:40 +00001405 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1406 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001407 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1408 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001409 }
1410
Jim Grosbach60f91a32011-08-19 17:55:24 +00001411 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1412 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001413 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1414 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001415 Inst.addOperand(MCOperand::CreateImm(Val));
1416 }
1417
Jim Grosbach38466302011-08-19 18:55:51 +00001418 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1419 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001420 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1421 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001422 Inst.addOperand(MCOperand::CreateImm(Val));
1423 }
1424
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001425 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001427 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1428 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001429 Inst.addOperand(MCOperand::CreateImm(Val));
1430 }
1431
Jim Grosbachecd85892011-08-19 18:13:48 +00001432 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1433 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1435 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001436 Inst.addOperand(MCOperand::CreateImm(Val));
1437 }
1438
Jim Grosbach7ce05792011-08-03 23:50:40 +00001439 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1442 assert(CE && "non-constant post-idx-imm8 operand!");
1443 int Imm = CE->getValue();
1444 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001445 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001446 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1447 Inst.addOperand(MCOperand::CreateImm(Imm));
1448 }
1449
Jim Grosbach2bd01182011-10-11 21:55:36 +00001450 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
1452 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1453 assert(CE && "non-constant post-idx-imm8s4 operand!");
1454 int Imm = CE->getValue();
1455 bool isAdd = Imm >= 0;
1456 if (Imm == INT32_MIN) Imm = 0;
1457 // Immediate is scaled by 4.
1458 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1459 Inst.addOperand(MCOperand::CreateImm(Imm));
1460 }
1461
Jim Grosbach7ce05792011-08-03 23:50:40 +00001462 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 2 && "Invalid number of operands!");
1464 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001465 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1466 }
1467
1468 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 2 && "Invalid number of operands!");
1470 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1471 // The sign, shift type, and shift amount are encoded in a single operand
1472 // using the AM2 encoding helpers.
1473 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1474 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1475 PostIdxReg.ShiftTy);
1476 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001477 }
1478
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001479 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1480 assert(N == 1 && "Invalid number of operands!");
1481 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1482 }
1483
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001484 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1487 }
1488
Jim Grosbach460a9052011-10-07 23:56:00 +00001489 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
1491 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1492 }
1493
1494 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1497 }
1498
1499 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1502 }
1503
Jim Grosbach0e387b22011-10-17 22:26:03 +00001504 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 // The immediate encodes the type of constant as well as the value.
1507 // Mask in that this is an i8 splat.
1508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1509 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1510 }
1511
Jim Grosbachea461102011-10-17 23:09:09 +00001512 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
1514 // The immediate encodes the type of constant as well as the value.
1515 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1516 unsigned Value = CE->getValue();
1517 if (Value >= 256)
1518 Value = (Value >> 8) | 0xa00;
1519 else
1520 Value |= 0x800;
1521 Inst.addOperand(MCOperand::CreateImm(Value));
1522 }
1523
Jim Grosbach6248a542011-10-18 00:22:00 +00001524 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 // The immediate encodes the type of constant as well as the value.
1527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1528 unsigned Value = CE->getValue();
1529 if (Value >= 256 && Value <= 0xff00)
1530 Value = (Value >> 8) | 0x200;
1531 else if (Value > 0xffff && Value <= 0xff0000)
1532 Value = (Value >> 16) | 0x400;
1533 else if (Value > 0xffffff)
1534 Value = (Value >> 24) | 0x600;
1535 Inst.addOperand(MCOperand::CreateImm(Value));
1536 }
1537
1538 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1539 assert(N == 1 && "Invalid number of operands!");
1540 // The immediate encodes the type of constant as well as the value.
1541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1542 unsigned Value = CE->getValue();
1543 if (Value >= 256 && Value <= 0xffff)
1544 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1545 else if (Value > 0xffff && Value <= 0xffffff)
1546 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1547 else if (Value > 0xffffff)
1548 Value = (Value >> 24) | 0x600;
1549 Inst.addOperand(MCOperand::CreateImm(Value));
1550 }
1551
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001552 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554 // The immediate encodes the type of constant as well as the value.
1555 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1556 uint64_t Value = CE->getValue();
1557 unsigned Imm = 0;
1558 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1559 Imm |= (Value & 1) << i;
1560 }
1561 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1562 }
1563
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001564 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001565
Jim Grosbach89df9962011-08-26 21:43:41 +00001566 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001567 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001568 Op->ITMask.Mask = Mask;
1569 Op->StartLoc = S;
1570 Op->EndLoc = S;
1571 return Op;
1572 }
1573
Chris Lattner3a697562010-10-28 17:20:03 +00001574 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001575 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001576 Op->CC.Val = CC;
1577 Op->StartLoc = S;
1578 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001579 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001580 }
1581
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001582 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001583 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001584 Op->Cop.Val = CopVal;
1585 Op->StartLoc = S;
1586 Op->EndLoc = S;
1587 return Op;
1588 }
1589
1590 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001591 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001592 Op->Cop.Val = CopVal;
1593 Op->StartLoc = S;
1594 Op->EndLoc = S;
1595 return Op;
1596 }
1597
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001598 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1599 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1600 Op->Cop.Val = Val;
1601 Op->StartLoc = S;
1602 Op->EndLoc = E;
1603 return Op;
1604 }
1605
Jim Grosbachd67641b2010-12-06 18:21:12 +00001606 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001607 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001608 Op->Reg.RegNum = RegNum;
1609 Op->StartLoc = S;
1610 Op->EndLoc = S;
1611 return Op;
1612 }
1613
Chris Lattner3a697562010-10-28 17:20:03 +00001614 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001615 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001616 Op->Tok.Data = Str.data();
1617 Op->Tok.Length = Str.size();
1618 Op->StartLoc = S;
1619 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001620 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001621 }
1622
Bill Wendling50d0f582010-11-18 23:43:05 +00001623 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001624 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001625 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001626 Op->StartLoc = S;
1627 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001628 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001629 }
1630
Jim Grosbache8606dc2011-07-13 17:50:29 +00001631 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1632 unsigned SrcReg,
1633 unsigned ShiftReg,
1634 unsigned ShiftImm,
1635 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001636 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001637 Op->RegShiftedReg.ShiftTy = ShTy;
1638 Op->RegShiftedReg.SrcReg = SrcReg;
1639 Op->RegShiftedReg.ShiftReg = ShiftReg;
1640 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001641 Op->StartLoc = S;
1642 Op->EndLoc = E;
1643 return Op;
1644 }
1645
Owen Anderson92a20222011-07-21 18:54:16 +00001646 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1647 unsigned SrcReg,
1648 unsigned ShiftImm,
1649 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001650 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001651 Op->RegShiftedImm.ShiftTy = ShTy;
1652 Op->RegShiftedImm.SrcReg = SrcReg;
1653 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001654 Op->StartLoc = S;
1655 Op->EndLoc = E;
1656 return Op;
1657 }
1658
Jim Grosbach580f4a92011-07-25 22:20:28 +00001659 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001660 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001661 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001662 Op->ShifterImm.isASR = isASR;
1663 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001664 Op->StartLoc = S;
1665 Op->EndLoc = E;
1666 return Op;
1667 }
1668
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001669 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001670 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001671 Op->RotImm.Imm = Imm;
1672 Op->StartLoc = S;
1673 Op->EndLoc = E;
1674 return Op;
1675 }
1676
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001677 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1678 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001679 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001680 Op->Bitfield.LSB = LSB;
1681 Op->Bitfield.Width = Width;
1682 Op->StartLoc = S;
1683 Op->EndLoc = E;
1684 return Op;
1685 }
1686
Bill Wendling7729e062010-11-09 22:44:22 +00001687 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001688 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001689 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001690 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001691
Jim Grosbachd300b942011-09-13 22:56:44 +00001692 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001693 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001694 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001695 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001696 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001697
1698 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001699 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001700 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001701 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001702 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001703 Op->StartLoc = StartLoc;
1704 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001705 return Op;
1706 }
1707
Jim Grosbach460a9052011-10-07 23:56:00 +00001708 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1709 MCContext &Ctx) {
1710 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1711 Op->VectorIndex.Val = Idx;
1712 Op->StartLoc = S;
1713 Op->EndLoc = E;
1714 return Op;
1715 }
1716
Chris Lattner3a697562010-10-28 17:20:03 +00001717 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001718 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001719 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001720 Op->StartLoc = S;
1721 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001722 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001723 }
1724
Jim Grosbach9d390362011-10-03 23:38:36 +00001725 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001726 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001727 Op->FPImm.Val = Val;
1728 Op->StartLoc = S;
1729 Op->EndLoc = S;
1730 return Op;
1731 }
1732
Jim Grosbach7ce05792011-08-03 23:50:40 +00001733 static ARMOperand *CreateMem(unsigned BaseRegNum,
1734 const MCConstantExpr *OffsetImm,
1735 unsigned OffsetRegNum,
1736 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001737 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001738 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001739 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001740 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001741 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001742 Op->Memory.BaseRegNum = BaseRegNum;
1743 Op->Memory.OffsetImm = OffsetImm;
1744 Op->Memory.OffsetRegNum = OffsetRegNum;
1745 Op->Memory.ShiftType = ShiftType;
1746 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001747 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001748 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001749 Op->StartLoc = S;
1750 Op->EndLoc = E;
1751 return Op;
1752 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001753
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001754 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1755 ARM_AM::ShiftOpc ShiftTy,
1756 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001757 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001758 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001759 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001760 Op->PostIdxReg.isAdd = isAdd;
1761 Op->PostIdxReg.ShiftTy = ShiftTy;
1762 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001763 Op->StartLoc = S;
1764 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001765 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001766 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001767
1768 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001769 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001770 Op->MBOpt.Val = Opt;
1771 Op->StartLoc = S;
1772 Op->EndLoc = S;
1773 return Op;
1774 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001775
1776 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001777 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001778 Op->IFlags.Val = IFlags;
1779 Op->StartLoc = S;
1780 Op->EndLoc = S;
1781 return Op;
1782 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001783
1784 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001785 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001786 Op->MMask.Val = MMask;
1787 Op->StartLoc = S;
1788 Op->EndLoc = S;
1789 return Op;
1790 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001791};
1792
1793} // end anonymous namespace.
1794
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001795void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001796 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001797 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001798 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1799 << ") >";
1800 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001801 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001802 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001803 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001804 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001805 OS << "<ccout " << getReg() << ">";
1806 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001807 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001808 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1809 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1810 "(tee)", "(eee)" };
1811 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1812 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1813 break;
1814 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001815 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001816 OS << "<coprocessor number: " << getCoproc() << ">";
1817 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001818 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001819 OS << "<coprocessor register: " << getCoproc() << ">";
1820 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001821 case k_CoprocOption:
1822 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1823 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001824 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001825 OS << "<mask: " << getMSRMask() << ">";
1826 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001827 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001828 getImm()->print(OS);
1829 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001830 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001831 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1832 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001833 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001834 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001835 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001836 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001837 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001838 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001839 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1840 << PostIdxReg.RegNum;
1841 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1842 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1843 << PostIdxReg.ShiftImm;
1844 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001845 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001846 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001847 OS << "<ARM_PROC::";
1848 unsigned IFlags = getProcIFlags();
1849 for (int i=2; i >= 0; --i)
1850 if (IFlags & (1 << i))
1851 OS << ARM_PROC::IFlagsToString(1 << i);
1852 OS << ">";
1853 break;
1854 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001855 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001856 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001857 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001858 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001859 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1860 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001861 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001862 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001863 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001864 << RegShiftedReg.SrcReg
1865 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1866 << ", " << RegShiftedReg.ShiftReg << ", "
1867 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001868 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001869 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001870 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001871 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001872 << RegShiftedImm.SrcReg
1873 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1874 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001875 << ">";
1876 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001877 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001878 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1879 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001880 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001881 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1882 << ", width: " << Bitfield.Width << ">";
1883 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001884 case k_RegisterList:
1885 case k_DPRRegisterList:
1886 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001887 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001888
Bill Wendling5fa22a12010-11-09 23:28:44 +00001889 const SmallVectorImpl<unsigned> &RegList = getRegList();
1890 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001891 I = RegList.begin(), E = RegList.end(); I != E; ) {
1892 OS << *I;
1893 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001894 }
1895
1896 OS << ">";
1897 break;
1898 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001899 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001900 OS << "'" << getToken() << "'";
1901 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001902 case k_VectorIndex:
1903 OS << "<vectorindex " << getVectorIndex() << ">";
1904 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001905 }
1906}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001907
1908/// @name Auto-generated Match Functions
1909/// {
1910
1911static unsigned MatchRegisterName(StringRef Name);
1912
1913/// }
1914
Bob Wilson69df7232011-02-03 21:46:10 +00001915bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1916 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001917 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001918
1919 return (RegNo == (unsigned)-1);
1920}
1921
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001922/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001923/// and if it is a register name the token is eaten and the register number is
1924/// returned. Otherwise return -1.
1925///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001926int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001927 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001928 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001929
Chris Lattnere5658fa2010-10-30 04:09:10 +00001930 // FIXME: Validate register for the current architecture; we have to do
1931 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001932 std::string upperCase = Tok.getString().str();
1933 std::string lowerCase = LowercaseString(upperCase);
1934 unsigned RegNum = MatchRegisterName(lowerCase);
1935 if (!RegNum) {
1936 RegNum = StringSwitch<unsigned>(lowerCase)
1937 .Case("r13", ARM::SP)
1938 .Case("r14", ARM::LR)
1939 .Case("r15", ARM::PC)
1940 .Case("ip", ARM::R12)
1941 .Default(0);
1942 }
1943 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001944
Chris Lattnere5658fa2010-10-30 04:09:10 +00001945 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001946
1947#if 0
1948 // Also check for an index operand. This is only legal for vector registers,
1949 // but that'll get caught OK in operand matching, so we don't need to
1950 // explicitly filter everything else out here.
1951 if (Parser.getTok().is(AsmToken::LBrac)) {
1952 SMLoc SIdx = Parser.getTok().getLoc();
1953 Parser.Lex(); // Eat left bracket token.
1954
1955 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00001956 if (getParser().ParseExpression(ImmVal))
1957 return MatchOperand_ParseFail;
1958 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1959 if (!MCE) {
1960 TokError("immediate value expected for vector index");
1961 return MatchOperand_ParseFail;
1962 }
1963
1964 SMLoc E = Parser.getTok().getLoc();
1965 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1966 Error(E, "']' expected");
1967 return MatchOperand_ParseFail;
1968 }
1969
1970 Parser.Lex(); // Eat right bracket token.
1971
1972 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1973 SIdx, E,
1974 getContext()));
1975 }
1976#endif
1977
Chris Lattnere5658fa2010-10-30 04:09:10 +00001978 return RegNum;
1979}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001980
Jim Grosbach19906722011-07-13 18:49:30 +00001981// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1982// If a recoverable error occurs, return 1. If an irrecoverable error
1983// occurs, return -1. An irrecoverable error is one where tokens have been
1984// consumed in the process of trying to parse the shifter (i.e., when it is
1985// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001986int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001987 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1988 SMLoc S = Parser.getTok().getLoc();
1989 const AsmToken &Tok = Parser.getTok();
1990 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1991
1992 std::string upperCase = Tok.getString().str();
1993 std::string lowerCase = LowercaseString(upperCase);
1994 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1995 .Case("lsl", ARM_AM::lsl)
1996 .Case("lsr", ARM_AM::lsr)
1997 .Case("asr", ARM_AM::asr)
1998 .Case("ror", ARM_AM::ror)
1999 .Case("rrx", ARM_AM::rrx)
2000 .Default(ARM_AM::no_shift);
2001
2002 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002003 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002004
Jim Grosbache8606dc2011-07-13 17:50:29 +00002005 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002006
Jim Grosbache8606dc2011-07-13 17:50:29 +00002007 // The source register for the shift has already been added to the
2008 // operand list, so we need to pop it off and combine it into the shifted
2009 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002010 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002011 if (!PrevOp->isReg())
2012 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2013 int SrcReg = PrevOp->getReg();
2014 int64_t Imm = 0;
2015 int ShiftReg = 0;
2016 if (ShiftTy == ARM_AM::rrx) {
2017 // RRX Doesn't have an explicit shift amount. The encoder expects
2018 // the shift register to be the same as the source register. Seems odd,
2019 // but OK.
2020 ShiftReg = SrcReg;
2021 } else {
2022 // Figure out if this is shifted by a constant or a register (for non-RRX).
2023 if (Parser.getTok().is(AsmToken::Hash)) {
2024 Parser.Lex(); // Eat hash.
2025 SMLoc ImmLoc = Parser.getTok().getLoc();
2026 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002027 if (getParser().ParseExpression(ShiftExpr)) {
2028 Error(ImmLoc, "invalid immediate shift value");
2029 return -1;
2030 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002031 // The expression must be evaluatable as an immediate.
2032 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002033 if (!CE) {
2034 Error(ImmLoc, "invalid immediate shift value");
2035 return -1;
2036 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002037 // Range check the immediate.
2038 // lsl, ror: 0 <= imm <= 31
2039 // lsr, asr: 0 <= imm <= 32
2040 Imm = CE->getValue();
2041 if (Imm < 0 ||
2042 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2043 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002044 Error(ImmLoc, "immediate shift value out of range");
2045 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002046 }
2047 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002048 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002049 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002050 if (ShiftReg == -1) {
2051 Error (L, "expected immediate or register in shift operand");
2052 return -1;
2053 }
2054 } else {
2055 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002056 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002057 return -1;
2058 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002059 }
2060
Owen Anderson92a20222011-07-21 18:54:16 +00002061 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2062 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002063 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002064 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002065 else
2066 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2067 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002068
Jim Grosbach19906722011-07-13 18:49:30 +00002069 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002070}
2071
2072
Bill Wendling50d0f582010-11-18 23:43:05 +00002073/// Try to parse a register name. The token must be an Identifier when called.
2074/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2075/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002076///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002077/// TODO this is likely to change to allow different register types and or to
2078/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002079bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002080tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002081 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002082 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002083 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002084 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002085
Bill Wendling50d0f582010-11-18 23:43:05 +00002086 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002087
Chris Lattnere5658fa2010-10-30 04:09:10 +00002088 const AsmToken &ExclaimTok = Parser.getTok();
2089 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002090 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2091 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002092 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002093 return false;
2094 }
2095
2096 // Also check for an index operand. This is only legal for vector registers,
2097 // but that'll get caught OK in operand matching, so we don't need to
2098 // explicitly filter everything else out here.
2099 if (Parser.getTok().is(AsmToken::LBrac)) {
2100 SMLoc SIdx = Parser.getTok().getLoc();
2101 Parser.Lex(); // Eat left bracket token.
2102
2103 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002104 if (getParser().ParseExpression(ImmVal))
2105 return MatchOperand_ParseFail;
2106 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2107 if (!MCE) {
2108 TokError("immediate value expected for vector index");
2109 return MatchOperand_ParseFail;
2110 }
2111
2112 SMLoc E = Parser.getTok().getLoc();
2113 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2114 Error(E, "']' expected");
2115 return MatchOperand_ParseFail;
2116 }
2117
2118 Parser.Lex(); // Eat right bracket token.
2119
2120 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2121 SIdx, E,
2122 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002123 }
2124
Bill Wendling50d0f582010-11-18 23:43:05 +00002125 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002126}
2127
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002128/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2129/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2130/// "c5", ...
2131static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002132 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2133 // but efficient.
2134 switch (Name.size()) {
2135 default: break;
2136 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002137 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002138 return -1;
2139 switch (Name[1]) {
2140 default: return -1;
2141 case '0': return 0;
2142 case '1': return 1;
2143 case '2': return 2;
2144 case '3': return 3;
2145 case '4': return 4;
2146 case '5': return 5;
2147 case '6': return 6;
2148 case '7': return 7;
2149 case '8': return 8;
2150 case '9': return 9;
2151 }
2152 break;
2153 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002154 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002155 return -1;
2156 switch (Name[2]) {
2157 default: return -1;
2158 case '0': return 10;
2159 case '1': return 11;
2160 case '2': return 12;
2161 case '3': return 13;
2162 case '4': return 14;
2163 case '5': return 15;
2164 }
2165 break;
2166 }
2167
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002168 return -1;
2169}
2170
Jim Grosbach89df9962011-08-26 21:43:41 +00002171/// parseITCondCode - Try to parse a condition code for an IT instruction.
2172ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2173parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2174 SMLoc S = Parser.getTok().getLoc();
2175 const AsmToken &Tok = Parser.getTok();
2176 if (!Tok.is(AsmToken::Identifier))
2177 return MatchOperand_NoMatch;
2178 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2179 .Case("eq", ARMCC::EQ)
2180 .Case("ne", ARMCC::NE)
2181 .Case("hs", ARMCC::HS)
2182 .Case("cs", ARMCC::HS)
2183 .Case("lo", ARMCC::LO)
2184 .Case("cc", ARMCC::LO)
2185 .Case("mi", ARMCC::MI)
2186 .Case("pl", ARMCC::PL)
2187 .Case("vs", ARMCC::VS)
2188 .Case("vc", ARMCC::VC)
2189 .Case("hi", ARMCC::HI)
2190 .Case("ls", ARMCC::LS)
2191 .Case("ge", ARMCC::GE)
2192 .Case("lt", ARMCC::LT)
2193 .Case("gt", ARMCC::GT)
2194 .Case("le", ARMCC::LE)
2195 .Case("al", ARMCC::AL)
2196 .Default(~0U);
2197 if (CC == ~0U)
2198 return MatchOperand_NoMatch;
2199 Parser.Lex(); // Eat the token.
2200
2201 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2202
2203 return MatchOperand_Success;
2204}
2205
Jim Grosbach43904292011-07-25 20:14:50 +00002206/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002207/// token must be an Identifier when called, and if it is a coprocessor
2208/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002209ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002210parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002211 SMLoc S = Parser.getTok().getLoc();
2212 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002213 if (Tok.isNot(AsmToken::Identifier))
2214 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002215
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002216 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002217 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002218 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002219
2220 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002221 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002222 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002223}
2224
Jim Grosbach43904292011-07-25 20:14:50 +00002225/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002226/// token must be an Identifier when called, and if it is a coprocessor
2227/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002228ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002229parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002230 SMLoc S = Parser.getTok().getLoc();
2231 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002232 if (Tok.isNot(AsmToken::Identifier))
2233 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002234
2235 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2236 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002237 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002238
2239 Parser.Lex(); // Eat identifier token.
2240 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002241 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002242}
2243
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002244/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2245/// coproc_option : '{' imm0_255 '}'
2246ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2247parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2248 SMLoc S = Parser.getTok().getLoc();
2249
2250 // If this isn't a '{', this isn't a coprocessor immediate operand.
2251 if (Parser.getTok().isNot(AsmToken::LCurly))
2252 return MatchOperand_NoMatch;
2253 Parser.Lex(); // Eat the '{'
2254
2255 const MCExpr *Expr;
2256 SMLoc Loc = Parser.getTok().getLoc();
2257 if (getParser().ParseExpression(Expr)) {
2258 Error(Loc, "illegal expression");
2259 return MatchOperand_ParseFail;
2260 }
2261 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2262 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2263 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2264 return MatchOperand_ParseFail;
2265 }
2266 int Val = CE->getValue();
2267
2268 // Check for and consume the closing '}'
2269 if (Parser.getTok().isNot(AsmToken::RCurly))
2270 return MatchOperand_ParseFail;
2271 SMLoc E = Parser.getTok().getLoc();
2272 Parser.Lex(); // Eat the '}'
2273
2274 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2275 return MatchOperand_Success;
2276}
2277
Jim Grosbachd0588e22011-09-14 18:08:35 +00002278// For register list parsing, we need to map from raw GPR register numbering
2279// to the enumeration values. The enumeration values aren't sorted by
2280// register number due to our using "sp", "lr" and "pc" as canonical names.
2281static unsigned getNextRegister(unsigned Reg) {
2282 // If this is a GPR, we need to do it manually, otherwise we can rely
2283 // on the sort ordering of the enumeration since the other reg-classes
2284 // are sane.
2285 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2286 return Reg + 1;
2287 switch(Reg) {
2288 default: assert(0 && "Invalid GPR number!");
2289 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2290 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2291 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2292 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2293 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2294 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2295 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2296 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2297 }
2298}
2299
2300/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002301bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002302parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002303 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002304 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002305 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002306 Parser.Lex(); // Eat '{' token.
2307 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002308
Jim Grosbachd0588e22011-09-14 18:08:35 +00002309 // Check the first register in the list to see what register class
2310 // this is a list of.
2311 int Reg = tryParseRegister();
2312 if (Reg == -1)
2313 return Error(RegLoc, "register expected");
2314
2315 MCRegisterClass *RC;
2316 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2317 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2318 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2319 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2320 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2321 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2322 else
2323 return Error(RegLoc, "invalid register in register list");
2324
2325 // The reglist instructions have at most 16 registers, so reserve
2326 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002327 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002328 // Store the first register.
2329 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002330
Jim Grosbachd0588e22011-09-14 18:08:35 +00002331 // This starts immediately after the first register token in the list,
2332 // so we can see either a comma or a minus (range separator) as a legal
2333 // next token.
2334 while (Parser.getTok().is(AsmToken::Comma) ||
2335 Parser.getTok().is(AsmToken::Minus)) {
2336 if (Parser.getTok().is(AsmToken::Minus)) {
2337 Parser.Lex(); // Eat the comma.
2338 SMLoc EndLoc = Parser.getTok().getLoc();
2339 int EndReg = tryParseRegister();
2340 if (EndReg == -1)
2341 return Error(EndLoc, "register expected");
2342 // If the register is the same as the start reg, there's nothing
2343 // more to do.
2344 if (Reg == EndReg)
2345 continue;
2346 // The register must be in the same register class as the first.
2347 if (!RC->contains(EndReg))
2348 return Error(EndLoc, "invalid register in register list");
2349 // Ranges must go from low to high.
2350 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2351 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002352
Jim Grosbachd0588e22011-09-14 18:08:35 +00002353 // Add all the registers in the range to the register list.
2354 while (Reg != EndReg) {
2355 Reg = getNextRegister(Reg);
2356 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2357 }
2358 continue;
2359 }
2360 Parser.Lex(); // Eat the comma.
2361 RegLoc = Parser.getTok().getLoc();
2362 int OldReg = Reg;
2363 Reg = tryParseRegister();
2364 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002365 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002366 // The register must be in the same register class as the first.
2367 if (!RC->contains(Reg))
2368 return Error(RegLoc, "invalid register in register list");
2369 // List must be monotonically increasing.
2370 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2371 return Error(RegLoc, "register list not in ascending order");
2372 // VFP register lists must also be contiguous.
2373 // It's OK to use the enumeration values directly here rather, as the
2374 // VFP register classes have the enum sorted properly.
2375 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2376 Reg != OldReg + 1)
2377 return Error(RegLoc, "non-contiguous register range");
2378 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002379 }
2380
Jim Grosbachd0588e22011-09-14 18:08:35 +00002381 SMLoc E = Parser.getTok().getLoc();
2382 if (Parser.getTok().isNot(AsmToken::RCurly))
2383 return Error(E, "'}' expected");
2384 Parser.Lex(); // Eat '}' token.
2385
Bill Wendling50d0f582010-11-18 23:43:05 +00002386 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2387 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002388}
2389
Jim Grosbach43904292011-07-25 20:14:50 +00002390/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002391ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002392parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002393 SMLoc S = Parser.getTok().getLoc();
2394 const AsmToken &Tok = Parser.getTok();
2395 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2396 StringRef OptStr = Tok.getString();
2397
2398 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2399 .Case("sy", ARM_MB::SY)
2400 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002401 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002402 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002403 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002404 .Case("ishst", ARM_MB::ISHST)
2405 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002406 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002407 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002408 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002409 .Case("osh", ARM_MB::OSH)
2410 .Case("oshst", ARM_MB::OSHST)
2411 .Default(~0U);
2412
2413 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002414 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002415
2416 Parser.Lex(); // Eat identifier token.
2417 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002418 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002419}
2420
Jim Grosbach43904292011-07-25 20:14:50 +00002421/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002422ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002423parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002424 SMLoc S = Parser.getTok().getLoc();
2425 const AsmToken &Tok = Parser.getTok();
2426 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2427 StringRef IFlagsStr = Tok.getString();
2428
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002429 // An iflags string of "none" is interpreted to mean that none of the AIF
2430 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002431 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002432 if (IFlagsStr != "none") {
2433 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2434 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2435 .Case("a", ARM_PROC::A)
2436 .Case("i", ARM_PROC::I)
2437 .Case("f", ARM_PROC::F)
2438 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002439
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002440 // If some specific iflag is already set, it means that some letter is
2441 // present more than once, this is not acceptable.
2442 if (Flag == ~0U || (IFlags & Flag))
2443 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002444
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002445 IFlags |= Flag;
2446 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002447 }
2448
2449 Parser.Lex(); // Eat identifier token.
2450 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2451 return MatchOperand_Success;
2452}
2453
Jim Grosbach43904292011-07-25 20:14:50 +00002454/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002455ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002456parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002457 SMLoc S = Parser.getTok().getLoc();
2458 const AsmToken &Tok = Parser.getTok();
2459 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2460 StringRef Mask = Tok.getString();
2461
James Molloyacad68d2011-09-28 14:21:38 +00002462 if (isMClass()) {
2463 // See ARMv6-M 10.1.1
2464 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2465 .Case("apsr", 0)
2466 .Case("iapsr", 1)
2467 .Case("eapsr", 2)
2468 .Case("xpsr", 3)
2469 .Case("ipsr", 5)
2470 .Case("epsr", 6)
2471 .Case("iepsr", 7)
2472 .Case("msp", 8)
2473 .Case("psp", 9)
2474 .Case("primask", 16)
2475 .Case("basepri", 17)
2476 .Case("basepri_max", 18)
2477 .Case("faultmask", 19)
2478 .Case("control", 20)
2479 .Default(~0U);
2480
2481 if (FlagsVal == ~0U)
2482 return MatchOperand_NoMatch;
2483
2484 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2485 // basepri, basepri_max and faultmask only valid for V7m.
2486 return MatchOperand_NoMatch;
2487
2488 Parser.Lex(); // Eat identifier token.
2489 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2490 return MatchOperand_Success;
2491 }
2492
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002493 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2494 size_t Start = 0, Next = Mask.find('_');
2495 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002496 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002497 if (Next != StringRef::npos)
2498 Flags = Mask.slice(Next+1, Mask.size());
2499
2500 // FlagsVal contains the complete mask:
2501 // 3-0: Mask
2502 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2503 unsigned FlagsVal = 0;
2504
2505 if (SpecReg == "apsr") {
2506 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002507 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002508 .Case("g", 0x4) // same as CPSR_s
2509 .Case("nzcvqg", 0xc) // same as CPSR_fs
2510 .Default(~0U);
2511
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002512 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002513 if (!Flags.empty())
2514 return MatchOperand_NoMatch;
2515 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002516 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002517 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002518 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002519 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2520 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002521 for (int i = 0, e = Flags.size(); i != e; ++i) {
2522 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2523 .Case("c", 1)
2524 .Case("x", 2)
2525 .Case("s", 4)
2526 .Case("f", 8)
2527 .Default(~0U);
2528
2529 // If some specific flag is already set, it means that some letter is
2530 // present more than once, this is not acceptable.
2531 if (FlagsVal == ~0U || (FlagsVal & Flag))
2532 return MatchOperand_NoMatch;
2533 FlagsVal |= Flag;
2534 }
2535 } else // No match for special register.
2536 return MatchOperand_NoMatch;
2537
2538 // Special register without flags are equivalent to "fc" flags.
2539 if (!FlagsVal)
2540 FlagsVal = 0x9;
2541
2542 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2543 if (SpecReg == "spsr")
2544 FlagsVal |= 16;
2545
2546 Parser.Lex(); // Eat identifier token.
2547 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2548 return MatchOperand_Success;
2549}
2550
Jim Grosbachf6c05252011-07-21 17:23:04 +00002551ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2552parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2553 int Low, int High) {
2554 const AsmToken &Tok = Parser.getTok();
2555 if (Tok.isNot(AsmToken::Identifier)) {
2556 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2557 return MatchOperand_ParseFail;
2558 }
2559 StringRef ShiftName = Tok.getString();
2560 std::string LowerOp = LowercaseString(Op);
2561 std::string UpperOp = UppercaseString(Op);
2562 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2563 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2564 return MatchOperand_ParseFail;
2565 }
2566 Parser.Lex(); // Eat shift type token.
2567
2568 // There must be a '#' and a shift amount.
2569 if (Parser.getTok().isNot(AsmToken::Hash)) {
2570 Error(Parser.getTok().getLoc(), "'#' expected");
2571 return MatchOperand_ParseFail;
2572 }
2573 Parser.Lex(); // Eat hash token.
2574
2575 const MCExpr *ShiftAmount;
2576 SMLoc Loc = Parser.getTok().getLoc();
2577 if (getParser().ParseExpression(ShiftAmount)) {
2578 Error(Loc, "illegal expression");
2579 return MatchOperand_ParseFail;
2580 }
2581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2582 if (!CE) {
2583 Error(Loc, "constant expression expected");
2584 return MatchOperand_ParseFail;
2585 }
2586 int Val = CE->getValue();
2587 if (Val < Low || Val > High) {
2588 Error(Loc, "immediate value out of range");
2589 return MatchOperand_ParseFail;
2590 }
2591
2592 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2593
2594 return MatchOperand_Success;
2595}
2596
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002597ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2598parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2599 const AsmToken &Tok = Parser.getTok();
2600 SMLoc S = Tok.getLoc();
2601 if (Tok.isNot(AsmToken::Identifier)) {
2602 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2603 return MatchOperand_ParseFail;
2604 }
2605 int Val = StringSwitch<int>(Tok.getString())
2606 .Case("be", 1)
2607 .Case("le", 0)
2608 .Default(-1);
2609 Parser.Lex(); // Eat the token.
2610
2611 if (Val == -1) {
2612 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2613 return MatchOperand_ParseFail;
2614 }
2615 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2616 getContext()),
2617 S, Parser.getTok().getLoc()));
2618 return MatchOperand_Success;
2619}
2620
Jim Grosbach580f4a92011-07-25 22:20:28 +00002621/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2622/// instructions. Legal values are:
2623/// lsl #n 'n' in [0,31]
2624/// asr #n 'n' in [1,32]
2625/// n == 32 encoded as n == 0.
2626ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2627parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2628 const AsmToken &Tok = Parser.getTok();
2629 SMLoc S = Tok.getLoc();
2630 if (Tok.isNot(AsmToken::Identifier)) {
2631 Error(S, "shift operator 'asr' or 'lsl' expected");
2632 return MatchOperand_ParseFail;
2633 }
2634 StringRef ShiftName = Tok.getString();
2635 bool isASR;
2636 if (ShiftName == "lsl" || ShiftName == "LSL")
2637 isASR = false;
2638 else if (ShiftName == "asr" || ShiftName == "ASR")
2639 isASR = true;
2640 else {
2641 Error(S, "shift operator 'asr' or 'lsl' expected");
2642 return MatchOperand_ParseFail;
2643 }
2644 Parser.Lex(); // Eat the operator.
2645
2646 // A '#' and a shift amount.
2647 if (Parser.getTok().isNot(AsmToken::Hash)) {
2648 Error(Parser.getTok().getLoc(), "'#' expected");
2649 return MatchOperand_ParseFail;
2650 }
2651 Parser.Lex(); // Eat hash token.
2652
2653 const MCExpr *ShiftAmount;
2654 SMLoc E = Parser.getTok().getLoc();
2655 if (getParser().ParseExpression(ShiftAmount)) {
2656 Error(E, "malformed shift expression");
2657 return MatchOperand_ParseFail;
2658 }
2659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2660 if (!CE) {
2661 Error(E, "shift amount must be an immediate");
2662 return MatchOperand_ParseFail;
2663 }
2664
2665 int64_t Val = CE->getValue();
2666 if (isASR) {
2667 // Shift amount must be in [1,32]
2668 if (Val < 1 || Val > 32) {
2669 Error(E, "'asr' shift amount must be in range [1,32]");
2670 return MatchOperand_ParseFail;
2671 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002672 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2673 if (isThumb() && Val == 32) {
2674 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2675 return MatchOperand_ParseFail;
2676 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002677 if (Val == 32) Val = 0;
2678 } else {
2679 // Shift amount must be in [1,32]
2680 if (Val < 0 || Val > 31) {
2681 Error(E, "'lsr' shift amount must be in range [0,31]");
2682 return MatchOperand_ParseFail;
2683 }
2684 }
2685
2686 E = Parser.getTok().getLoc();
2687 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2688
2689 return MatchOperand_Success;
2690}
2691
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002692/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2693/// of instructions. Legal values are:
2694/// ror #n 'n' in {0, 8, 16, 24}
2695ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2696parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2697 const AsmToken &Tok = Parser.getTok();
2698 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002699 if (Tok.isNot(AsmToken::Identifier))
2700 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002701 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002702 if (ShiftName != "ror" && ShiftName != "ROR")
2703 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002704 Parser.Lex(); // Eat the operator.
2705
2706 // A '#' and a rotate amount.
2707 if (Parser.getTok().isNot(AsmToken::Hash)) {
2708 Error(Parser.getTok().getLoc(), "'#' expected");
2709 return MatchOperand_ParseFail;
2710 }
2711 Parser.Lex(); // Eat hash token.
2712
2713 const MCExpr *ShiftAmount;
2714 SMLoc E = Parser.getTok().getLoc();
2715 if (getParser().ParseExpression(ShiftAmount)) {
2716 Error(E, "malformed rotate expression");
2717 return MatchOperand_ParseFail;
2718 }
2719 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2720 if (!CE) {
2721 Error(E, "rotate amount must be an immediate");
2722 return MatchOperand_ParseFail;
2723 }
2724
2725 int64_t Val = CE->getValue();
2726 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2727 // normally, zero is represented in asm by omitting the rotate operand
2728 // entirely.
2729 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2730 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2731 return MatchOperand_ParseFail;
2732 }
2733
2734 E = Parser.getTok().getLoc();
2735 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2736
2737 return MatchOperand_Success;
2738}
2739
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002740ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2741parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2742 SMLoc S = Parser.getTok().getLoc();
2743 // The bitfield descriptor is really two operands, the LSB and the width.
2744 if (Parser.getTok().isNot(AsmToken::Hash)) {
2745 Error(Parser.getTok().getLoc(), "'#' expected");
2746 return MatchOperand_ParseFail;
2747 }
2748 Parser.Lex(); // Eat hash token.
2749
2750 const MCExpr *LSBExpr;
2751 SMLoc E = Parser.getTok().getLoc();
2752 if (getParser().ParseExpression(LSBExpr)) {
2753 Error(E, "malformed immediate expression");
2754 return MatchOperand_ParseFail;
2755 }
2756 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2757 if (!CE) {
2758 Error(E, "'lsb' operand must be an immediate");
2759 return MatchOperand_ParseFail;
2760 }
2761
2762 int64_t LSB = CE->getValue();
2763 // The LSB must be in the range [0,31]
2764 if (LSB < 0 || LSB > 31) {
2765 Error(E, "'lsb' operand must be in the range [0,31]");
2766 return MatchOperand_ParseFail;
2767 }
2768 E = Parser.getTok().getLoc();
2769
2770 // Expect another immediate operand.
2771 if (Parser.getTok().isNot(AsmToken::Comma)) {
2772 Error(Parser.getTok().getLoc(), "too few operands");
2773 return MatchOperand_ParseFail;
2774 }
2775 Parser.Lex(); // Eat hash token.
2776 if (Parser.getTok().isNot(AsmToken::Hash)) {
2777 Error(Parser.getTok().getLoc(), "'#' expected");
2778 return MatchOperand_ParseFail;
2779 }
2780 Parser.Lex(); // Eat hash token.
2781
2782 const MCExpr *WidthExpr;
2783 if (getParser().ParseExpression(WidthExpr)) {
2784 Error(E, "malformed immediate expression");
2785 return MatchOperand_ParseFail;
2786 }
2787 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2788 if (!CE) {
2789 Error(E, "'width' operand must be an immediate");
2790 return MatchOperand_ParseFail;
2791 }
2792
2793 int64_t Width = CE->getValue();
2794 // The LSB must be in the range [1,32-lsb]
2795 if (Width < 1 || Width > 32 - LSB) {
2796 Error(E, "'width' operand must be in the range [1,32-lsb]");
2797 return MatchOperand_ParseFail;
2798 }
2799 E = Parser.getTok().getLoc();
2800
2801 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2802
2803 return MatchOperand_Success;
2804}
2805
Jim Grosbach7ce05792011-08-03 23:50:40 +00002806ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2807parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2808 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002809 // postidx_reg := '+' register {, shift}
2810 // | '-' register {, shift}
2811 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002812
2813 // This method must return MatchOperand_NoMatch without consuming any tokens
2814 // in the case where there is no match, as other alternatives take other
2815 // parse methods.
2816 AsmToken Tok = Parser.getTok();
2817 SMLoc S = Tok.getLoc();
2818 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002819 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002820 int Reg = -1;
2821 if (Tok.is(AsmToken::Plus)) {
2822 Parser.Lex(); // Eat the '+' token.
2823 haveEaten = true;
2824 } else if (Tok.is(AsmToken::Minus)) {
2825 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002826 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002827 haveEaten = true;
2828 }
2829 if (Parser.getTok().is(AsmToken::Identifier))
2830 Reg = tryParseRegister();
2831 if (Reg == -1) {
2832 if (!haveEaten)
2833 return MatchOperand_NoMatch;
2834 Error(Parser.getTok().getLoc(), "register expected");
2835 return MatchOperand_ParseFail;
2836 }
2837 SMLoc E = Parser.getTok().getLoc();
2838
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002839 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2840 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002841 if (Parser.getTok().is(AsmToken::Comma)) {
2842 Parser.Lex(); // Eat the ','.
2843 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2844 return MatchOperand_ParseFail;
2845 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002846
2847 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2848 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002849
2850 return MatchOperand_Success;
2851}
2852
Jim Grosbach251bf252011-08-10 21:56:18 +00002853ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2854parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2855 // Check for a post-index addressing register operand. Specifically:
2856 // am3offset := '+' register
2857 // | '-' register
2858 // | register
2859 // | # imm
2860 // | # + imm
2861 // | # - imm
2862
2863 // This method must return MatchOperand_NoMatch without consuming any tokens
2864 // in the case where there is no match, as other alternatives take other
2865 // parse methods.
2866 AsmToken Tok = Parser.getTok();
2867 SMLoc S = Tok.getLoc();
2868
2869 // Do immediates first, as we always parse those if we have a '#'.
2870 if (Parser.getTok().is(AsmToken::Hash)) {
2871 Parser.Lex(); // Eat the '#'.
2872 // Explicitly look for a '-', as we need to encode negative zero
2873 // differently.
2874 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2875 const MCExpr *Offset;
2876 if (getParser().ParseExpression(Offset))
2877 return MatchOperand_ParseFail;
2878 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2879 if (!CE) {
2880 Error(S, "constant expression expected");
2881 return MatchOperand_ParseFail;
2882 }
2883 SMLoc E = Tok.getLoc();
2884 // Negative zero is encoded as the flag value INT32_MIN.
2885 int32_t Val = CE->getValue();
2886 if (isNegative && Val == 0)
2887 Val = INT32_MIN;
2888
2889 Operands.push_back(
2890 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2891
2892 return MatchOperand_Success;
2893 }
2894
2895
2896 bool haveEaten = false;
2897 bool isAdd = true;
2898 int Reg = -1;
2899 if (Tok.is(AsmToken::Plus)) {
2900 Parser.Lex(); // Eat the '+' token.
2901 haveEaten = true;
2902 } else if (Tok.is(AsmToken::Minus)) {
2903 Parser.Lex(); // Eat the '-' token.
2904 isAdd = false;
2905 haveEaten = true;
2906 }
2907 if (Parser.getTok().is(AsmToken::Identifier))
2908 Reg = tryParseRegister();
2909 if (Reg == -1) {
2910 if (!haveEaten)
2911 return MatchOperand_NoMatch;
2912 Error(Parser.getTok().getLoc(), "register expected");
2913 return MatchOperand_ParseFail;
2914 }
2915 SMLoc E = Parser.getTok().getLoc();
2916
2917 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2918 0, S, E));
2919
2920 return MatchOperand_Success;
2921}
2922
Jim Grosbacha77295d2011-09-08 22:07:06 +00002923/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2924/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2925/// when they refer multiple MIOperands inside a single one.
2926bool ARMAsmParser::
2927cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2928 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2929 // Rt, Rt2
2930 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2931 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2932 // Create a writeback register dummy placeholder.
2933 Inst.addOperand(MCOperand::CreateReg(0));
2934 // addr
2935 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2936 // pred
2937 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2938 return true;
2939}
2940
2941/// cvtT2StrdPre - Convert parsed operands to MCInst.
2942/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2943/// when they refer multiple MIOperands inside a single one.
2944bool ARMAsmParser::
2945cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2946 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2947 // Create a writeback register dummy placeholder.
2948 Inst.addOperand(MCOperand::CreateReg(0));
2949 // Rt, Rt2
2950 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2951 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2952 // addr
2953 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2954 // pred
2955 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2956 return true;
2957}
2958
Jim Grosbacheeec0252011-09-08 00:39:19 +00002959/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2960/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2961/// when they refer multiple MIOperands inside a single one.
2962bool ARMAsmParser::
2963cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2964 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2965 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2966
2967 // Create a writeback register dummy placeholder.
2968 Inst.addOperand(MCOperand::CreateImm(0));
2969
2970 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2971 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2972 return true;
2973}
2974
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002975/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2976/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2977/// when they refer multiple MIOperands inside a single one.
2978bool ARMAsmParser::
2979cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2980 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2981 // Create a writeback register dummy placeholder.
2982 Inst.addOperand(MCOperand::CreateImm(0));
2983 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2984 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2985 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2986 return true;
2987}
2988
Jim Grosbach1355cf12011-07-26 17:10:22 +00002989/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002990/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2991/// when they refer multiple MIOperands inside a single one.
2992bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002993cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002994 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2995 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2996
2997 // Create a writeback register dummy placeholder.
2998 Inst.addOperand(MCOperand::CreateImm(0));
2999
Jim Grosbach7ce05792011-08-03 23:50:40 +00003000 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003001 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3002 return true;
3003}
3004
Owen Anderson9ab0f252011-08-26 20:43:14 +00003005/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3006/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3007/// when they refer multiple MIOperands inside a single one.
3008bool ARMAsmParser::
3009cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3010 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3011 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3012
3013 // Create a writeback register dummy placeholder.
3014 Inst.addOperand(MCOperand::CreateImm(0));
3015
3016 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3017 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3018 return true;
3019}
3020
3021
Jim Grosbach548340c2011-08-11 19:22:40 +00003022/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3023/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3024/// when they refer multiple MIOperands inside a single one.
3025bool ARMAsmParser::
3026cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3027 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3028 // Create a writeback register dummy placeholder.
3029 Inst.addOperand(MCOperand::CreateImm(0));
3030 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3031 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3032 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3033 return true;
3034}
3035
Jim Grosbach1355cf12011-07-26 17:10:22 +00003036/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003037/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3038/// when they refer multiple MIOperands inside a single one.
3039bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003040cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003041 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3042 // Create a writeback register dummy placeholder.
3043 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003044 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3045 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3046 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003047 return true;
3048}
3049
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003050/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3051/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3052/// when they refer multiple MIOperands inside a single one.
3053bool ARMAsmParser::
3054cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3055 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3056 // Create a writeback register dummy placeholder.
3057 Inst.addOperand(MCOperand::CreateImm(0));
3058 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3059 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3060 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3061 return true;
3062}
3063
Jim Grosbach7ce05792011-08-03 23:50:40 +00003064/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3065/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3066/// when they refer multiple MIOperands inside a single one.
3067bool ARMAsmParser::
3068cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3069 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3070 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003071 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003072 // Create a writeback register dummy placeholder.
3073 Inst.addOperand(MCOperand::CreateImm(0));
3074 // addr
3075 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3076 // offset
3077 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3078 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003079 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3080 return true;
3081}
3082
Jim Grosbach7ce05792011-08-03 23:50:40 +00003083/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003084/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3085/// when they refer multiple MIOperands inside a single one.
3086bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003087cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3088 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3089 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003090 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003091 // Create a writeback register dummy placeholder.
3092 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003093 // addr
3094 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3095 // offset
3096 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3097 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003098 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3099 return true;
3100}
3101
Jim Grosbach7ce05792011-08-03 23:50:40 +00003102/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003103/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3104/// when they refer multiple MIOperands inside a single one.
3105bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003106cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3107 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003108 // Create a writeback register dummy placeholder.
3109 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003110 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003111 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003112 // addr
3113 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3114 // offset
3115 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3116 // pred
3117 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3118 return true;
3119}
3120
3121/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3122/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3123/// when they refer multiple MIOperands inside a single one.
3124bool ARMAsmParser::
3125cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3126 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3127 // Create a writeback register dummy placeholder.
3128 Inst.addOperand(MCOperand::CreateImm(0));
3129 // Rt
3130 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3131 // addr
3132 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3133 // offset
3134 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3135 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3137 return true;
3138}
3139
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003140/// cvtLdrdPre - Convert parsed operands to MCInst.
3141/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3142/// when they refer multiple MIOperands inside a single one.
3143bool ARMAsmParser::
3144cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3145 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3146 // Rt, Rt2
3147 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3148 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3149 // Create a writeback register dummy placeholder.
3150 Inst.addOperand(MCOperand::CreateImm(0));
3151 // addr
3152 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3153 // pred
3154 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3155 return true;
3156}
3157
Jim Grosbach14605d12011-08-11 20:28:23 +00003158/// cvtStrdPre - Convert parsed operands to MCInst.
3159/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3160/// when they refer multiple MIOperands inside a single one.
3161bool ARMAsmParser::
3162cvtStrdPre(MCInst &Inst, unsigned Opcode,
3163 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3164 // Create a writeback register dummy placeholder.
3165 Inst.addOperand(MCOperand::CreateImm(0));
3166 // Rt, Rt2
3167 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3168 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3169 // addr
3170 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3171 // pred
3172 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3173 return true;
3174}
3175
Jim Grosbach623a4542011-08-10 22:42:16 +00003176/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3177/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3178/// when they refer multiple MIOperands inside a single one.
3179bool ARMAsmParser::
3180cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3181 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3182 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3183 // Create a writeback register dummy placeholder.
3184 Inst.addOperand(MCOperand::CreateImm(0));
3185 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3186 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3187 return true;
3188}
3189
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003190/// cvtThumbMultiple- Convert parsed operands to MCInst.
3191/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3192/// when they refer multiple MIOperands inside a single one.
3193bool ARMAsmParser::
3194cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3195 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3196 // The second source operand must be the same register as the destination
3197 // operand.
3198 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003199 (((ARMOperand*)Operands[3])->getReg() !=
3200 ((ARMOperand*)Operands[5])->getReg()) &&
3201 (((ARMOperand*)Operands[3])->getReg() !=
3202 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003203 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003204 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003205 return false;
3206 }
3207 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3208 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3209 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003210 // If we have a three-operand form, use that, else the second source operand
3211 // is just the destination operand again.
3212 if (Operands.size() == 6)
3213 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3214 else
3215 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003216 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3217
3218 return true;
3219}
Jim Grosbach623a4542011-08-10 22:42:16 +00003220
Bill Wendlinge7176102010-11-06 22:36:58 +00003221/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003222/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003223bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003224parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003225 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003226 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003227 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003228 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003229 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003230
Sean Callanan18b83232010-01-19 21:44:56 +00003231 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003232 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003233 if (BaseRegNum == -1)
3234 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003235
Daniel Dunbar05710932011-01-18 05:34:17 +00003236 // The next token must either be a comma or a closing bracket.
3237 const AsmToken &Tok = Parser.getTok();
3238 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003239 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003240
Jim Grosbach7ce05792011-08-03 23:50:40 +00003241 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003242 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003243 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003244
Jim Grosbach7ce05792011-08-03 23:50:40 +00003245 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003246 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003247
Jim Grosbachfb12f352011-09-19 18:42:21 +00003248 // If there's a pre-indexing writeback marker, '!', just add it as a token
3249 // operand. It's rather odd, but syntactically valid.
3250 if (Parser.getTok().is(AsmToken::Exclaim)) {
3251 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3252 Parser.Lex(); // Eat the '!'.
3253 }
3254
Jim Grosbach7ce05792011-08-03 23:50:40 +00003255 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003256 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003257
Jim Grosbach7ce05792011-08-03 23:50:40 +00003258 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3259 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003260
Jim Grosbach57dcb852011-10-11 17:29:55 +00003261 // If we have a ':', it's an alignment specifier.
3262 if (Parser.getTok().is(AsmToken::Colon)) {
3263 Parser.Lex(); // Eat the ':'.
3264 E = Parser.getTok().getLoc();
3265
3266 const MCExpr *Expr;
3267 if (getParser().ParseExpression(Expr))
3268 return true;
3269
3270 // The expression has to be a constant. Memory references with relocations
3271 // don't come through here, as they use the <label> forms of the relevant
3272 // instructions.
3273 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3274 if (!CE)
3275 return Error (E, "constant expression expected");
3276
3277 unsigned Align = 0;
3278 switch (CE->getValue()) {
3279 default:
3280 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3281 case 64: Align = 8; break;
3282 case 128: Align = 16; break;
3283 case 256: Align = 32; break;
3284 }
3285
3286 // Now we should have the closing ']'
3287 E = Parser.getTok().getLoc();
3288 if (Parser.getTok().isNot(AsmToken::RBrac))
3289 return Error(E, "']' expected");
3290 Parser.Lex(); // Eat right bracket token.
3291
3292 // Don't worry about range checking the value here. That's handled by
3293 // the is*() predicates.
3294 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3295 ARM_AM::no_shift, 0, Align,
3296 false, S, E));
3297
3298 // If there's a pre-indexing writeback marker, '!', just add it as a token
3299 // operand.
3300 if (Parser.getTok().is(AsmToken::Exclaim)) {
3301 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3302 Parser.Lex(); // Eat the '!'.
3303 }
3304
3305 return false;
3306 }
3307
3308 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003309 // offset.
3310 if (Parser.getTok().is(AsmToken::Hash)) {
3311 Parser.Lex(); // Eat the '#'.
3312 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003313
Owen Anderson0da10cf2011-08-29 19:36:44 +00003314 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003315 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003316 if (getParser().ParseExpression(Offset))
3317 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003318
3319 // The expression has to be a constant. Memory references with relocations
3320 // don't come through here, as they use the <label> forms of the relevant
3321 // instructions.
3322 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3323 if (!CE)
3324 return Error (E, "constant expression expected");
3325
Owen Anderson0da10cf2011-08-29 19:36:44 +00003326 // If the constant was #-0, represent it as INT32_MIN.
3327 int32_t Val = CE->getValue();
3328 if (isNegative && Val == 0)
3329 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3330
Jim Grosbach7ce05792011-08-03 23:50:40 +00003331 // Now we should have the closing ']'
3332 E = Parser.getTok().getLoc();
3333 if (Parser.getTok().isNot(AsmToken::RBrac))
3334 return Error(E, "']' expected");
3335 Parser.Lex(); // Eat right bracket token.
3336
3337 // Don't worry about range checking the value here. That's handled by
3338 // the is*() predicates.
3339 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003340 ARM_AM::no_shift, 0, 0,
3341 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003342
3343 // If there's a pre-indexing writeback marker, '!', just add it as a token
3344 // operand.
3345 if (Parser.getTok().is(AsmToken::Exclaim)) {
3346 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3347 Parser.Lex(); // Eat the '!'.
3348 }
3349
3350 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003351 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003352
3353 // The register offset is optionally preceded by a '+' or '-'
3354 bool isNegative = false;
3355 if (Parser.getTok().is(AsmToken::Minus)) {
3356 isNegative = true;
3357 Parser.Lex(); // Eat the '-'.
3358 } else if (Parser.getTok().is(AsmToken::Plus)) {
3359 // Nothing to do.
3360 Parser.Lex(); // Eat the '+'.
3361 }
3362
3363 E = Parser.getTok().getLoc();
3364 int OffsetRegNum = tryParseRegister();
3365 if (OffsetRegNum == -1)
3366 return Error(E, "register expected");
3367
3368 // If there's a shift operator, handle it.
3369 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003370 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003371 if (Parser.getTok().is(AsmToken::Comma)) {
3372 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003373 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003374 return true;
3375 }
3376
3377 // Now we should have the closing ']'
3378 E = Parser.getTok().getLoc();
3379 if (Parser.getTok().isNot(AsmToken::RBrac))
3380 return Error(E, "']' expected");
3381 Parser.Lex(); // Eat right bracket token.
3382
3383 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003384 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003385 S, E));
3386
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003387 // If there's a pre-indexing writeback marker, '!', just add it as a token
3388 // operand.
3389 if (Parser.getTok().is(AsmToken::Exclaim)) {
3390 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3391 Parser.Lex(); // Eat the '!'.
3392 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003393
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003394 return false;
3395}
3396
Jim Grosbach7ce05792011-08-03 23:50:40 +00003397/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003398/// ( lsl | lsr | asr | ror ) , # shift_amount
3399/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003400/// return true if it parses a shift otherwise it returns false.
3401bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3402 unsigned &Amount) {
3403 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003404 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003405 if (Tok.isNot(AsmToken::Identifier))
3406 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003407 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003408 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003409 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003410 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003411 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003412 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003413 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003414 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003415 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003416 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003417 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003418 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003419 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003420 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003421
Jim Grosbach7ce05792011-08-03 23:50:40 +00003422 // rrx stands alone.
3423 Amount = 0;
3424 if (St != ARM_AM::rrx) {
3425 Loc = Parser.getTok().getLoc();
3426 // A '#' and a shift amount.
3427 const AsmToken &HashTok = Parser.getTok();
3428 if (HashTok.isNot(AsmToken::Hash))
3429 return Error(HashTok.getLoc(), "'#' expected");
3430 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003431
Jim Grosbach7ce05792011-08-03 23:50:40 +00003432 const MCExpr *Expr;
3433 if (getParser().ParseExpression(Expr))
3434 return true;
3435 // Range check the immediate.
3436 // lsl, ror: 0 <= imm <= 31
3437 // lsr, asr: 0 <= imm <= 32
3438 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3439 if (!CE)
3440 return Error(Loc, "shift amount must be an immediate");
3441 int64_t Imm = CE->getValue();
3442 if (Imm < 0 ||
3443 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3444 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3445 return Error(Loc, "immediate shift value out of range");
3446 Amount = Imm;
3447 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003448
3449 return false;
3450}
3451
Jim Grosbach9d390362011-10-03 23:38:36 +00003452/// parseFPImm - A floating point immediate expression operand.
3453ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3454parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3455 SMLoc S = Parser.getTok().getLoc();
3456
3457 if (Parser.getTok().isNot(AsmToken::Hash))
3458 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003459
3460 // Disambiguate the VMOV forms that can accept an FP immediate.
3461 // vmov.f32 <sreg>, #imm
3462 // vmov.f64 <dreg>, #imm
3463 // vmov.f32 <dreg>, #imm @ vector f32x2
3464 // vmov.f32 <qreg>, #imm @ vector f32x4
3465 //
3466 // There are also the NEON VMOV instructions which expect an
3467 // integer constant. Make sure we don't try to parse an FPImm
3468 // for these:
3469 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3470 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3471 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3472 TyOp->getToken() != ".f64"))
3473 return MatchOperand_NoMatch;
3474
Jim Grosbach9d390362011-10-03 23:38:36 +00003475 Parser.Lex(); // Eat the '#'.
3476
3477 // Handle negation, as that still comes through as a separate token.
3478 bool isNegative = false;
3479 if (Parser.getTok().is(AsmToken::Minus)) {
3480 isNegative = true;
3481 Parser.Lex();
3482 }
3483 const AsmToken &Tok = Parser.getTok();
3484 if (Tok.is(AsmToken::Real)) {
3485 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3486 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3487 // If we had a '-' in front, toggle the sign bit.
3488 IntVal ^= (uint64_t)isNegative << 63;
3489 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3490 Parser.Lex(); // Eat the token.
3491 if (Val == -1) {
3492 TokError("floating point value out of range");
3493 return MatchOperand_ParseFail;
3494 }
3495 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3496 return MatchOperand_Success;
3497 }
3498 if (Tok.is(AsmToken::Integer)) {
3499 int64_t Val = Tok.getIntVal();
3500 Parser.Lex(); // Eat the token.
3501 if (Val > 255 || Val < 0) {
3502 TokError("encoded floating point value out of range");
3503 return MatchOperand_ParseFail;
3504 }
3505 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3506 return MatchOperand_Success;
3507 }
3508
3509 TokError("invalid floating point immediate");
3510 return MatchOperand_ParseFail;
3511}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003512/// Parse a arm instruction operand. For now this parses the operand regardless
3513/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003514bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003515 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003516 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003517
3518 // Check if the current operand has a custom associated parser, if so, try to
3519 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003520 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3521 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003522 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003523 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3524 // there was a match, but an error occurred, in which case, just return that
3525 // the operand parsing failed.
3526 if (ResTy == MatchOperand_ParseFail)
3527 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003528
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003529 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003530 default:
3531 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003532 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003533 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003534 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003535 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003536 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003537 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003538 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003539 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003540 else if (Res == -1) // irrecoverable error
3541 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003542 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3543 S = Parser.getTok().getLoc();
3544 Parser.Lex();
3545 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3546 return false;
3547 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003548
3549 // Fall though for the Identifier case that is not a register or a
3550 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003551 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003552 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3553 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003554 // This was not a register so parse other operands that start with an
3555 // identifier (like labels) as expressions and create them as immediates.
3556 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003557 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003558 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003559 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003560 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003561 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3562 return false;
3563 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003564 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003565 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003566 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003567 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003568 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003569 // #42 -> immediate.
3570 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003571 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003572 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003573 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003574 const MCExpr *ImmVal;
3575 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003576 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3578 if (!CE) {
3579 Error(S, "constant expression expected");
3580 return MatchOperand_ParseFail;
3581 }
3582 int32_t Val = CE->getValue();
3583 if (isNegative && Val == 0)
3584 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003585 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003586 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3587 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003588 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003589 case AsmToken::Colon: {
3590 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003591 // FIXME: Check it's an expression prefix,
3592 // e.g. (FOO - :lower16:BAR) isn't legal.
3593 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003594 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003595 return true;
3596
Evan Cheng75972122011-01-13 07:58:56 +00003597 const MCExpr *SubExprVal;
3598 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003599 return true;
3600
Evan Cheng75972122011-01-13 07:58:56 +00003601 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3602 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003603 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003604 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003605 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003606 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003607 }
3608}
3609
Jim Grosbach1355cf12011-07-26 17:10:22 +00003610// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003611// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003612bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003613 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003614
3615 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003616 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003617 Parser.Lex(); // Eat ':'
3618
3619 if (getLexer().isNot(AsmToken::Identifier)) {
3620 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3621 return true;
3622 }
3623
3624 StringRef IDVal = Parser.getTok().getIdentifier();
3625 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003626 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003627 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003628 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003629 } else {
3630 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3631 return true;
3632 }
3633 Parser.Lex();
3634
3635 if (getLexer().isNot(AsmToken::Colon)) {
3636 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3637 return true;
3638 }
3639 Parser.Lex(); // Eat the last ':'
3640 return false;
3641}
3642
Daniel Dunbar352e1482011-01-11 15:59:50 +00003643/// \brief Given a mnemonic, split out possible predication code and carry
3644/// setting letters to form a canonical mnemonic and flags.
3645//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003646// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003647// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003648StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003649 unsigned &PredicationCode,
3650 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003651 unsigned &ProcessorIMod,
3652 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003653 PredicationCode = ARMCC::AL;
3654 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003655 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003656
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003657 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003658 //
3659 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003660 if ((Mnemonic == "movs" && isThumb()) ||
3661 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3662 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3663 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3664 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3665 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3666 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3667 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003668 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003669
Jim Grosbach3f00e312011-07-11 17:09:57 +00003670 // First, split out any predication code. Ignore mnemonics we know aren't
3671 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003672 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003673 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003674 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003675 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003676 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3677 .Case("eq", ARMCC::EQ)
3678 .Case("ne", ARMCC::NE)
3679 .Case("hs", ARMCC::HS)
3680 .Case("cs", ARMCC::HS)
3681 .Case("lo", ARMCC::LO)
3682 .Case("cc", ARMCC::LO)
3683 .Case("mi", ARMCC::MI)
3684 .Case("pl", ARMCC::PL)
3685 .Case("vs", ARMCC::VS)
3686 .Case("vc", ARMCC::VC)
3687 .Case("hi", ARMCC::HI)
3688 .Case("ls", ARMCC::LS)
3689 .Case("ge", ARMCC::GE)
3690 .Case("lt", ARMCC::LT)
3691 .Case("gt", ARMCC::GT)
3692 .Case("le", ARMCC::LE)
3693 .Case("al", ARMCC::AL)
3694 .Default(~0U);
3695 if (CC != ~0U) {
3696 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3697 PredicationCode = CC;
3698 }
Bill Wendling52925b62010-10-29 23:50:21 +00003699 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003700
Daniel Dunbar352e1482011-01-11 15:59:50 +00003701 // Next, determine if we have a carry setting bit. We explicitly ignore all
3702 // the instructions we know end in 's'.
3703 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003704 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003705 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3706 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3707 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003708 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3709 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003710 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3711 CarrySetting = true;
3712 }
3713
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003714 // The "cps" instruction can have a interrupt mode operand which is glued into
3715 // the mnemonic. Check if this is the case, split it and parse the imod op
3716 if (Mnemonic.startswith("cps")) {
3717 // Split out any imod code.
3718 unsigned IMod =
3719 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3720 .Case("ie", ARM_PROC::IE)
3721 .Case("id", ARM_PROC::ID)
3722 .Default(~0U);
3723 if (IMod != ~0U) {
3724 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3725 ProcessorIMod = IMod;
3726 }
3727 }
3728
Jim Grosbach89df9962011-08-26 21:43:41 +00003729 // The "it" instruction has the condition mask on the end of the mnemonic.
3730 if (Mnemonic.startswith("it")) {
3731 ITMask = Mnemonic.slice(2, Mnemonic.size());
3732 Mnemonic = Mnemonic.slice(0, 2);
3733 }
3734
Daniel Dunbar352e1482011-01-11 15:59:50 +00003735 return Mnemonic;
3736}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003737
3738/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3739/// inclusion of carry set or predication code operands.
3740//
3741// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003742void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003743getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003744 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003745 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3746 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003747 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003748 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003749 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003750 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003751 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003752 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003753 Mnemonic == "mla" || Mnemonic == "smlal" ||
3754 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003755 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003756 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003757 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003758
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003759 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3760 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3761 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3762 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003763 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3764 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003765 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003766 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3767 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3768 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003769 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3770 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003771 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003772 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003773 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003774 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003775
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003776 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003777 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003778 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003779 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003780 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003781}
3782
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003783bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3784 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003785 // FIXME: This is all horribly hacky. We really need a better way to deal
3786 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003787
3788 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3789 // another does not. Specifically, the MOVW instruction does not. So we
3790 // special case it here and remove the defaulted (non-setting) cc_out
3791 // operand if that's the instruction we're trying to match.
3792 //
3793 // We do this as post-processing of the explicit operands rather than just
3794 // conditionally adding the cc_out in the first place because we need
3795 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003796 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003797 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3798 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3799 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3800 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003801
3802 // Register-register 'add' for thumb does not have a cc_out operand
3803 // when there are only two register operands.
3804 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3805 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3806 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3807 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3808 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003809 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003810 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3811 // have to check the immediate range here since Thumb2 has a variant
3812 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003813 if (((isThumb() && Mnemonic == "add") ||
3814 (isThumbTwo() && Mnemonic == "sub")) &&
3815 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003816 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3817 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3818 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003819 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3820 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3821 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003822 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003823 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3824 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003825 // selecting via the generic "add" mnemonic, so to know that we
3826 // should remove the cc_out operand, we have to explicitly check that
3827 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003828 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3829 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003830 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3831 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3832 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3833 // Nest conditions rather than one big 'if' statement for readability.
3834 //
3835 // If either register is a high reg, it's either one of the SP
3836 // variants (handled above) or a 32-bit encoding, so we just
3837 // check against T3.
3838 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3839 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3840 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3841 return false;
3842 // If both registers are low, we're in an IT block, and the immediate is
3843 // in range, we should use encoding T1 instead, which has a cc_out.
3844 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003845 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003846 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3847 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3848 return false;
3849
3850 // Otherwise, we use encoding T4, which does not have a cc_out
3851 // operand.
3852 return true;
3853 }
3854
Jim Grosbach64944f42011-09-14 21:00:40 +00003855 // The thumb2 multiply instruction doesn't have a CCOut register, so
3856 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3857 // use the 16-bit encoding or not.
3858 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3859 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3860 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3861 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3862 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3863 // If the registers aren't low regs, the destination reg isn't the
3864 // same as one of the source regs, or the cc_out operand is zero
3865 // outside of an IT block, we have to use the 32-bit encoding, so
3866 // remove the cc_out operand.
3867 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3868 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3869 !inITBlock() ||
3870 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3871 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3872 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3873 static_cast<ARMOperand*>(Operands[4])->getReg())))
3874 return true;
3875
3876
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003877
Jim Grosbachf69c8042011-08-24 21:42:27 +00003878 // Register-register 'add/sub' for thumb does not have a cc_out operand
3879 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3880 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3881 // right, this will result in better diagnostics (which operand is off)
3882 // anyway.
3883 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3884 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003885 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3886 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3887 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3888 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003889
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003890 return false;
3891}
3892
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003893/// Parse an arm instruction mnemonic followed by its operands.
3894bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3895 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3896 // Create the leading tokens for the mnemonic, split by '.' characters.
3897 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003898 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003899
Daniel Dunbar352e1482011-01-11 15:59:50 +00003900 // Split out the predication code and carry setting flag from the mnemonic.
3901 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003902 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003903 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003904 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003905 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003906 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003907
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003908 // In Thumb1, only the branch (B) instruction can be predicated.
3909 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3910 Parser.EatToEndOfStatement();
3911 return Error(NameLoc, "conditional execution not supported in Thumb1");
3912 }
3913
Jim Grosbachffa32252011-07-19 19:13:28 +00003914 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3915
Jim Grosbach89df9962011-08-26 21:43:41 +00003916 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3917 // is the mask as it will be for the IT encoding if the conditional
3918 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3919 // where the conditional bit0 is zero, the instruction post-processing
3920 // will adjust the mask accordingly.
3921 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003922 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3923 if (ITMask.size() > 3) {
3924 Parser.EatToEndOfStatement();
3925 return Error(Loc, "too many conditions on IT instruction");
3926 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003927 unsigned Mask = 8;
3928 for (unsigned i = ITMask.size(); i != 0; --i) {
3929 char pos = ITMask[i - 1];
3930 if (pos != 't' && pos != 'e') {
3931 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003932 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003933 }
3934 Mask >>= 1;
3935 if (ITMask[i - 1] == 't')
3936 Mask |= 8;
3937 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003938 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003939 }
3940
Jim Grosbachffa32252011-07-19 19:13:28 +00003941 // FIXME: This is all a pretty gross hack. We should automatically handle
3942 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003943
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003944 // Next, add the CCOut and ConditionCode operands, if needed.
3945 //
3946 // For mnemonics which can ever incorporate a carry setting bit or predication
3947 // code, our matching model involves us always generating CCOut and
3948 // ConditionCode operands to match the mnemonic "as written" and then we let
3949 // the matcher deal with finding the right instruction or generating an
3950 // appropriate error.
3951 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003952 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003953
Jim Grosbach33c16a22011-07-14 22:04:21 +00003954 // If we had a carry-set on an instruction that can't do that, issue an
3955 // error.
3956 if (!CanAcceptCarrySet && CarrySetting) {
3957 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003958 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003959 "' can not set flags, but 's' suffix specified");
3960 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003961 // If we had a predication code on an instruction that can't do that, issue an
3962 // error.
3963 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3964 Parser.EatToEndOfStatement();
3965 return Error(NameLoc, "instruction '" + Mnemonic +
3966 "' is not predicable, but condition code specified");
3967 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003968
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003969 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003970 if (CanAcceptCarrySet) {
3971 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003972 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003973 Loc));
3974 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003975
3976 // Add the predication code operand, if necessary.
3977 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003978 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3979 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003980 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003981 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003982 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003983
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003984 // Add the processor imod operand, if necessary.
3985 if (ProcessorIMod) {
3986 Operands.push_back(ARMOperand::CreateImm(
3987 MCConstantExpr::Create(ProcessorIMod, getContext()),
3988 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003989 }
3990
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003991 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003992 while (Next != StringRef::npos) {
3993 Start = Next;
3994 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003995 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003996
Jim Grosbach4d23e992011-08-24 22:19:48 +00003997 // For now, we're only parsing Thumb1 (for the most part), so
3998 // just ignore ".n" qualifiers. We'll use them to restrict
3999 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004000 if (ExtraToken != ".n") {
4001 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4002 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4003 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004004 }
4005
4006 // Read the remaining operands.
4007 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004008 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004009 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004010 Parser.EatToEndOfStatement();
4011 return true;
4012 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004013
4014 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004015 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004016
4017 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004018 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004019 Parser.EatToEndOfStatement();
4020 return true;
4021 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004022 }
4023 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004024
Chris Lattnercbf8a982010-09-11 16:18:25 +00004025 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004026 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004027 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004028 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004029 }
Bill Wendling146018f2010-11-06 21:42:12 +00004030
Chris Lattner34e53142010-09-08 05:10:46 +00004031 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004032
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004033 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4034 // do and don't have a cc_out optional-def operand. With some spot-checks
4035 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004036 // parse and adjust accordingly before actually matching. We shouldn't ever
4037 // try to remove a cc_out operand that was explicitly set on the the
4038 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4039 // table driven matcher doesn't fit well with the ARM instruction set.
4040 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004041 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4042 Operands.erase(Operands.begin() + 1);
4043 delete Op;
4044 }
4045
Jim Grosbachcf121c32011-07-28 21:57:55 +00004046 // ARM mode 'blx' need special handling, as the register operand version
4047 // is predicable, but the label operand version is not. So, we can't rely
4048 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004049 // a k_CondCode operand in the list. If we're trying to match the label
4050 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004051 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4052 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4053 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4054 Operands.erase(Operands.begin() + 1);
4055 delete Op;
4056 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004057
4058 // The vector-compare-to-zero instructions have a literal token "#0" at
4059 // the end that comes to here as an immediate operand. Convert it to a
4060 // token to play nicely with the matcher.
4061 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4062 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4063 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4064 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4065 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4066 if (CE && CE->getValue() == 0) {
4067 Operands.erase(Operands.begin() + 5);
4068 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4069 delete Op;
4070 }
4071 }
Jim Grosbach68259142011-10-03 22:30:24 +00004072 // VCMP{E} does the same thing, but with a different operand count.
4073 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4074 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4075 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4076 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4077 if (CE && CE->getValue() == 0) {
4078 Operands.erase(Operands.begin() + 4);
4079 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4080 delete Op;
4081 }
4082 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004083 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4084 // end. Convert it to a token here.
4085 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4086 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4087 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4088 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4089 if (CE && CE->getValue() == 0) {
4090 Operands.erase(Operands.begin() + 5);
4091 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4092 delete Op;
4093 }
4094 }
4095
Chris Lattner98986712010-01-14 22:21:20 +00004096 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004097}
4098
Jim Grosbach189610f2011-07-26 18:25:39 +00004099// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004100
4101// return 'true' if register list contains non-low GPR registers,
4102// 'false' otherwise. If Reg is in the register list or is HiReg, set
4103// 'containsReg' to true.
4104static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4105 unsigned HiReg, bool &containsReg) {
4106 containsReg = false;
4107 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4108 unsigned OpReg = Inst.getOperand(i).getReg();
4109 if (OpReg == Reg)
4110 containsReg = true;
4111 // Anything other than a low register isn't legal here.
4112 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4113 return true;
4114 }
4115 return false;
4116}
4117
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004118// Check if the specified regisgter is in the register list of the inst,
4119// starting at the indicated operand number.
4120static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4121 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4122 unsigned OpReg = Inst.getOperand(i).getReg();
4123 if (OpReg == Reg)
4124 return true;
4125 }
4126 return false;
4127}
4128
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004129// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4130// the ARMInsts array) instead. Getting that here requires awkward
4131// API changes, though. Better way?
4132namespace llvm {
4133extern MCInstrDesc ARMInsts[];
4134}
4135static MCInstrDesc &getInstDesc(unsigned Opcode) {
4136 return ARMInsts[Opcode];
4137}
4138
Jim Grosbach189610f2011-07-26 18:25:39 +00004139// FIXME: We would really like to be able to tablegen'erate this.
4140bool ARMAsmParser::
4141validateInstruction(MCInst &Inst,
4142 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004143 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4144 SMLoc Loc = Operands[0]->getStartLoc();
4145 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004146 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4147 // being allowed in IT blocks, but not being predicable. It just always
4148 // executes.
4149 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004150 unsigned bit = 1;
4151 if (ITState.FirstCond)
4152 ITState.FirstCond = false;
4153 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004154 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004155 // The instruction must be predicable.
4156 if (!MCID.isPredicable())
4157 return Error(Loc, "instructions in IT block must be predicable");
4158 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4159 unsigned ITCond = bit ? ITState.Cond :
4160 ARMCC::getOppositeCondition(ITState.Cond);
4161 if (Cond != ITCond) {
4162 // Find the condition code Operand to get its SMLoc information.
4163 SMLoc CondLoc;
4164 for (unsigned i = 1; i < Operands.size(); ++i)
4165 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4166 CondLoc = Operands[i]->getStartLoc();
4167 return Error(CondLoc, "incorrect condition in IT block; got '" +
4168 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4169 "', but expected '" +
4170 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4171 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004172 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004173 } else if (isThumbTwo() && MCID.isPredicable() &&
4174 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004175 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4176 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004177 return Error(Loc, "predicated instructions must be in IT block");
4178
Jim Grosbach189610f2011-07-26 18:25:39 +00004179 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004180 case ARM::LDRD:
4181 case ARM::LDRD_PRE:
4182 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004183 case ARM::LDREXD: {
4184 // Rt2 must be Rt + 1.
4185 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4186 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4187 if (Rt2 != Rt + 1)
4188 return Error(Operands[3]->getStartLoc(),
4189 "destination operands must be sequential");
4190 return false;
4191 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004192 case ARM::STRD: {
4193 // Rt2 must be Rt + 1.
4194 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4195 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4196 if (Rt2 != Rt + 1)
4197 return Error(Operands[3]->getStartLoc(),
4198 "source operands must be sequential");
4199 return false;
4200 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004201 case ARM::STRD_PRE:
4202 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004203 case ARM::STREXD: {
4204 // Rt2 must be Rt + 1.
4205 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4206 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4207 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004208 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004209 "source operands must be sequential");
4210 return false;
4211 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004212 case ARM::SBFX:
4213 case ARM::UBFX: {
4214 // width must be in range [1, 32-lsb]
4215 unsigned lsb = Inst.getOperand(2).getImm();
4216 unsigned widthm1 = Inst.getOperand(3).getImm();
4217 if (widthm1 >= 32 - lsb)
4218 return Error(Operands[5]->getStartLoc(),
4219 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004220 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004221 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004222 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004223 // If we're parsing Thumb2, the .w variant is available and handles
4224 // most cases that are normally illegal for a Thumb1 LDM
4225 // instruction. We'll make the transformation in processInstruction()
4226 // if necessary.
4227 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004228 // Thumb LDM instructions are writeback iff the base register is not
4229 // in the register list.
4230 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004231 bool hasWritebackToken =
4232 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4233 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004234 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004235 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004236 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4237 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004238 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004239 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004240 return Error(Operands[2]->getStartLoc(),
4241 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004242 // If we should not have writeback, there must not be a '!'. This is
4243 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004244 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004245 return Error(Operands[3]->getStartLoc(),
4246 "writeback operator '!' not allowed when base register "
4247 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004248
4249 break;
4250 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004251 case ARM::t2LDMIA_UPD: {
4252 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4253 return Error(Operands[4]->getStartLoc(),
4254 "writeback operator '!' not allowed when base register "
4255 "in register list");
4256 break;
4257 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004258 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004259 bool listContainsBase;
4260 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4261 return Error(Operands[2]->getStartLoc(),
4262 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004263 break;
4264 }
4265 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004266 bool listContainsBase;
4267 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4268 return Error(Operands[2]->getStartLoc(),
4269 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004270 break;
4271 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004272 case ARM::tSTMIA_UPD: {
4273 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004274 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004275 return Error(Operands[4]->getStartLoc(),
4276 "registers must be in range r0-r7");
4277 break;
4278 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004279 }
4280
4281 return false;
4282}
4283
Jim Grosbachf8fce712011-08-11 17:35:48 +00004284void ARMAsmParser::
4285processInstruction(MCInst &Inst,
4286 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4287 switch (Inst.getOpcode()) {
4288 case ARM::LDMIA_UPD:
4289 // If this is a load of a single register via a 'pop', then we should use
4290 // a post-indexed LDR instruction instead, per the ARM ARM.
4291 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4292 Inst.getNumOperands() == 5) {
4293 MCInst TmpInst;
4294 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4295 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4296 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4297 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4298 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4299 TmpInst.addOperand(MCOperand::CreateImm(4));
4300 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4301 TmpInst.addOperand(Inst.getOperand(3));
4302 Inst = TmpInst;
4303 }
4304 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004305 case ARM::STMDB_UPD:
4306 // If this is a store of a single register via a 'push', then we should use
4307 // a pre-indexed STR instruction instead, per the ARM ARM.
4308 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4309 Inst.getNumOperands() == 5) {
4310 MCInst TmpInst;
4311 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4312 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4313 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4314 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4315 TmpInst.addOperand(MCOperand::CreateImm(-4));
4316 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4317 TmpInst.addOperand(Inst.getOperand(3));
4318 Inst = TmpInst;
4319 }
4320 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004321 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004322 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4323 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4324 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4325 // to encoding T1 if <Rd> is omitted."
4326 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004327 Inst.setOpcode(ARM::tADDi3);
4328 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004329 case ARM::tSUBi8:
4330 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4331 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4332 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4333 // to encoding T1 if <Rd> is omitted."
4334 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4335 Inst.setOpcode(ARM::tSUBi3);
4336 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004337 case ARM::tB:
4338 // A Thumb conditional branch outside of an IT block is a tBcc.
4339 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4340 Inst.setOpcode(ARM::tBcc);
4341 break;
4342 case ARM::t2B:
4343 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4344 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4345 Inst.setOpcode(ARM::t2Bcc);
4346 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004347 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004348 // If the conditional is AL or we're in an IT block, we really want t2B.
4349 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004350 Inst.setOpcode(ARM::t2B);
4351 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004352 case ARM::tBcc:
4353 // If the conditional is AL, we really want tB.
4354 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4355 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004356 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004357 case ARM::tLDMIA: {
4358 // If the register list contains any high registers, or if the writeback
4359 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4360 // instead if we're in Thumb2. Otherwise, this should have generated
4361 // an error in validateInstruction().
4362 unsigned Rn = Inst.getOperand(0).getReg();
4363 bool hasWritebackToken =
4364 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4365 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4366 bool listContainsBase;
4367 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4368 (!listContainsBase && !hasWritebackToken) ||
4369 (listContainsBase && hasWritebackToken)) {
4370 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4371 assert (isThumbTwo());
4372 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4373 // If we're switching to the updating version, we need to insert
4374 // the writeback tied operand.
4375 if (hasWritebackToken)
4376 Inst.insert(Inst.begin(),
4377 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4378 }
4379 break;
4380 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004381 case ARM::tSTMIA_UPD: {
4382 // If the register list contains any high registers, we need to use
4383 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4384 // should have generated an error in validateInstruction().
4385 unsigned Rn = Inst.getOperand(0).getReg();
4386 bool listContainsBase;
4387 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4388 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4389 assert (isThumbTwo());
4390 Inst.setOpcode(ARM::t2STMIA_UPD);
4391 }
4392 break;
4393 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004394 case ARM::t2MOVi: {
4395 // If we can use the 16-bit encoding and the user didn't explicitly
4396 // request the 32-bit variant, transform it here.
4397 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4398 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004399 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4400 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4401 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004402 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4403 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4404 // The operands aren't in the same order for tMOVi8...
4405 MCInst TmpInst;
4406 TmpInst.setOpcode(ARM::tMOVi8);
4407 TmpInst.addOperand(Inst.getOperand(0));
4408 TmpInst.addOperand(Inst.getOperand(4));
4409 TmpInst.addOperand(Inst.getOperand(1));
4410 TmpInst.addOperand(Inst.getOperand(2));
4411 TmpInst.addOperand(Inst.getOperand(3));
4412 Inst = TmpInst;
4413 }
4414 break;
4415 }
4416 case ARM::t2MOVr: {
4417 // If we can use the 16-bit encoding and the user didn't explicitly
4418 // request the 32-bit variant, transform it here.
4419 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4420 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4421 Inst.getOperand(2).getImm() == ARMCC::AL &&
4422 Inst.getOperand(4).getReg() == ARM::CPSR &&
4423 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4424 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4425 // The operands aren't the same for tMOV[S]r... (no cc_out)
4426 MCInst TmpInst;
4427 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4428 TmpInst.addOperand(Inst.getOperand(0));
4429 TmpInst.addOperand(Inst.getOperand(1));
4430 TmpInst.addOperand(Inst.getOperand(2));
4431 TmpInst.addOperand(Inst.getOperand(3));
4432 Inst = TmpInst;
4433 }
4434 break;
4435 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004436 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004437 case ARM::t2SXTB:
4438 case ARM::t2UXTH:
4439 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004440 // If we can use the 16-bit encoding and the user didn't explicitly
4441 // request the 32-bit variant, transform it here.
4442 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4443 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4444 Inst.getOperand(2).getImm() == 0 &&
4445 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4446 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004447 unsigned NewOpc;
4448 switch (Inst.getOpcode()) {
4449 default: llvm_unreachable("Illegal opcode!");
4450 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4451 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4452 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4453 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4454 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004455 // The operands aren't the same for thumb1 (no rotate operand).
4456 MCInst TmpInst;
4457 TmpInst.setOpcode(NewOpc);
4458 TmpInst.addOperand(Inst.getOperand(0));
4459 TmpInst.addOperand(Inst.getOperand(1));
4460 TmpInst.addOperand(Inst.getOperand(3));
4461 TmpInst.addOperand(Inst.getOperand(4));
4462 Inst = TmpInst;
4463 }
4464 break;
4465 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004466 case ARM::t2IT: {
4467 // The mask bits for all but the first condition are represented as
4468 // the low bit of the condition code value implies 't'. We currently
4469 // always have 1 implies 't', so XOR toggle the bits if the low bit
4470 // of the condition code is zero. The encoding also expects the low
4471 // bit of the condition to be encoded as bit 4 of the mask operand,
4472 // so mask that in if needed
4473 MCOperand &MO = Inst.getOperand(1);
4474 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004475 unsigned OrigMask = Mask;
4476 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004477 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004478 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4479 for (unsigned i = 3; i != TZ; --i)
4480 Mask ^= 1 << i;
4481 } else
4482 Mask |= 0x10;
4483 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004484
4485 // Set up the IT block state according to the IT instruction we just
4486 // matched.
4487 assert(!inITBlock() && "nested IT blocks?!");
4488 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4489 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4490 ITState.CurPosition = 0;
4491 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004492 break;
4493 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004494 }
4495}
4496
Jim Grosbach47a0d522011-08-16 20:45:50 +00004497unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4498 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4499 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004500 unsigned Opc = Inst.getOpcode();
4501 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004502 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4503 assert(MCID.hasOptionalDef() &&
4504 "optionally flag setting instruction missing optional def operand");
4505 assert(MCID.NumOperands == Inst.getNumOperands() &&
4506 "operand count mismatch!");
4507 // Find the optional-def operand (cc_out).
4508 unsigned OpNo;
4509 for (OpNo = 0;
4510 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4511 ++OpNo)
4512 ;
4513 // If we're parsing Thumb1, reject it completely.
4514 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4515 return Match_MnemonicFail;
4516 // If we're parsing Thumb2, which form is legal depends on whether we're
4517 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004518 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4519 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004520 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004521 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4522 inITBlock())
4523 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004524 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004525 // Some high-register supporting Thumb1 encodings only allow both registers
4526 // to be from r0-r7 when in Thumb2.
4527 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4528 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4529 isARMLowRegister(Inst.getOperand(2).getReg()))
4530 return Match_RequiresThumb2;
4531 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004532 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004533 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4534 isARMLowRegister(Inst.getOperand(1).getReg()))
4535 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004536 return Match_Success;
4537}
4538
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004539bool ARMAsmParser::
4540MatchAndEmitInstruction(SMLoc IDLoc,
4541 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4542 MCStreamer &Out) {
4543 MCInst Inst;
4544 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004545 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004546 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004547 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004548 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004549 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004550 // Context sensitive operand constraints aren't handled by the matcher,
4551 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004552 if (validateInstruction(Inst, Operands)) {
4553 // Still progress the IT block, otherwise one wrong condition causes
4554 // nasty cascading errors.
4555 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004556 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004557 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004558
Jim Grosbachf8fce712011-08-11 17:35:48 +00004559 // Some instructions need post-processing to, for example, tweak which
4560 // encoding is selected.
4561 processInstruction(Inst, Operands);
4562
Jim Grosbacha1109882011-09-02 23:22:08 +00004563 // Only move forward at the very end so that everything in validate
4564 // and process gets a consistent answer about whether we're in an IT
4565 // block.
4566 forwardITPosition();
4567
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004568 Out.EmitInstruction(Inst);
4569 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004570 case Match_MissingFeature:
4571 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4572 return true;
4573 case Match_InvalidOperand: {
4574 SMLoc ErrorLoc = IDLoc;
4575 if (ErrorInfo != ~0U) {
4576 if (ErrorInfo >= Operands.size())
4577 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004578
Chris Lattnere73d4f82010-10-28 21:41:58 +00004579 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4580 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4581 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004582
Chris Lattnere73d4f82010-10-28 21:41:58 +00004583 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004584 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004585 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004586 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004587 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004588 // The converter function will have already emited a diagnostic.
4589 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004590 case Match_RequiresNotITBlock:
4591 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004592 case Match_RequiresITBlock:
4593 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004594 case Match_RequiresV6:
4595 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4596 case Match_RequiresThumb2:
4597 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004598 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004599
Eric Christopherc223e2b2010-10-29 09:26:59 +00004600 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004601 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004602}
4603
Jim Grosbach1355cf12011-07-26 17:10:22 +00004604/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004605bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4606 StringRef IDVal = DirectiveID.getIdentifier();
4607 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004608 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004609 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004610 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004611 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004612 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004613 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004614 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004615 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004616 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004617 return true;
4618}
4619
Jim Grosbach1355cf12011-07-26 17:10:22 +00004620/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004621/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004622bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004623 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4624 for (;;) {
4625 const MCExpr *Value;
4626 if (getParser().ParseExpression(Value))
4627 return true;
4628
Chris Lattneraaec2052010-01-19 19:46:13 +00004629 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004630
4631 if (getLexer().is(AsmToken::EndOfStatement))
4632 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004633
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004634 // FIXME: Improve diagnostic.
4635 if (getLexer().isNot(AsmToken::Comma))
4636 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004637 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004638 }
4639 }
4640
Sean Callananb9a25b72010-01-19 20:27:46 +00004641 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004642 return false;
4643}
4644
Jim Grosbach1355cf12011-07-26 17:10:22 +00004645/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004646/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004647bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004648 if (getLexer().isNot(AsmToken::EndOfStatement))
4649 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004650 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004651
4652 // TODO: set thumb mode
4653 // TODO: tell the MC streamer the mode
4654 // getParser().getStreamer().Emit???();
4655 return false;
4656}
4657
Jim Grosbach1355cf12011-07-26 17:10:22 +00004658/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004659/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004660bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004661 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4662 bool isMachO = MAI.hasSubsectionsViaSymbols();
4663 StringRef Name;
4664
4665 // Darwin asm has function name after .thumb_func direction
4666 // ELF doesn't
4667 if (isMachO) {
4668 const AsmToken &Tok = Parser.getTok();
4669 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4670 return Error(L, "unexpected token in .thumb_func directive");
4671 Name = Tok.getString();
4672 Parser.Lex(); // Consume the identifier token.
4673 }
4674
Kevin Enderby515d5092009-10-15 20:48:48 +00004675 if (getLexer().isNot(AsmToken::EndOfStatement))
4676 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004677 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004678
Rafael Espindola64695402011-05-16 16:17:21 +00004679 // FIXME: assuming function name will be the line following .thumb_func
4680 if (!isMachO) {
4681 Name = Parser.getTok().getString();
4682 }
4683
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004684 // Mark symbol as a thumb symbol.
4685 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4686 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004687 return false;
4688}
4689
Jim Grosbach1355cf12011-07-26 17:10:22 +00004690/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004691/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004692bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004693 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004694 if (Tok.isNot(AsmToken::Identifier))
4695 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004696 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004697 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004698 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004699 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004700 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004701 else
4702 return Error(L, "unrecognized syntax mode in .syntax directive");
4703
4704 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004705 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004706 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004707
4708 // TODO tell the MC streamer the mode
4709 // getParser().getStreamer().Emit???();
4710 return false;
4711}
4712
Jim Grosbach1355cf12011-07-26 17:10:22 +00004713/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004714/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004715bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004716 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004717 if (Tok.isNot(AsmToken::Integer))
4718 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004719 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004720 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004721 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004722 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004723 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004724 else
4725 return Error(L, "invalid operand to .code directive");
4726
4727 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004728 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004729 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004730
Evan Cheng32869202011-07-08 22:36:29 +00004731 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004732 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004733 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004734 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004735 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004736 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004737 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004738 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004739 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004740
Kevin Enderby515d5092009-10-15 20:48:48 +00004741 return false;
4742}
4743
Sean Callanan90b70972010-04-07 20:29:34 +00004744extern "C" void LLVMInitializeARMAsmLexer();
4745
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004746/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004747extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004748 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4749 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004750 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004751}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004752
Chris Lattner0692ee62010-09-06 19:11:01 +00004753#define GET_REGISTER_MATCHER
4754#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004755#include "ARMGenAsmMatcher.inc"