blob: b496705efcd8890308c1648571199a176d4a6f01 [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.
924// return ((Value << 8) | (Value & 0xff)) == Value;
925 return Value >= 0 && Value < 256;
926 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000927
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000928 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000929 // Add as immediates when possible. Null MCExpr = 0.
930 if (Expr == 0)
931 Inst.addOperand(MCOperand::CreateImm(0));
932 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000933 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
934 else
935 Inst.addOperand(MCOperand::CreateExpr(Expr));
936 }
937
Daniel Dunbar8462b302010-08-11 06:36:53 +0000938 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000939 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000940 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000941 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
942 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000943 }
944
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000945 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
946 assert(N == 1 && "Invalid number of operands!");
947 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
948 }
949
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000950 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
951 assert(N == 1 && "Invalid number of operands!");
952 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
953 }
954
955 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
956 assert(N == 1 && "Invalid number of operands!");
957 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
958 }
959
Jim Grosbach89df9962011-08-26 21:43:41 +0000960 void addITMaskOperands(MCInst &Inst, unsigned N) const {
961 assert(N == 1 && "Invalid number of operands!");
962 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
963 }
964
965 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
966 assert(N == 1 && "Invalid number of operands!");
967 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
968 }
969
Jim Grosbachd67641b2010-12-06 18:21:12 +0000970 void addCCOutOperands(MCInst &Inst, unsigned N) const {
971 assert(N == 1 && "Invalid number of operands!");
972 Inst.addOperand(MCOperand::CreateReg(getReg()));
973 }
974
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000975 void addRegOperands(MCInst &Inst, unsigned N) const {
976 assert(N == 1 && "Invalid number of operands!");
977 Inst.addOperand(MCOperand::CreateReg(getReg()));
978 }
979
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000980 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000981 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000982 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
983 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
984 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000985 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000986 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000987 }
988
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000989 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000990 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000991 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
992 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000993 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000994 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000995 }
996
Jim Grosbach580f4a92011-07-25 22:20:28 +0000997 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000998 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000999 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1000 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001001 }
1002
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001003 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001004 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001005 const SmallVectorImpl<unsigned> &RegList = getRegList();
1006 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001007 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1008 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001009 }
1010
Bill Wendling0f630752010-11-17 04:32:08 +00001011 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1012 addRegListOperands(Inst, N);
1013 }
1014
1015 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1016 addRegListOperands(Inst, N);
1017 }
1018
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001019 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1020 assert(N == 1 && "Invalid number of operands!");
1021 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1022 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1023 }
1024
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001025 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
1027 // Munge the lsb/width into a bitfield mask.
1028 unsigned lsb = Bitfield.LSB;
1029 unsigned width = Bitfield.Width;
1030 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1031 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1032 (32 - (lsb + width)));
1033 Inst.addOperand(MCOperand::CreateImm(Mask));
1034 }
1035
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001036 void addImmOperands(MCInst &Inst, unsigned N) const {
1037 assert(N == 1 && "Invalid number of operands!");
1038 addExpr(Inst, getImm());
1039 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001040
Jim Grosbach9d390362011-10-03 23:38:36 +00001041 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1042 assert(N == 1 && "Invalid number of operands!");
1043 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1044 }
1045
Jim Grosbacha77295d2011-09-08 22:07:06 +00001046 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1047 assert(N == 1 && "Invalid number of operands!");
1048 // FIXME: We really want to scale the value here, but the LDRD/STRD
1049 // instruction don't encode operands that way yet.
1050 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1051 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1052 }
1053
Jim Grosbach72f39f82011-08-24 21:22:15 +00001054 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1055 assert(N == 1 && "Invalid number of operands!");
1056 // The immediate is scaled by four in the encoding and is stored
1057 // in the MCInst as such. Lop off the low two bits here.
1058 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1059 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1060 }
1061
1062 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1063 assert(N == 1 && "Invalid number of operands!");
1064 // The immediate is scaled by four in the encoding and is stored
1065 // in the MCInst as such. Lop off the low two bits here.
1066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1068 }
1069
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001070 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
1072 addExpr(Inst, getImm());
1073 }
1074
Jim Grosbach83ab0702011-07-13 22:01:08 +00001075 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1076 assert(N == 1 && "Invalid number of operands!");
1077 addExpr(Inst, getImm());
1078 }
1079
1080 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
1082 addExpr(Inst, getImm());
1083 }
1084
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001085 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
1087 addExpr(Inst, getImm());
1088 }
1089
Jim Grosbachf4943352011-07-25 23:09:14 +00001090 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
1092 // The constant encodes as the immediate-1, and we store in the instruction
1093 // the bits as encoded, so subtract off one here.
1094 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1095 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1096 }
1097
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001098 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1099 assert(N == 1 && "Invalid number of operands!");
1100 // The constant encodes as the immediate-1, and we store in the instruction
1101 // the bits as encoded, so subtract off one here.
1102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1103 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1104 }
1105
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001106 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1107 assert(N == 1 && "Invalid number of operands!");
1108 addExpr(Inst, getImm());
1109 }
1110
Jim Grosbachffa32252011-07-19 19:13:28 +00001111 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!");
1113 addExpr(Inst, getImm());
1114 }
1115
Jim Grosbached838482011-07-26 16:24:27 +00001116 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!");
1118 addExpr(Inst, getImm());
1119 }
1120
Jim Grosbach70939ee2011-08-17 21:51:27 +00001121 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 // The constant encodes as the immediate, except for 32, which encodes as
1124 // zero.
1125 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1126 unsigned Imm = CE->getValue();
1127 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1128 }
1129
Jim Grosbachf6c05252011-07-21 17:23:04 +00001130 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1131 assert(N == 1 && "Invalid number of operands!");
1132 addExpr(Inst, getImm());
1133 }
1134
1135 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 1 && "Invalid number of operands!");
1137 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1138 // the instruction as well.
1139 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1140 int Val = CE->getValue();
1141 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1142 }
1143
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001144 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1145 assert(N == 1 && "Invalid number of operands!");
1146 addExpr(Inst, getImm());
1147 }
1148
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001149 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 addExpr(Inst, getImm());
1152 }
1153
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001154 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1155 assert(N == 1 && "Invalid number of operands!");
1156 addExpr(Inst, getImm());
1157 }
1158
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001159 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
1161 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1162 }
1163
Jim Grosbach7ce05792011-08-03 23:50:40 +00001164 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001166 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001167 }
1168
Jim Grosbach57dcb852011-10-11 17:29:55 +00001169 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1170 assert(N == 2 && "Invalid number of operands!");
1171 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1172 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1173 }
1174
Jim Grosbach7ce05792011-08-03 23:50:40 +00001175 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1176 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001177 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1178 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001179 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1180 // Special case for #-0
1181 if (Val == INT32_MIN) Val = 0;
1182 if (Val < 0) Val = -Val;
1183 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1184 } else {
1185 // For register offset, we encode the shift type and negation flag
1186 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001187 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1188 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001189 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001190 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1191 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001192 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001193 }
1194
Jim Grosbach039c2e12011-08-04 23:01:30 +00001195 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1196 assert(N == 2 && "Invalid number of operands!");
1197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 assert(CE && "non-constant AM2OffsetImm operand!");
1199 int32_t Val = CE->getValue();
1200 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1201 // Special case for #-0
1202 if (Val == INT32_MIN) Val = 0;
1203 if (Val < 0) Val = -Val;
1204 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1205 Inst.addOperand(MCOperand::CreateReg(0));
1206 Inst.addOperand(MCOperand::CreateImm(Val));
1207 }
1208
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001209 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1210 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001211 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1212 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001213 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1214 // Special case for #-0
1215 if (Val == INT32_MIN) Val = 0;
1216 if (Val < 0) Val = -Val;
1217 Val = ARM_AM::getAM3Opc(AddSub, Val);
1218 } else {
1219 // For register offset, we encode the shift type and negation flag
1220 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001221 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001222 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001223 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1224 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001225 Inst.addOperand(MCOperand::CreateImm(Val));
1226 }
1227
1228 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001230 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001231 int32_t Val =
1232 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1233 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1234 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001235 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001236 }
1237
1238 // Constant offset.
1239 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1240 int32_t Val = CE->getValue();
1241 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1242 // Special case for #-0
1243 if (Val == INT32_MIN) Val = 0;
1244 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001245 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001246 Inst.addOperand(MCOperand::CreateReg(0));
1247 Inst.addOperand(MCOperand::CreateImm(Val));
1248 }
1249
Jim Grosbach7ce05792011-08-03 23:50:40 +00001250 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1251 assert(N == 2 && "Invalid number of operands!");
1252 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001253 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001254 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1255 // Special case for #-0
1256 if (Val == INT32_MIN) Val = 0;
1257 if (Val < 0) Val = -Val;
1258 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001259 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001260 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001261 }
1262
Jim Grosbacha77295d2011-09-08 22:07:06 +00001263 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1264 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001265 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1266 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001267 Inst.addOperand(MCOperand::CreateImm(Val));
1268 }
1269
Jim Grosbachb6aed502011-09-09 18:37:27 +00001270 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1271 assert(N == 2 && "Invalid number of operands!");
1272 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001273 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1274 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001275 Inst.addOperand(MCOperand::CreateImm(Val));
1276 }
1277
Jim Grosbach7ce05792011-08-03 23:50:40 +00001278 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1279 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001280 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1281 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001282 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001283 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001284
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001285 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1286 addMemImm8OffsetOperands(Inst, N);
1287 }
1288
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001289 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001290 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001291 }
1292
1293 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1294 assert(N == 2 && "Invalid number of operands!");
1295 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001296 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001297 addExpr(Inst, getImm());
1298 Inst.addOperand(MCOperand::CreateImm(0));
1299 return;
1300 }
1301
1302 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001303 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1304 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001305 Inst.addOperand(MCOperand::CreateImm(Val));
1306 }
1307
Jim Grosbach7ce05792011-08-03 23:50:40 +00001308 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1309 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001310 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001311 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001312 addExpr(Inst, getImm());
1313 Inst.addOperand(MCOperand::CreateImm(0));
1314 return;
1315 }
1316
1317 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001318 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1319 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001320 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001321 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001322
Jim Grosbach7f739be2011-09-19 22:21:13 +00001323 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001325 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1326 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001327 }
1328
1329 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1330 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001331 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1332 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001333 }
1334
Jim Grosbach7ce05792011-08-03 23:50:40 +00001335 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1336 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001337 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1338 Memory.ShiftImm, Memory.ShiftType);
1339 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1340 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001341 Inst.addOperand(MCOperand::CreateImm(Val));
1342 }
1343
Jim Grosbachab899c12011-09-07 23:10:15 +00001344 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1345 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001346 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1347 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1348 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001349 }
1350
Jim Grosbach7ce05792011-08-03 23:50:40 +00001351 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1352 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001353 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1354 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001355 }
1356
Jim Grosbach60f91a32011-08-19 17:55:24 +00001357 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1358 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001359 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1360 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001361 Inst.addOperand(MCOperand::CreateImm(Val));
1362 }
1363
Jim Grosbach38466302011-08-19 18:55:51 +00001364 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1365 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001366 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1367 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001368 Inst.addOperand(MCOperand::CreateImm(Val));
1369 }
1370
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001371 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1372 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001373 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1374 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001375 Inst.addOperand(MCOperand::CreateImm(Val));
1376 }
1377
Jim Grosbachecd85892011-08-19 18:13:48 +00001378 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1379 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001380 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1381 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001382 Inst.addOperand(MCOperand::CreateImm(Val));
1383 }
1384
Jim Grosbach7ce05792011-08-03 23:50:40 +00001385 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1388 assert(CE && "non-constant post-idx-imm8 operand!");
1389 int Imm = CE->getValue();
1390 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001391 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001392 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1393 Inst.addOperand(MCOperand::CreateImm(Imm));
1394 }
1395
Jim Grosbach2bd01182011-10-11 21:55:36 +00001396 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1397 assert(N == 1 && "Invalid number of operands!");
1398 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1399 assert(CE && "non-constant post-idx-imm8s4 operand!");
1400 int Imm = CE->getValue();
1401 bool isAdd = Imm >= 0;
1402 if (Imm == INT32_MIN) Imm = 0;
1403 // Immediate is scaled by 4.
1404 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1405 Inst.addOperand(MCOperand::CreateImm(Imm));
1406 }
1407
Jim Grosbach7ce05792011-08-03 23:50:40 +00001408 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1409 assert(N == 2 && "Invalid number of operands!");
1410 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001411 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1412 }
1413
1414 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 2 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1417 // The sign, shift type, and shift amount are encoded in a single operand
1418 // using the AM2 encoding helpers.
1419 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1420 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1421 PostIdxReg.ShiftTy);
1422 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001423 }
1424
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001425 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1428 }
1429
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001430 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1431 assert(N == 1 && "Invalid number of operands!");
1432 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1433 }
1434
Jim Grosbach460a9052011-10-07 23:56:00 +00001435 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1436 assert(N == 1 && "Invalid number of operands!");
1437 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1438 }
1439
1440 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1441 assert(N == 1 && "Invalid number of operands!");
1442 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1443 }
1444
1445 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1446 assert(N == 1 && "Invalid number of operands!");
1447 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1448 }
1449
Jim Grosbach0e387b22011-10-17 22:26:03 +00001450 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
1452 // The immediate encodes the type of constant as well as the value.
1453 // Mask in that this is an i8 splat.
1454 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1455 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1456 }
1457
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001458 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001459
Jim Grosbach89df9962011-08-26 21:43:41 +00001460 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001461 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001462 Op->ITMask.Mask = Mask;
1463 Op->StartLoc = S;
1464 Op->EndLoc = S;
1465 return Op;
1466 }
1467
Chris Lattner3a697562010-10-28 17:20:03 +00001468 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001469 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001470 Op->CC.Val = CC;
1471 Op->StartLoc = S;
1472 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001473 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001474 }
1475
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001476 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001477 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001478 Op->Cop.Val = CopVal;
1479 Op->StartLoc = S;
1480 Op->EndLoc = S;
1481 return Op;
1482 }
1483
1484 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001485 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001486 Op->Cop.Val = CopVal;
1487 Op->StartLoc = S;
1488 Op->EndLoc = S;
1489 return Op;
1490 }
1491
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001492 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1493 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1494 Op->Cop.Val = Val;
1495 Op->StartLoc = S;
1496 Op->EndLoc = E;
1497 return Op;
1498 }
1499
Jim Grosbachd67641b2010-12-06 18:21:12 +00001500 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001501 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001502 Op->Reg.RegNum = RegNum;
1503 Op->StartLoc = S;
1504 Op->EndLoc = S;
1505 return Op;
1506 }
1507
Chris Lattner3a697562010-10-28 17:20:03 +00001508 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001509 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001510 Op->Tok.Data = Str.data();
1511 Op->Tok.Length = Str.size();
1512 Op->StartLoc = S;
1513 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001514 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001515 }
1516
Bill Wendling50d0f582010-11-18 23:43:05 +00001517 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001518 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001519 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001520 Op->StartLoc = S;
1521 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001522 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001523 }
1524
Jim Grosbache8606dc2011-07-13 17:50:29 +00001525 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1526 unsigned SrcReg,
1527 unsigned ShiftReg,
1528 unsigned ShiftImm,
1529 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001530 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001531 Op->RegShiftedReg.ShiftTy = ShTy;
1532 Op->RegShiftedReg.SrcReg = SrcReg;
1533 Op->RegShiftedReg.ShiftReg = ShiftReg;
1534 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001535 Op->StartLoc = S;
1536 Op->EndLoc = E;
1537 return Op;
1538 }
1539
Owen Anderson92a20222011-07-21 18:54:16 +00001540 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1541 unsigned SrcReg,
1542 unsigned ShiftImm,
1543 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001544 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001545 Op->RegShiftedImm.ShiftTy = ShTy;
1546 Op->RegShiftedImm.SrcReg = SrcReg;
1547 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001548 Op->StartLoc = S;
1549 Op->EndLoc = E;
1550 return Op;
1551 }
1552
Jim Grosbach580f4a92011-07-25 22:20:28 +00001553 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001554 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001555 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001556 Op->ShifterImm.isASR = isASR;
1557 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001558 Op->StartLoc = S;
1559 Op->EndLoc = E;
1560 return Op;
1561 }
1562
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001563 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001564 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001565 Op->RotImm.Imm = Imm;
1566 Op->StartLoc = S;
1567 Op->EndLoc = E;
1568 return Op;
1569 }
1570
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001571 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1572 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001573 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001574 Op->Bitfield.LSB = LSB;
1575 Op->Bitfield.Width = Width;
1576 Op->StartLoc = S;
1577 Op->EndLoc = E;
1578 return Op;
1579 }
1580
Bill Wendling7729e062010-11-09 22:44:22 +00001581 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001582 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001583 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001584 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001585
Jim Grosbachd300b942011-09-13 22:56:44 +00001586 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001587 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001588 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001589 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001590 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001591
1592 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001593 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001594 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001595 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001596 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001597 Op->StartLoc = StartLoc;
1598 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001599 return Op;
1600 }
1601
Jim Grosbach460a9052011-10-07 23:56:00 +00001602 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1603 MCContext &Ctx) {
1604 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1605 Op->VectorIndex.Val = Idx;
1606 Op->StartLoc = S;
1607 Op->EndLoc = E;
1608 return Op;
1609 }
1610
Chris Lattner3a697562010-10-28 17:20:03 +00001611 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001612 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001613 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001614 Op->StartLoc = S;
1615 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001616 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001617 }
1618
Jim Grosbach9d390362011-10-03 23:38:36 +00001619 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001620 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001621 Op->FPImm.Val = Val;
1622 Op->StartLoc = S;
1623 Op->EndLoc = S;
1624 return Op;
1625 }
1626
Jim Grosbach7ce05792011-08-03 23:50:40 +00001627 static ARMOperand *CreateMem(unsigned BaseRegNum,
1628 const MCConstantExpr *OffsetImm,
1629 unsigned OffsetRegNum,
1630 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001631 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001632 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001633 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001634 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001635 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001636 Op->Memory.BaseRegNum = BaseRegNum;
1637 Op->Memory.OffsetImm = OffsetImm;
1638 Op->Memory.OffsetRegNum = OffsetRegNum;
1639 Op->Memory.ShiftType = ShiftType;
1640 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001641 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001642 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001643 Op->StartLoc = S;
1644 Op->EndLoc = E;
1645 return Op;
1646 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001647
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001648 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1649 ARM_AM::ShiftOpc ShiftTy,
1650 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001651 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001652 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001653 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001654 Op->PostIdxReg.isAdd = isAdd;
1655 Op->PostIdxReg.ShiftTy = ShiftTy;
1656 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001657 Op->StartLoc = S;
1658 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001659 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001660 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001661
1662 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001663 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001664 Op->MBOpt.Val = Opt;
1665 Op->StartLoc = S;
1666 Op->EndLoc = S;
1667 return Op;
1668 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001669
1670 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001671 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001672 Op->IFlags.Val = IFlags;
1673 Op->StartLoc = S;
1674 Op->EndLoc = S;
1675 return Op;
1676 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001677
1678 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001679 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001680 Op->MMask.Val = MMask;
1681 Op->StartLoc = S;
1682 Op->EndLoc = S;
1683 return Op;
1684 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001685};
1686
1687} // end anonymous namespace.
1688
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001689void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001690 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001691 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001692 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1693 << ") >";
1694 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001695 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001696 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001697 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001698 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001699 OS << "<ccout " << getReg() << ">";
1700 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001701 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001702 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1703 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1704 "(tee)", "(eee)" };
1705 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1706 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1707 break;
1708 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001709 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001710 OS << "<coprocessor number: " << getCoproc() << ">";
1711 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001712 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001713 OS << "<coprocessor register: " << getCoproc() << ">";
1714 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001715 case k_CoprocOption:
1716 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1717 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001718 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001719 OS << "<mask: " << getMSRMask() << ">";
1720 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001721 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001722 getImm()->print(OS);
1723 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001724 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001725 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1726 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001727 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001728 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001729 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001730 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001731 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001732 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001733 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1734 << PostIdxReg.RegNum;
1735 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1736 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1737 << PostIdxReg.ShiftImm;
1738 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001739 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001740 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001741 OS << "<ARM_PROC::";
1742 unsigned IFlags = getProcIFlags();
1743 for (int i=2; i >= 0; --i)
1744 if (IFlags & (1 << i))
1745 OS << ARM_PROC::IFlagsToString(1 << i);
1746 OS << ">";
1747 break;
1748 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001749 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001750 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001751 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001752 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001753 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1754 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001755 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001756 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001757 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001758 << RegShiftedReg.SrcReg
1759 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1760 << ", " << RegShiftedReg.ShiftReg << ", "
1761 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001762 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001763 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001765 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001766 << RegShiftedImm.SrcReg
1767 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1768 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001769 << ">";
1770 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001771 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001772 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1773 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001774 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001775 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1776 << ", width: " << Bitfield.Width << ">";
1777 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001778 case k_RegisterList:
1779 case k_DPRRegisterList:
1780 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001781 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001782
Bill Wendling5fa22a12010-11-09 23:28:44 +00001783 const SmallVectorImpl<unsigned> &RegList = getRegList();
1784 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001785 I = RegList.begin(), E = RegList.end(); I != E; ) {
1786 OS << *I;
1787 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001788 }
1789
1790 OS << ">";
1791 break;
1792 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001793 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001794 OS << "'" << getToken() << "'";
1795 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001796 case k_VectorIndex:
1797 OS << "<vectorindex " << getVectorIndex() << ">";
1798 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001799 }
1800}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001801
1802/// @name Auto-generated Match Functions
1803/// {
1804
1805static unsigned MatchRegisterName(StringRef Name);
1806
1807/// }
1808
Bob Wilson69df7232011-02-03 21:46:10 +00001809bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1810 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001811 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001812
1813 return (RegNo == (unsigned)-1);
1814}
1815
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001816/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001817/// and if it is a register name the token is eaten and the register number is
1818/// returned. Otherwise return -1.
1819///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001820int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001821 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001822 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001823
Chris Lattnere5658fa2010-10-30 04:09:10 +00001824 // FIXME: Validate register for the current architecture; we have to do
1825 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001826 std::string upperCase = Tok.getString().str();
1827 std::string lowerCase = LowercaseString(upperCase);
1828 unsigned RegNum = MatchRegisterName(lowerCase);
1829 if (!RegNum) {
1830 RegNum = StringSwitch<unsigned>(lowerCase)
1831 .Case("r13", ARM::SP)
1832 .Case("r14", ARM::LR)
1833 .Case("r15", ARM::PC)
1834 .Case("ip", ARM::R12)
1835 .Default(0);
1836 }
1837 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001838
Chris Lattnere5658fa2010-10-30 04:09:10 +00001839 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001840
1841#if 0
1842 // Also check for an index operand. This is only legal for vector registers,
1843 // but that'll get caught OK in operand matching, so we don't need to
1844 // explicitly filter everything else out here.
1845 if (Parser.getTok().is(AsmToken::LBrac)) {
1846 SMLoc SIdx = Parser.getTok().getLoc();
1847 Parser.Lex(); // Eat left bracket token.
1848
1849 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00001850 if (getParser().ParseExpression(ImmVal))
1851 return MatchOperand_ParseFail;
1852 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1853 if (!MCE) {
1854 TokError("immediate value expected for vector index");
1855 return MatchOperand_ParseFail;
1856 }
1857
1858 SMLoc E = Parser.getTok().getLoc();
1859 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1860 Error(E, "']' expected");
1861 return MatchOperand_ParseFail;
1862 }
1863
1864 Parser.Lex(); // Eat right bracket token.
1865
1866 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1867 SIdx, E,
1868 getContext()));
1869 }
1870#endif
1871
Chris Lattnere5658fa2010-10-30 04:09:10 +00001872 return RegNum;
1873}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001874
Jim Grosbach19906722011-07-13 18:49:30 +00001875// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1876// If a recoverable error occurs, return 1. If an irrecoverable error
1877// occurs, return -1. An irrecoverable error is one where tokens have been
1878// consumed in the process of trying to parse the shifter (i.e., when it is
1879// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001880int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001881 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1882 SMLoc S = Parser.getTok().getLoc();
1883 const AsmToken &Tok = Parser.getTok();
1884 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1885
1886 std::string upperCase = Tok.getString().str();
1887 std::string lowerCase = LowercaseString(upperCase);
1888 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1889 .Case("lsl", ARM_AM::lsl)
1890 .Case("lsr", ARM_AM::lsr)
1891 .Case("asr", ARM_AM::asr)
1892 .Case("ror", ARM_AM::ror)
1893 .Case("rrx", ARM_AM::rrx)
1894 .Default(ARM_AM::no_shift);
1895
1896 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001897 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001898
Jim Grosbache8606dc2011-07-13 17:50:29 +00001899 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001900
Jim Grosbache8606dc2011-07-13 17:50:29 +00001901 // The source register for the shift has already been added to the
1902 // operand list, so we need to pop it off and combine it into the shifted
1903 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001904 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001905 if (!PrevOp->isReg())
1906 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1907 int SrcReg = PrevOp->getReg();
1908 int64_t Imm = 0;
1909 int ShiftReg = 0;
1910 if (ShiftTy == ARM_AM::rrx) {
1911 // RRX Doesn't have an explicit shift amount. The encoder expects
1912 // the shift register to be the same as the source register. Seems odd,
1913 // but OK.
1914 ShiftReg = SrcReg;
1915 } else {
1916 // Figure out if this is shifted by a constant or a register (for non-RRX).
1917 if (Parser.getTok().is(AsmToken::Hash)) {
1918 Parser.Lex(); // Eat hash.
1919 SMLoc ImmLoc = Parser.getTok().getLoc();
1920 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001921 if (getParser().ParseExpression(ShiftExpr)) {
1922 Error(ImmLoc, "invalid immediate shift value");
1923 return -1;
1924 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001925 // The expression must be evaluatable as an immediate.
1926 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001927 if (!CE) {
1928 Error(ImmLoc, "invalid immediate shift value");
1929 return -1;
1930 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001931 // Range check the immediate.
1932 // lsl, ror: 0 <= imm <= 31
1933 // lsr, asr: 0 <= imm <= 32
1934 Imm = CE->getValue();
1935 if (Imm < 0 ||
1936 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1937 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001938 Error(ImmLoc, "immediate shift value out of range");
1939 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001940 }
1941 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001942 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001943 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001944 if (ShiftReg == -1) {
1945 Error (L, "expected immediate or register in shift operand");
1946 return -1;
1947 }
1948 } else {
1949 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001950 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001951 return -1;
1952 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001953 }
1954
Owen Anderson92a20222011-07-21 18:54:16 +00001955 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1956 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001957 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001958 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001959 else
1960 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1961 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001962
Jim Grosbach19906722011-07-13 18:49:30 +00001963 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001964}
1965
1966
Bill Wendling50d0f582010-11-18 23:43:05 +00001967/// Try to parse a register name. The token must be an Identifier when called.
1968/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1969/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001970///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001971/// TODO this is likely to change to allow different register types and or to
1972/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001973bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001974tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001975 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001976 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001977 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001978 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001979
Bill Wendling50d0f582010-11-18 23:43:05 +00001980 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001981
Chris Lattnere5658fa2010-10-30 04:09:10 +00001982 const AsmToken &ExclaimTok = Parser.getTok();
1983 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001984 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1985 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001986 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00001987 return false;
1988 }
1989
1990 // Also check for an index operand. This is only legal for vector registers,
1991 // but that'll get caught OK in operand matching, so we don't need to
1992 // explicitly filter everything else out here.
1993 if (Parser.getTok().is(AsmToken::LBrac)) {
1994 SMLoc SIdx = Parser.getTok().getLoc();
1995 Parser.Lex(); // Eat left bracket token.
1996
1997 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00001998 if (getParser().ParseExpression(ImmVal))
1999 return MatchOperand_ParseFail;
2000 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2001 if (!MCE) {
2002 TokError("immediate value expected for vector index");
2003 return MatchOperand_ParseFail;
2004 }
2005
2006 SMLoc E = Parser.getTok().getLoc();
2007 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2008 Error(E, "']' expected");
2009 return MatchOperand_ParseFail;
2010 }
2011
2012 Parser.Lex(); // Eat right bracket token.
2013
2014 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2015 SIdx, E,
2016 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002017 }
2018
Bill Wendling50d0f582010-11-18 23:43:05 +00002019 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002020}
2021
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002022/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2023/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2024/// "c5", ...
2025static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002026 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2027 // but efficient.
2028 switch (Name.size()) {
2029 default: break;
2030 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002031 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002032 return -1;
2033 switch (Name[1]) {
2034 default: return -1;
2035 case '0': return 0;
2036 case '1': return 1;
2037 case '2': return 2;
2038 case '3': return 3;
2039 case '4': return 4;
2040 case '5': return 5;
2041 case '6': return 6;
2042 case '7': return 7;
2043 case '8': return 8;
2044 case '9': return 9;
2045 }
2046 break;
2047 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002048 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002049 return -1;
2050 switch (Name[2]) {
2051 default: return -1;
2052 case '0': return 10;
2053 case '1': return 11;
2054 case '2': return 12;
2055 case '3': return 13;
2056 case '4': return 14;
2057 case '5': return 15;
2058 }
2059 break;
2060 }
2061
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002062 return -1;
2063}
2064
Jim Grosbach89df9962011-08-26 21:43:41 +00002065/// parseITCondCode - Try to parse a condition code for an IT instruction.
2066ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2067parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2068 SMLoc S = Parser.getTok().getLoc();
2069 const AsmToken &Tok = Parser.getTok();
2070 if (!Tok.is(AsmToken::Identifier))
2071 return MatchOperand_NoMatch;
2072 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2073 .Case("eq", ARMCC::EQ)
2074 .Case("ne", ARMCC::NE)
2075 .Case("hs", ARMCC::HS)
2076 .Case("cs", ARMCC::HS)
2077 .Case("lo", ARMCC::LO)
2078 .Case("cc", ARMCC::LO)
2079 .Case("mi", ARMCC::MI)
2080 .Case("pl", ARMCC::PL)
2081 .Case("vs", ARMCC::VS)
2082 .Case("vc", ARMCC::VC)
2083 .Case("hi", ARMCC::HI)
2084 .Case("ls", ARMCC::LS)
2085 .Case("ge", ARMCC::GE)
2086 .Case("lt", ARMCC::LT)
2087 .Case("gt", ARMCC::GT)
2088 .Case("le", ARMCC::LE)
2089 .Case("al", ARMCC::AL)
2090 .Default(~0U);
2091 if (CC == ~0U)
2092 return MatchOperand_NoMatch;
2093 Parser.Lex(); // Eat the token.
2094
2095 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2096
2097 return MatchOperand_Success;
2098}
2099
Jim Grosbach43904292011-07-25 20:14:50 +00002100/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002101/// token must be an Identifier when called, and if it is a coprocessor
2102/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002103ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002104parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002105 SMLoc S = Parser.getTok().getLoc();
2106 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002107 if (Tok.isNot(AsmToken::Identifier))
2108 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002109
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002110 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002111 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002112 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002113
2114 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002115 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002116 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002117}
2118
Jim Grosbach43904292011-07-25 20:14:50 +00002119/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002120/// token must be an Identifier when called, and if it is a coprocessor
2121/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002122ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002123parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002124 SMLoc S = Parser.getTok().getLoc();
2125 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002126 if (Tok.isNot(AsmToken::Identifier))
2127 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002128
2129 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2130 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002131 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002132
2133 Parser.Lex(); // Eat identifier token.
2134 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002135 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002136}
2137
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002138/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2139/// coproc_option : '{' imm0_255 '}'
2140ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2141parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2142 SMLoc S = Parser.getTok().getLoc();
2143
2144 // If this isn't a '{', this isn't a coprocessor immediate operand.
2145 if (Parser.getTok().isNot(AsmToken::LCurly))
2146 return MatchOperand_NoMatch;
2147 Parser.Lex(); // Eat the '{'
2148
2149 const MCExpr *Expr;
2150 SMLoc Loc = Parser.getTok().getLoc();
2151 if (getParser().ParseExpression(Expr)) {
2152 Error(Loc, "illegal expression");
2153 return MatchOperand_ParseFail;
2154 }
2155 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2156 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2157 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2158 return MatchOperand_ParseFail;
2159 }
2160 int Val = CE->getValue();
2161
2162 // Check for and consume the closing '}'
2163 if (Parser.getTok().isNot(AsmToken::RCurly))
2164 return MatchOperand_ParseFail;
2165 SMLoc E = Parser.getTok().getLoc();
2166 Parser.Lex(); // Eat the '}'
2167
2168 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2169 return MatchOperand_Success;
2170}
2171
Jim Grosbachd0588e22011-09-14 18:08:35 +00002172// For register list parsing, we need to map from raw GPR register numbering
2173// to the enumeration values. The enumeration values aren't sorted by
2174// register number due to our using "sp", "lr" and "pc" as canonical names.
2175static unsigned getNextRegister(unsigned Reg) {
2176 // If this is a GPR, we need to do it manually, otherwise we can rely
2177 // on the sort ordering of the enumeration since the other reg-classes
2178 // are sane.
2179 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2180 return Reg + 1;
2181 switch(Reg) {
2182 default: assert(0 && "Invalid GPR number!");
2183 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2184 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2185 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2186 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2187 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2188 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2189 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2190 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2191 }
2192}
2193
2194/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002195bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002196parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002197 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002198 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002199 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002200 Parser.Lex(); // Eat '{' token.
2201 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002202
Jim Grosbachd0588e22011-09-14 18:08:35 +00002203 // Check the first register in the list to see what register class
2204 // this is a list of.
2205 int Reg = tryParseRegister();
2206 if (Reg == -1)
2207 return Error(RegLoc, "register expected");
2208
2209 MCRegisterClass *RC;
2210 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2211 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2212 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2213 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2214 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2215 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2216 else
2217 return Error(RegLoc, "invalid register in register list");
2218
2219 // The reglist instructions have at most 16 registers, so reserve
2220 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002221 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002222 // Store the first register.
2223 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002224
Jim Grosbachd0588e22011-09-14 18:08:35 +00002225 // This starts immediately after the first register token in the list,
2226 // so we can see either a comma or a minus (range separator) as a legal
2227 // next token.
2228 while (Parser.getTok().is(AsmToken::Comma) ||
2229 Parser.getTok().is(AsmToken::Minus)) {
2230 if (Parser.getTok().is(AsmToken::Minus)) {
2231 Parser.Lex(); // Eat the comma.
2232 SMLoc EndLoc = Parser.getTok().getLoc();
2233 int EndReg = tryParseRegister();
2234 if (EndReg == -1)
2235 return Error(EndLoc, "register expected");
2236 // If the register is the same as the start reg, there's nothing
2237 // more to do.
2238 if (Reg == EndReg)
2239 continue;
2240 // The register must be in the same register class as the first.
2241 if (!RC->contains(EndReg))
2242 return Error(EndLoc, "invalid register in register list");
2243 // Ranges must go from low to high.
2244 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2245 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002246
Jim Grosbachd0588e22011-09-14 18:08:35 +00002247 // Add all the registers in the range to the register list.
2248 while (Reg != EndReg) {
2249 Reg = getNextRegister(Reg);
2250 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2251 }
2252 continue;
2253 }
2254 Parser.Lex(); // Eat the comma.
2255 RegLoc = Parser.getTok().getLoc();
2256 int OldReg = Reg;
2257 Reg = tryParseRegister();
2258 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002259 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002260 // The register must be in the same register class as the first.
2261 if (!RC->contains(Reg))
2262 return Error(RegLoc, "invalid register in register list");
2263 // List must be monotonically increasing.
2264 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2265 return Error(RegLoc, "register list not in ascending order");
2266 // VFP register lists must also be contiguous.
2267 // It's OK to use the enumeration values directly here rather, as the
2268 // VFP register classes have the enum sorted properly.
2269 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2270 Reg != OldReg + 1)
2271 return Error(RegLoc, "non-contiguous register range");
2272 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002273 }
2274
Jim Grosbachd0588e22011-09-14 18:08:35 +00002275 SMLoc E = Parser.getTok().getLoc();
2276 if (Parser.getTok().isNot(AsmToken::RCurly))
2277 return Error(E, "'}' expected");
2278 Parser.Lex(); // Eat '}' token.
2279
Bill Wendling50d0f582010-11-18 23:43:05 +00002280 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2281 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002282}
2283
Jim Grosbach43904292011-07-25 20:14:50 +00002284/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002285ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002286parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002287 SMLoc S = Parser.getTok().getLoc();
2288 const AsmToken &Tok = Parser.getTok();
2289 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2290 StringRef OptStr = Tok.getString();
2291
2292 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2293 .Case("sy", ARM_MB::SY)
2294 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002295 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002296 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002297 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002298 .Case("ishst", ARM_MB::ISHST)
2299 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002300 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002301 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002302 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002303 .Case("osh", ARM_MB::OSH)
2304 .Case("oshst", ARM_MB::OSHST)
2305 .Default(~0U);
2306
2307 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002308 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002309
2310 Parser.Lex(); // Eat identifier token.
2311 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002312 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002313}
2314
Jim Grosbach43904292011-07-25 20:14:50 +00002315/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002316ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002317parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002318 SMLoc S = Parser.getTok().getLoc();
2319 const AsmToken &Tok = Parser.getTok();
2320 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2321 StringRef IFlagsStr = Tok.getString();
2322
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002323 // An iflags string of "none" is interpreted to mean that none of the AIF
2324 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002325 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002326 if (IFlagsStr != "none") {
2327 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2328 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2329 .Case("a", ARM_PROC::A)
2330 .Case("i", ARM_PROC::I)
2331 .Case("f", ARM_PROC::F)
2332 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002333
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002334 // If some specific iflag is already set, it means that some letter is
2335 // present more than once, this is not acceptable.
2336 if (Flag == ~0U || (IFlags & Flag))
2337 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002338
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002339 IFlags |= Flag;
2340 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002341 }
2342
2343 Parser.Lex(); // Eat identifier token.
2344 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2345 return MatchOperand_Success;
2346}
2347
Jim Grosbach43904292011-07-25 20:14:50 +00002348/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002349ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002350parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002351 SMLoc S = Parser.getTok().getLoc();
2352 const AsmToken &Tok = Parser.getTok();
2353 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2354 StringRef Mask = Tok.getString();
2355
James Molloyacad68d2011-09-28 14:21:38 +00002356 if (isMClass()) {
2357 // See ARMv6-M 10.1.1
2358 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2359 .Case("apsr", 0)
2360 .Case("iapsr", 1)
2361 .Case("eapsr", 2)
2362 .Case("xpsr", 3)
2363 .Case("ipsr", 5)
2364 .Case("epsr", 6)
2365 .Case("iepsr", 7)
2366 .Case("msp", 8)
2367 .Case("psp", 9)
2368 .Case("primask", 16)
2369 .Case("basepri", 17)
2370 .Case("basepri_max", 18)
2371 .Case("faultmask", 19)
2372 .Case("control", 20)
2373 .Default(~0U);
2374
2375 if (FlagsVal == ~0U)
2376 return MatchOperand_NoMatch;
2377
2378 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2379 // basepri, basepri_max and faultmask only valid for V7m.
2380 return MatchOperand_NoMatch;
2381
2382 Parser.Lex(); // Eat identifier token.
2383 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2384 return MatchOperand_Success;
2385 }
2386
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002387 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2388 size_t Start = 0, Next = Mask.find('_');
2389 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002390 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002391 if (Next != StringRef::npos)
2392 Flags = Mask.slice(Next+1, Mask.size());
2393
2394 // FlagsVal contains the complete mask:
2395 // 3-0: Mask
2396 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2397 unsigned FlagsVal = 0;
2398
2399 if (SpecReg == "apsr") {
2400 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002401 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002402 .Case("g", 0x4) // same as CPSR_s
2403 .Case("nzcvqg", 0xc) // same as CPSR_fs
2404 .Default(~0U);
2405
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002406 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002407 if (!Flags.empty())
2408 return MatchOperand_NoMatch;
2409 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002410 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002411 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002412 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002413 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2414 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002415 for (int i = 0, e = Flags.size(); i != e; ++i) {
2416 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2417 .Case("c", 1)
2418 .Case("x", 2)
2419 .Case("s", 4)
2420 .Case("f", 8)
2421 .Default(~0U);
2422
2423 // If some specific flag is already set, it means that some letter is
2424 // present more than once, this is not acceptable.
2425 if (FlagsVal == ~0U || (FlagsVal & Flag))
2426 return MatchOperand_NoMatch;
2427 FlagsVal |= Flag;
2428 }
2429 } else // No match for special register.
2430 return MatchOperand_NoMatch;
2431
2432 // Special register without flags are equivalent to "fc" flags.
2433 if (!FlagsVal)
2434 FlagsVal = 0x9;
2435
2436 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2437 if (SpecReg == "spsr")
2438 FlagsVal |= 16;
2439
2440 Parser.Lex(); // Eat identifier token.
2441 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2442 return MatchOperand_Success;
2443}
2444
Jim Grosbachf6c05252011-07-21 17:23:04 +00002445ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2446parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2447 int Low, int High) {
2448 const AsmToken &Tok = Parser.getTok();
2449 if (Tok.isNot(AsmToken::Identifier)) {
2450 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2451 return MatchOperand_ParseFail;
2452 }
2453 StringRef ShiftName = Tok.getString();
2454 std::string LowerOp = LowercaseString(Op);
2455 std::string UpperOp = UppercaseString(Op);
2456 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2457 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2458 return MatchOperand_ParseFail;
2459 }
2460 Parser.Lex(); // Eat shift type token.
2461
2462 // There must be a '#' and a shift amount.
2463 if (Parser.getTok().isNot(AsmToken::Hash)) {
2464 Error(Parser.getTok().getLoc(), "'#' expected");
2465 return MatchOperand_ParseFail;
2466 }
2467 Parser.Lex(); // Eat hash token.
2468
2469 const MCExpr *ShiftAmount;
2470 SMLoc Loc = Parser.getTok().getLoc();
2471 if (getParser().ParseExpression(ShiftAmount)) {
2472 Error(Loc, "illegal expression");
2473 return MatchOperand_ParseFail;
2474 }
2475 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2476 if (!CE) {
2477 Error(Loc, "constant expression expected");
2478 return MatchOperand_ParseFail;
2479 }
2480 int Val = CE->getValue();
2481 if (Val < Low || Val > High) {
2482 Error(Loc, "immediate value out of range");
2483 return MatchOperand_ParseFail;
2484 }
2485
2486 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2487
2488 return MatchOperand_Success;
2489}
2490
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002491ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2492parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2493 const AsmToken &Tok = Parser.getTok();
2494 SMLoc S = Tok.getLoc();
2495 if (Tok.isNot(AsmToken::Identifier)) {
2496 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2497 return MatchOperand_ParseFail;
2498 }
2499 int Val = StringSwitch<int>(Tok.getString())
2500 .Case("be", 1)
2501 .Case("le", 0)
2502 .Default(-1);
2503 Parser.Lex(); // Eat the token.
2504
2505 if (Val == -1) {
2506 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2507 return MatchOperand_ParseFail;
2508 }
2509 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2510 getContext()),
2511 S, Parser.getTok().getLoc()));
2512 return MatchOperand_Success;
2513}
2514
Jim Grosbach580f4a92011-07-25 22:20:28 +00002515/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2516/// instructions. Legal values are:
2517/// lsl #n 'n' in [0,31]
2518/// asr #n 'n' in [1,32]
2519/// n == 32 encoded as n == 0.
2520ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2521parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2522 const AsmToken &Tok = Parser.getTok();
2523 SMLoc S = Tok.getLoc();
2524 if (Tok.isNot(AsmToken::Identifier)) {
2525 Error(S, "shift operator 'asr' or 'lsl' expected");
2526 return MatchOperand_ParseFail;
2527 }
2528 StringRef ShiftName = Tok.getString();
2529 bool isASR;
2530 if (ShiftName == "lsl" || ShiftName == "LSL")
2531 isASR = false;
2532 else if (ShiftName == "asr" || ShiftName == "ASR")
2533 isASR = true;
2534 else {
2535 Error(S, "shift operator 'asr' or 'lsl' expected");
2536 return MatchOperand_ParseFail;
2537 }
2538 Parser.Lex(); // Eat the operator.
2539
2540 // A '#' and a shift amount.
2541 if (Parser.getTok().isNot(AsmToken::Hash)) {
2542 Error(Parser.getTok().getLoc(), "'#' expected");
2543 return MatchOperand_ParseFail;
2544 }
2545 Parser.Lex(); // Eat hash token.
2546
2547 const MCExpr *ShiftAmount;
2548 SMLoc E = Parser.getTok().getLoc();
2549 if (getParser().ParseExpression(ShiftAmount)) {
2550 Error(E, "malformed shift expression");
2551 return MatchOperand_ParseFail;
2552 }
2553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2554 if (!CE) {
2555 Error(E, "shift amount must be an immediate");
2556 return MatchOperand_ParseFail;
2557 }
2558
2559 int64_t Val = CE->getValue();
2560 if (isASR) {
2561 // Shift amount must be in [1,32]
2562 if (Val < 1 || Val > 32) {
2563 Error(E, "'asr' shift amount must be in range [1,32]");
2564 return MatchOperand_ParseFail;
2565 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002566 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2567 if (isThumb() && Val == 32) {
2568 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2569 return MatchOperand_ParseFail;
2570 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002571 if (Val == 32) Val = 0;
2572 } else {
2573 // Shift amount must be in [1,32]
2574 if (Val < 0 || Val > 31) {
2575 Error(E, "'lsr' shift amount must be in range [0,31]");
2576 return MatchOperand_ParseFail;
2577 }
2578 }
2579
2580 E = Parser.getTok().getLoc();
2581 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2582
2583 return MatchOperand_Success;
2584}
2585
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002586/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2587/// of instructions. Legal values are:
2588/// ror #n 'n' in {0, 8, 16, 24}
2589ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2590parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2591 const AsmToken &Tok = Parser.getTok();
2592 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002593 if (Tok.isNot(AsmToken::Identifier))
2594 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002595 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002596 if (ShiftName != "ror" && ShiftName != "ROR")
2597 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002598 Parser.Lex(); // Eat the operator.
2599
2600 // A '#' and a rotate amount.
2601 if (Parser.getTok().isNot(AsmToken::Hash)) {
2602 Error(Parser.getTok().getLoc(), "'#' expected");
2603 return MatchOperand_ParseFail;
2604 }
2605 Parser.Lex(); // Eat hash token.
2606
2607 const MCExpr *ShiftAmount;
2608 SMLoc E = Parser.getTok().getLoc();
2609 if (getParser().ParseExpression(ShiftAmount)) {
2610 Error(E, "malformed rotate expression");
2611 return MatchOperand_ParseFail;
2612 }
2613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2614 if (!CE) {
2615 Error(E, "rotate amount must be an immediate");
2616 return MatchOperand_ParseFail;
2617 }
2618
2619 int64_t Val = CE->getValue();
2620 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2621 // normally, zero is represented in asm by omitting the rotate operand
2622 // entirely.
2623 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2624 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2625 return MatchOperand_ParseFail;
2626 }
2627
2628 E = Parser.getTok().getLoc();
2629 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2630
2631 return MatchOperand_Success;
2632}
2633
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002634ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2635parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2636 SMLoc S = Parser.getTok().getLoc();
2637 // The bitfield descriptor is really two operands, the LSB and the width.
2638 if (Parser.getTok().isNot(AsmToken::Hash)) {
2639 Error(Parser.getTok().getLoc(), "'#' expected");
2640 return MatchOperand_ParseFail;
2641 }
2642 Parser.Lex(); // Eat hash token.
2643
2644 const MCExpr *LSBExpr;
2645 SMLoc E = Parser.getTok().getLoc();
2646 if (getParser().ParseExpression(LSBExpr)) {
2647 Error(E, "malformed immediate expression");
2648 return MatchOperand_ParseFail;
2649 }
2650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2651 if (!CE) {
2652 Error(E, "'lsb' operand must be an immediate");
2653 return MatchOperand_ParseFail;
2654 }
2655
2656 int64_t LSB = CE->getValue();
2657 // The LSB must be in the range [0,31]
2658 if (LSB < 0 || LSB > 31) {
2659 Error(E, "'lsb' operand must be in the range [0,31]");
2660 return MatchOperand_ParseFail;
2661 }
2662 E = Parser.getTok().getLoc();
2663
2664 // Expect another immediate operand.
2665 if (Parser.getTok().isNot(AsmToken::Comma)) {
2666 Error(Parser.getTok().getLoc(), "too few operands");
2667 return MatchOperand_ParseFail;
2668 }
2669 Parser.Lex(); // Eat hash token.
2670 if (Parser.getTok().isNot(AsmToken::Hash)) {
2671 Error(Parser.getTok().getLoc(), "'#' expected");
2672 return MatchOperand_ParseFail;
2673 }
2674 Parser.Lex(); // Eat hash token.
2675
2676 const MCExpr *WidthExpr;
2677 if (getParser().ParseExpression(WidthExpr)) {
2678 Error(E, "malformed immediate expression");
2679 return MatchOperand_ParseFail;
2680 }
2681 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2682 if (!CE) {
2683 Error(E, "'width' operand must be an immediate");
2684 return MatchOperand_ParseFail;
2685 }
2686
2687 int64_t Width = CE->getValue();
2688 // The LSB must be in the range [1,32-lsb]
2689 if (Width < 1 || Width > 32 - LSB) {
2690 Error(E, "'width' operand must be in the range [1,32-lsb]");
2691 return MatchOperand_ParseFail;
2692 }
2693 E = Parser.getTok().getLoc();
2694
2695 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2696
2697 return MatchOperand_Success;
2698}
2699
Jim Grosbach7ce05792011-08-03 23:50:40 +00002700ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2701parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2702 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002703 // postidx_reg := '+' register {, shift}
2704 // | '-' register {, shift}
2705 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002706
2707 // This method must return MatchOperand_NoMatch without consuming any tokens
2708 // in the case where there is no match, as other alternatives take other
2709 // parse methods.
2710 AsmToken Tok = Parser.getTok();
2711 SMLoc S = Tok.getLoc();
2712 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002713 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002714 int Reg = -1;
2715 if (Tok.is(AsmToken::Plus)) {
2716 Parser.Lex(); // Eat the '+' token.
2717 haveEaten = true;
2718 } else if (Tok.is(AsmToken::Minus)) {
2719 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002720 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002721 haveEaten = true;
2722 }
2723 if (Parser.getTok().is(AsmToken::Identifier))
2724 Reg = tryParseRegister();
2725 if (Reg == -1) {
2726 if (!haveEaten)
2727 return MatchOperand_NoMatch;
2728 Error(Parser.getTok().getLoc(), "register expected");
2729 return MatchOperand_ParseFail;
2730 }
2731 SMLoc E = Parser.getTok().getLoc();
2732
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002733 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2734 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002735 if (Parser.getTok().is(AsmToken::Comma)) {
2736 Parser.Lex(); // Eat the ','.
2737 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2738 return MatchOperand_ParseFail;
2739 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002740
2741 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2742 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002743
2744 return MatchOperand_Success;
2745}
2746
Jim Grosbach251bf252011-08-10 21:56:18 +00002747ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2748parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2749 // Check for a post-index addressing register operand. Specifically:
2750 // am3offset := '+' register
2751 // | '-' register
2752 // | register
2753 // | # imm
2754 // | # + imm
2755 // | # - imm
2756
2757 // This method must return MatchOperand_NoMatch without consuming any tokens
2758 // in the case where there is no match, as other alternatives take other
2759 // parse methods.
2760 AsmToken Tok = Parser.getTok();
2761 SMLoc S = Tok.getLoc();
2762
2763 // Do immediates first, as we always parse those if we have a '#'.
2764 if (Parser.getTok().is(AsmToken::Hash)) {
2765 Parser.Lex(); // Eat the '#'.
2766 // Explicitly look for a '-', as we need to encode negative zero
2767 // differently.
2768 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2769 const MCExpr *Offset;
2770 if (getParser().ParseExpression(Offset))
2771 return MatchOperand_ParseFail;
2772 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2773 if (!CE) {
2774 Error(S, "constant expression expected");
2775 return MatchOperand_ParseFail;
2776 }
2777 SMLoc E = Tok.getLoc();
2778 // Negative zero is encoded as the flag value INT32_MIN.
2779 int32_t Val = CE->getValue();
2780 if (isNegative && Val == 0)
2781 Val = INT32_MIN;
2782
2783 Operands.push_back(
2784 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2785
2786 return MatchOperand_Success;
2787 }
2788
2789
2790 bool haveEaten = false;
2791 bool isAdd = true;
2792 int Reg = -1;
2793 if (Tok.is(AsmToken::Plus)) {
2794 Parser.Lex(); // Eat the '+' token.
2795 haveEaten = true;
2796 } else if (Tok.is(AsmToken::Minus)) {
2797 Parser.Lex(); // Eat the '-' token.
2798 isAdd = false;
2799 haveEaten = true;
2800 }
2801 if (Parser.getTok().is(AsmToken::Identifier))
2802 Reg = tryParseRegister();
2803 if (Reg == -1) {
2804 if (!haveEaten)
2805 return MatchOperand_NoMatch;
2806 Error(Parser.getTok().getLoc(), "register expected");
2807 return MatchOperand_ParseFail;
2808 }
2809 SMLoc E = Parser.getTok().getLoc();
2810
2811 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2812 0, S, E));
2813
2814 return MatchOperand_Success;
2815}
2816
Jim Grosbacha77295d2011-09-08 22:07:06 +00002817/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2818/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2819/// when they refer multiple MIOperands inside a single one.
2820bool ARMAsmParser::
2821cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2822 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2823 // Rt, Rt2
2824 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2825 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2826 // Create a writeback register dummy placeholder.
2827 Inst.addOperand(MCOperand::CreateReg(0));
2828 // addr
2829 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2830 // pred
2831 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2832 return true;
2833}
2834
2835/// cvtT2StrdPre - Convert parsed operands to MCInst.
2836/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2837/// when they refer multiple MIOperands inside a single one.
2838bool ARMAsmParser::
2839cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2840 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2841 // Create a writeback register dummy placeholder.
2842 Inst.addOperand(MCOperand::CreateReg(0));
2843 // Rt, Rt2
2844 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2845 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2846 // addr
2847 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2848 // pred
2849 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2850 return true;
2851}
2852
Jim Grosbacheeec0252011-09-08 00:39:19 +00002853/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2854/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2855/// when they refer multiple MIOperands inside a single one.
2856bool ARMAsmParser::
2857cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2858 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2859 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2860
2861 // Create a writeback register dummy placeholder.
2862 Inst.addOperand(MCOperand::CreateImm(0));
2863
2864 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2865 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2866 return true;
2867}
2868
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002869/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2870/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2871/// when they refer multiple MIOperands inside a single one.
2872bool ARMAsmParser::
2873cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2874 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2875 // Create a writeback register dummy placeholder.
2876 Inst.addOperand(MCOperand::CreateImm(0));
2877 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2878 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2879 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2880 return true;
2881}
2882
Jim Grosbach1355cf12011-07-26 17:10:22 +00002883/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002884/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2885/// when they refer multiple MIOperands inside a single one.
2886bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002887cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002888 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2889 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2890
2891 // Create a writeback register dummy placeholder.
2892 Inst.addOperand(MCOperand::CreateImm(0));
2893
Jim Grosbach7ce05792011-08-03 23:50:40 +00002894 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002895 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2896 return true;
2897}
2898
Owen Anderson9ab0f252011-08-26 20:43:14 +00002899/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2900/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2901/// when they refer multiple MIOperands inside a single one.
2902bool ARMAsmParser::
2903cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2904 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2905 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2906
2907 // Create a writeback register dummy placeholder.
2908 Inst.addOperand(MCOperand::CreateImm(0));
2909
2910 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2911 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2912 return true;
2913}
2914
2915
Jim Grosbach548340c2011-08-11 19:22:40 +00002916/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2917/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2918/// when they refer multiple MIOperands inside a single one.
2919bool ARMAsmParser::
2920cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2921 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2922 // Create a writeback register dummy placeholder.
2923 Inst.addOperand(MCOperand::CreateImm(0));
2924 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2925 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2926 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2927 return true;
2928}
2929
Jim Grosbach1355cf12011-07-26 17:10:22 +00002930/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002931/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2932/// when they refer multiple MIOperands inside a single one.
2933bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002934cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002935 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2936 // Create a writeback register dummy placeholder.
2937 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002938 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2939 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2940 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002941 return true;
2942}
2943
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002944/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2945/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2946/// when they refer multiple MIOperands inside a single one.
2947bool ARMAsmParser::
2948cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2949 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2950 // Create a writeback register dummy placeholder.
2951 Inst.addOperand(MCOperand::CreateImm(0));
2952 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2953 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2954 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2955 return true;
2956}
2957
Jim Grosbach7ce05792011-08-03 23:50:40 +00002958/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2959/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2960/// when they refer multiple MIOperands inside a single one.
2961bool ARMAsmParser::
2962cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2963 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2964 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002965 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002966 // Create a writeback register dummy placeholder.
2967 Inst.addOperand(MCOperand::CreateImm(0));
2968 // addr
2969 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2970 // offset
2971 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2972 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002973 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2974 return true;
2975}
2976
Jim Grosbach7ce05792011-08-03 23:50:40 +00002977/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002978/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2979/// when they refer multiple MIOperands inside a single one.
2980bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002981cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2982 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2983 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002984 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002985 // Create a writeback register dummy placeholder.
2986 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002987 // addr
2988 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2989 // offset
2990 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2991 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002992 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2993 return true;
2994}
2995
Jim Grosbach7ce05792011-08-03 23:50:40 +00002996/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002997/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2998/// when they refer multiple MIOperands inside a single one.
2999bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003000cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3001 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003002 // Create a writeback register dummy placeholder.
3003 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003004 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003005 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003006 // addr
3007 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3008 // offset
3009 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3010 // pred
3011 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3012 return true;
3013}
3014
3015/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3016/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3017/// when they refer multiple MIOperands inside a single one.
3018bool ARMAsmParser::
3019cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3020 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3021 // Create a writeback register dummy placeholder.
3022 Inst.addOperand(MCOperand::CreateImm(0));
3023 // Rt
3024 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3025 // addr
3026 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3027 // offset
3028 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3029 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003030 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3031 return true;
3032}
3033
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003034/// cvtLdrdPre - Convert parsed operands to MCInst.
3035/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3036/// when they refer multiple MIOperands inside a single one.
3037bool ARMAsmParser::
3038cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3039 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3040 // Rt, Rt2
3041 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3042 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3043 // Create a writeback register dummy placeholder.
3044 Inst.addOperand(MCOperand::CreateImm(0));
3045 // addr
3046 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3047 // pred
3048 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3049 return true;
3050}
3051
Jim Grosbach14605d12011-08-11 20:28:23 +00003052/// cvtStrdPre - Convert parsed operands to MCInst.
3053/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3054/// when they refer multiple MIOperands inside a single one.
3055bool ARMAsmParser::
3056cvtStrdPre(MCInst &Inst, unsigned Opcode,
3057 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3058 // Create a writeback register dummy placeholder.
3059 Inst.addOperand(MCOperand::CreateImm(0));
3060 // Rt, Rt2
3061 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3062 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3063 // addr
3064 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3065 // pred
3066 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3067 return true;
3068}
3069
Jim Grosbach623a4542011-08-10 22:42:16 +00003070/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3071/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3072/// when they refer multiple MIOperands inside a single one.
3073bool ARMAsmParser::
3074cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3075 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3076 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3077 // Create a writeback register dummy placeholder.
3078 Inst.addOperand(MCOperand::CreateImm(0));
3079 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3080 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3081 return true;
3082}
3083
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003084/// cvtThumbMultiple- Convert parsed operands to MCInst.
3085/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3086/// when they refer multiple MIOperands inside a single one.
3087bool ARMAsmParser::
3088cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3089 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3090 // The second source operand must be the same register as the destination
3091 // operand.
3092 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003093 (((ARMOperand*)Operands[3])->getReg() !=
3094 ((ARMOperand*)Operands[5])->getReg()) &&
3095 (((ARMOperand*)Operands[3])->getReg() !=
3096 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003097 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003098 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003099 return false;
3100 }
3101 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3102 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3103 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003104 // If we have a three-operand form, use that, else the second source operand
3105 // is just the destination operand again.
3106 if (Operands.size() == 6)
3107 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3108 else
3109 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003110 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3111
3112 return true;
3113}
Jim Grosbach623a4542011-08-10 22:42:16 +00003114
Bill Wendlinge7176102010-11-06 22:36:58 +00003115/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003116/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003117bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003118parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003119 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003120 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003121 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003122 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003123 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003124
Sean Callanan18b83232010-01-19 21:44:56 +00003125 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003126 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003127 if (BaseRegNum == -1)
3128 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003129
Daniel Dunbar05710932011-01-18 05:34:17 +00003130 // The next token must either be a comma or a closing bracket.
3131 const AsmToken &Tok = Parser.getTok();
3132 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003133 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003134
Jim Grosbach7ce05792011-08-03 23:50:40 +00003135 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003136 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003137 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003138
Jim Grosbach7ce05792011-08-03 23:50:40 +00003139 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003140 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003141
Jim Grosbachfb12f352011-09-19 18:42:21 +00003142 // If there's a pre-indexing writeback marker, '!', just add it as a token
3143 // operand. It's rather odd, but syntactically valid.
3144 if (Parser.getTok().is(AsmToken::Exclaim)) {
3145 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3146 Parser.Lex(); // Eat the '!'.
3147 }
3148
Jim Grosbach7ce05792011-08-03 23:50:40 +00003149 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003150 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003151
Jim Grosbach7ce05792011-08-03 23:50:40 +00003152 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3153 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003154
Jim Grosbach57dcb852011-10-11 17:29:55 +00003155 // If we have a ':', it's an alignment specifier.
3156 if (Parser.getTok().is(AsmToken::Colon)) {
3157 Parser.Lex(); // Eat the ':'.
3158 E = Parser.getTok().getLoc();
3159
3160 const MCExpr *Expr;
3161 if (getParser().ParseExpression(Expr))
3162 return true;
3163
3164 // The expression has to be a constant. Memory references with relocations
3165 // don't come through here, as they use the <label> forms of the relevant
3166 // instructions.
3167 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3168 if (!CE)
3169 return Error (E, "constant expression expected");
3170
3171 unsigned Align = 0;
3172 switch (CE->getValue()) {
3173 default:
3174 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3175 case 64: Align = 8; break;
3176 case 128: Align = 16; break;
3177 case 256: Align = 32; break;
3178 }
3179
3180 // Now we should have the closing ']'
3181 E = Parser.getTok().getLoc();
3182 if (Parser.getTok().isNot(AsmToken::RBrac))
3183 return Error(E, "']' expected");
3184 Parser.Lex(); // Eat right bracket token.
3185
3186 // Don't worry about range checking the value here. That's handled by
3187 // the is*() predicates.
3188 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3189 ARM_AM::no_shift, 0, Align,
3190 false, S, E));
3191
3192 // If there's a pre-indexing writeback marker, '!', just add it as a token
3193 // operand.
3194 if (Parser.getTok().is(AsmToken::Exclaim)) {
3195 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3196 Parser.Lex(); // Eat the '!'.
3197 }
3198
3199 return false;
3200 }
3201
3202 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003203 // offset.
3204 if (Parser.getTok().is(AsmToken::Hash)) {
3205 Parser.Lex(); // Eat the '#'.
3206 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003207
Owen Anderson0da10cf2011-08-29 19:36:44 +00003208 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003209 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003210 if (getParser().ParseExpression(Offset))
3211 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003212
3213 // The expression has to be a constant. Memory references with relocations
3214 // don't come through here, as they use the <label> forms of the relevant
3215 // instructions.
3216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3217 if (!CE)
3218 return Error (E, "constant expression expected");
3219
Owen Anderson0da10cf2011-08-29 19:36:44 +00003220 // If the constant was #-0, represent it as INT32_MIN.
3221 int32_t Val = CE->getValue();
3222 if (isNegative && Val == 0)
3223 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3224
Jim Grosbach7ce05792011-08-03 23:50:40 +00003225 // Now we should have the closing ']'
3226 E = Parser.getTok().getLoc();
3227 if (Parser.getTok().isNot(AsmToken::RBrac))
3228 return Error(E, "']' expected");
3229 Parser.Lex(); // Eat right bracket token.
3230
3231 // Don't worry about range checking the value here. That's handled by
3232 // the is*() predicates.
3233 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003234 ARM_AM::no_shift, 0, 0,
3235 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003236
3237 // If there's a pre-indexing writeback marker, '!', just add it as a token
3238 // operand.
3239 if (Parser.getTok().is(AsmToken::Exclaim)) {
3240 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3241 Parser.Lex(); // Eat the '!'.
3242 }
3243
3244 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003245 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003246
3247 // The register offset is optionally preceded by a '+' or '-'
3248 bool isNegative = false;
3249 if (Parser.getTok().is(AsmToken::Minus)) {
3250 isNegative = true;
3251 Parser.Lex(); // Eat the '-'.
3252 } else if (Parser.getTok().is(AsmToken::Plus)) {
3253 // Nothing to do.
3254 Parser.Lex(); // Eat the '+'.
3255 }
3256
3257 E = Parser.getTok().getLoc();
3258 int OffsetRegNum = tryParseRegister();
3259 if (OffsetRegNum == -1)
3260 return Error(E, "register expected");
3261
3262 // If there's a shift operator, handle it.
3263 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003264 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003265 if (Parser.getTok().is(AsmToken::Comma)) {
3266 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003267 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003268 return true;
3269 }
3270
3271 // Now we should have the closing ']'
3272 E = Parser.getTok().getLoc();
3273 if (Parser.getTok().isNot(AsmToken::RBrac))
3274 return Error(E, "']' expected");
3275 Parser.Lex(); // Eat right bracket token.
3276
3277 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003278 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003279 S, E));
3280
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003281 // If there's a pre-indexing writeback marker, '!', just add it as a token
3282 // operand.
3283 if (Parser.getTok().is(AsmToken::Exclaim)) {
3284 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3285 Parser.Lex(); // Eat the '!'.
3286 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003287
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003288 return false;
3289}
3290
Jim Grosbach7ce05792011-08-03 23:50:40 +00003291/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003292/// ( lsl | lsr | asr | ror ) , # shift_amount
3293/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003294/// return true if it parses a shift otherwise it returns false.
3295bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3296 unsigned &Amount) {
3297 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003298 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003299 if (Tok.isNot(AsmToken::Identifier))
3300 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003301 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003302 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003303 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003304 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003305 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003306 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003307 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003308 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003309 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003310 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003311 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003312 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003313 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003314 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003315
Jim Grosbach7ce05792011-08-03 23:50:40 +00003316 // rrx stands alone.
3317 Amount = 0;
3318 if (St != ARM_AM::rrx) {
3319 Loc = Parser.getTok().getLoc();
3320 // A '#' and a shift amount.
3321 const AsmToken &HashTok = Parser.getTok();
3322 if (HashTok.isNot(AsmToken::Hash))
3323 return Error(HashTok.getLoc(), "'#' expected");
3324 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003325
Jim Grosbach7ce05792011-08-03 23:50:40 +00003326 const MCExpr *Expr;
3327 if (getParser().ParseExpression(Expr))
3328 return true;
3329 // Range check the immediate.
3330 // lsl, ror: 0 <= imm <= 31
3331 // lsr, asr: 0 <= imm <= 32
3332 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3333 if (!CE)
3334 return Error(Loc, "shift amount must be an immediate");
3335 int64_t Imm = CE->getValue();
3336 if (Imm < 0 ||
3337 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3338 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3339 return Error(Loc, "immediate shift value out of range");
3340 Amount = Imm;
3341 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003342
3343 return false;
3344}
3345
Jim Grosbach9d390362011-10-03 23:38:36 +00003346/// parseFPImm - A floating point immediate expression operand.
3347ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3348parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3349 SMLoc S = Parser.getTok().getLoc();
3350
3351 if (Parser.getTok().isNot(AsmToken::Hash))
3352 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003353
3354 // Disambiguate the VMOV forms that can accept an FP immediate.
3355 // vmov.f32 <sreg>, #imm
3356 // vmov.f64 <dreg>, #imm
3357 // vmov.f32 <dreg>, #imm @ vector f32x2
3358 // vmov.f32 <qreg>, #imm @ vector f32x4
3359 //
3360 // There are also the NEON VMOV instructions which expect an
3361 // integer constant. Make sure we don't try to parse an FPImm
3362 // for these:
3363 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3364 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3365 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3366 TyOp->getToken() != ".f64"))
3367 return MatchOperand_NoMatch;
3368
Jim Grosbach9d390362011-10-03 23:38:36 +00003369 Parser.Lex(); // Eat the '#'.
3370
3371 // Handle negation, as that still comes through as a separate token.
3372 bool isNegative = false;
3373 if (Parser.getTok().is(AsmToken::Minus)) {
3374 isNegative = true;
3375 Parser.Lex();
3376 }
3377 const AsmToken &Tok = Parser.getTok();
3378 if (Tok.is(AsmToken::Real)) {
3379 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3380 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3381 // If we had a '-' in front, toggle the sign bit.
3382 IntVal ^= (uint64_t)isNegative << 63;
3383 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3384 Parser.Lex(); // Eat the token.
3385 if (Val == -1) {
3386 TokError("floating point value out of range");
3387 return MatchOperand_ParseFail;
3388 }
3389 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3390 return MatchOperand_Success;
3391 }
3392 if (Tok.is(AsmToken::Integer)) {
3393 int64_t Val = Tok.getIntVal();
3394 Parser.Lex(); // Eat the token.
3395 if (Val > 255 || Val < 0) {
3396 TokError("encoded floating point value out of range");
3397 return MatchOperand_ParseFail;
3398 }
3399 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3400 return MatchOperand_Success;
3401 }
3402
3403 TokError("invalid floating point immediate");
3404 return MatchOperand_ParseFail;
3405}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003406/// Parse a arm instruction operand. For now this parses the operand regardless
3407/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003408bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003409 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003410 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003411
3412 // Check if the current operand has a custom associated parser, if so, try to
3413 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003414 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3415 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003416 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003417 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3418 // there was a match, but an error occurred, in which case, just return that
3419 // the operand parsing failed.
3420 if (ResTy == MatchOperand_ParseFail)
3421 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003422
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003423 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003424 default:
3425 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003426 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003427 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003428 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003429 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003430 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003431 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003432 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003433 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003434 else if (Res == -1) // irrecoverable error
3435 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003436 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3437 S = Parser.getTok().getLoc();
3438 Parser.Lex();
3439 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3440 return false;
3441 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003442
3443 // Fall though for the Identifier case that is not a register or a
3444 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003445 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003446 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3447 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003448 // This was not a register so parse other operands that start with an
3449 // identifier (like labels) as expressions and create them as immediates.
3450 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003451 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003452 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003453 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003454 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003455 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3456 return false;
3457 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003458 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003459 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003460 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003461 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003462 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003463 // #42 -> immediate.
3464 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003465 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003466 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003467 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003468 const MCExpr *ImmVal;
3469 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003470 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3472 if (!CE) {
3473 Error(S, "constant expression expected");
3474 return MatchOperand_ParseFail;
3475 }
3476 int32_t Val = CE->getValue();
3477 if (isNegative && Val == 0)
3478 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003479 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003480 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3481 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003482 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003483 case AsmToken::Colon: {
3484 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003485 // FIXME: Check it's an expression prefix,
3486 // e.g. (FOO - :lower16:BAR) isn't legal.
3487 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003488 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003489 return true;
3490
Evan Cheng75972122011-01-13 07:58:56 +00003491 const MCExpr *SubExprVal;
3492 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003493 return true;
3494
Evan Cheng75972122011-01-13 07:58:56 +00003495 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3496 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003497 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003498 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003499 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003500 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003501 }
3502}
3503
Jim Grosbach1355cf12011-07-26 17:10:22 +00003504// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003505// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003506bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003507 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003508
3509 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003510 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003511 Parser.Lex(); // Eat ':'
3512
3513 if (getLexer().isNot(AsmToken::Identifier)) {
3514 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3515 return true;
3516 }
3517
3518 StringRef IDVal = Parser.getTok().getIdentifier();
3519 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003520 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003521 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003522 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003523 } else {
3524 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3525 return true;
3526 }
3527 Parser.Lex();
3528
3529 if (getLexer().isNot(AsmToken::Colon)) {
3530 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3531 return true;
3532 }
3533 Parser.Lex(); // Eat the last ':'
3534 return false;
3535}
3536
Daniel Dunbar352e1482011-01-11 15:59:50 +00003537/// \brief Given a mnemonic, split out possible predication code and carry
3538/// setting letters to form a canonical mnemonic and flags.
3539//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003540// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003541// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003542StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003543 unsigned &PredicationCode,
3544 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003545 unsigned &ProcessorIMod,
3546 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003547 PredicationCode = ARMCC::AL;
3548 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003549 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003550
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003551 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003552 //
3553 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003554 if ((Mnemonic == "movs" && isThumb()) ||
3555 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3556 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3557 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3558 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3559 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3560 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3561 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003562 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003563
Jim Grosbach3f00e312011-07-11 17:09:57 +00003564 // First, split out any predication code. Ignore mnemonics we know aren't
3565 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003566 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003567 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003568 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003569 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003570 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3571 .Case("eq", ARMCC::EQ)
3572 .Case("ne", ARMCC::NE)
3573 .Case("hs", ARMCC::HS)
3574 .Case("cs", ARMCC::HS)
3575 .Case("lo", ARMCC::LO)
3576 .Case("cc", ARMCC::LO)
3577 .Case("mi", ARMCC::MI)
3578 .Case("pl", ARMCC::PL)
3579 .Case("vs", ARMCC::VS)
3580 .Case("vc", ARMCC::VC)
3581 .Case("hi", ARMCC::HI)
3582 .Case("ls", ARMCC::LS)
3583 .Case("ge", ARMCC::GE)
3584 .Case("lt", ARMCC::LT)
3585 .Case("gt", ARMCC::GT)
3586 .Case("le", ARMCC::LE)
3587 .Case("al", ARMCC::AL)
3588 .Default(~0U);
3589 if (CC != ~0U) {
3590 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3591 PredicationCode = CC;
3592 }
Bill Wendling52925b62010-10-29 23:50:21 +00003593 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003594
Daniel Dunbar352e1482011-01-11 15:59:50 +00003595 // Next, determine if we have a carry setting bit. We explicitly ignore all
3596 // the instructions we know end in 's'.
3597 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003598 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003599 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3600 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3601 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003602 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3603 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003604 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3605 CarrySetting = true;
3606 }
3607
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003608 // The "cps" instruction can have a interrupt mode operand which is glued into
3609 // the mnemonic. Check if this is the case, split it and parse the imod op
3610 if (Mnemonic.startswith("cps")) {
3611 // Split out any imod code.
3612 unsigned IMod =
3613 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3614 .Case("ie", ARM_PROC::IE)
3615 .Case("id", ARM_PROC::ID)
3616 .Default(~0U);
3617 if (IMod != ~0U) {
3618 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3619 ProcessorIMod = IMod;
3620 }
3621 }
3622
Jim Grosbach89df9962011-08-26 21:43:41 +00003623 // The "it" instruction has the condition mask on the end of the mnemonic.
3624 if (Mnemonic.startswith("it")) {
3625 ITMask = Mnemonic.slice(2, Mnemonic.size());
3626 Mnemonic = Mnemonic.slice(0, 2);
3627 }
3628
Daniel Dunbar352e1482011-01-11 15:59:50 +00003629 return Mnemonic;
3630}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003631
3632/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3633/// inclusion of carry set or predication code operands.
3634//
3635// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003636void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003637getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003638 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003639 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3640 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003641 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003642 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003643 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003644 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003645 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003646 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003647 Mnemonic == "mla" || Mnemonic == "smlal" ||
3648 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003649 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003650 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003651 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003652
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003653 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3654 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3655 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3656 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003657 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3658 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003659 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003660 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3661 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3662 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003663 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3664 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003665 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003666 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003667 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003668 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003669
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003670 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003671 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003672 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003673 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003674 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003675}
3676
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003677bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3678 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003679 // FIXME: This is all horribly hacky. We really need a better way to deal
3680 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003681
3682 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3683 // another does not. Specifically, the MOVW instruction does not. So we
3684 // special case it here and remove the defaulted (non-setting) cc_out
3685 // operand if that's the instruction we're trying to match.
3686 //
3687 // We do this as post-processing of the explicit operands rather than just
3688 // conditionally adding the cc_out in the first place because we need
3689 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003690 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003691 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3692 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3693 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3694 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003695
3696 // Register-register 'add' for thumb does not have a cc_out operand
3697 // when there are only two register operands.
3698 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3699 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3700 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3701 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3702 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003703 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003704 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3705 // have to check the immediate range here since Thumb2 has a variant
3706 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003707 if (((isThumb() && Mnemonic == "add") ||
3708 (isThumbTwo() && Mnemonic == "sub")) &&
3709 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003710 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3711 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3712 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003713 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3714 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3715 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003716 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003717 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3718 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003719 // selecting via the generic "add" mnemonic, so to know that we
3720 // should remove the cc_out operand, we have to explicitly check that
3721 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003722 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3723 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003724 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3725 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3726 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3727 // Nest conditions rather than one big 'if' statement for readability.
3728 //
3729 // If either register is a high reg, it's either one of the SP
3730 // variants (handled above) or a 32-bit encoding, so we just
3731 // check against T3.
3732 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3733 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3734 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3735 return false;
3736 // If both registers are low, we're in an IT block, and the immediate is
3737 // in range, we should use encoding T1 instead, which has a cc_out.
3738 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003739 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003740 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3741 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3742 return false;
3743
3744 // Otherwise, we use encoding T4, which does not have a cc_out
3745 // operand.
3746 return true;
3747 }
3748
Jim Grosbach64944f42011-09-14 21:00:40 +00003749 // The thumb2 multiply instruction doesn't have a CCOut register, so
3750 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3751 // use the 16-bit encoding or not.
3752 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3753 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3754 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3755 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3756 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3757 // If the registers aren't low regs, the destination reg isn't the
3758 // same as one of the source regs, or the cc_out operand is zero
3759 // outside of an IT block, we have to use the 32-bit encoding, so
3760 // remove the cc_out operand.
3761 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3762 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3763 !inITBlock() ||
3764 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3765 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3766 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3767 static_cast<ARMOperand*>(Operands[4])->getReg())))
3768 return true;
3769
3770
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003771
Jim Grosbachf69c8042011-08-24 21:42:27 +00003772 // Register-register 'add/sub' for thumb does not have a cc_out operand
3773 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3774 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3775 // right, this will result in better diagnostics (which operand is off)
3776 // anyway.
3777 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3778 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003779 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3780 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3781 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3782 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003783
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003784 return false;
3785}
3786
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003787/// Parse an arm instruction mnemonic followed by its operands.
3788bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3789 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3790 // Create the leading tokens for the mnemonic, split by '.' characters.
3791 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003792 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003793
Daniel Dunbar352e1482011-01-11 15:59:50 +00003794 // Split out the predication code and carry setting flag from the mnemonic.
3795 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003796 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003797 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003798 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003799 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003800 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003801
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003802 // In Thumb1, only the branch (B) instruction can be predicated.
3803 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3804 Parser.EatToEndOfStatement();
3805 return Error(NameLoc, "conditional execution not supported in Thumb1");
3806 }
3807
Jim Grosbachffa32252011-07-19 19:13:28 +00003808 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3809
Jim Grosbach89df9962011-08-26 21:43:41 +00003810 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3811 // is the mask as it will be for the IT encoding if the conditional
3812 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3813 // where the conditional bit0 is zero, the instruction post-processing
3814 // will adjust the mask accordingly.
3815 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003816 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3817 if (ITMask.size() > 3) {
3818 Parser.EatToEndOfStatement();
3819 return Error(Loc, "too many conditions on IT instruction");
3820 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003821 unsigned Mask = 8;
3822 for (unsigned i = ITMask.size(); i != 0; --i) {
3823 char pos = ITMask[i - 1];
3824 if (pos != 't' && pos != 'e') {
3825 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003826 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003827 }
3828 Mask >>= 1;
3829 if (ITMask[i - 1] == 't')
3830 Mask |= 8;
3831 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003832 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003833 }
3834
Jim Grosbachffa32252011-07-19 19:13:28 +00003835 // FIXME: This is all a pretty gross hack. We should automatically handle
3836 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003837
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003838 // Next, add the CCOut and ConditionCode operands, if needed.
3839 //
3840 // For mnemonics which can ever incorporate a carry setting bit or predication
3841 // code, our matching model involves us always generating CCOut and
3842 // ConditionCode operands to match the mnemonic "as written" and then we let
3843 // the matcher deal with finding the right instruction or generating an
3844 // appropriate error.
3845 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003846 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003847
Jim Grosbach33c16a22011-07-14 22:04:21 +00003848 // If we had a carry-set on an instruction that can't do that, issue an
3849 // error.
3850 if (!CanAcceptCarrySet && CarrySetting) {
3851 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003852 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003853 "' can not set flags, but 's' suffix specified");
3854 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003855 // If we had a predication code on an instruction that can't do that, issue an
3856 // error.
3857 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3858 Parser.EatToEndOfStatement();
3859 return Error(NameLoc, "instruction '" + Mnemonic +
3860 "' is not predicable, but condition code specified");
3861 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003862
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003863 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003864 if (CanAcceptCarrySet) {
3865 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003866 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003867 Loc));
3868 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003869
3870 // Add the predication code operand, if necessary.
3871 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003872 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3873 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003874 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003875 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003876 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003877
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003878 // Add the processor imod operand, if necessary.
3879 if (ProcessorIMod) {
3880 Operands.push_back(ARMOperand::CreateImm(
3881 MCConstantExpr::Create(ProcessorIMod, getContext()),
3882 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003883 }
3884
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003885 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003886 while (Next != StringRef::npos) {
3887 Start = Next;
3888 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003889 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003890
Jim Grosbach4d23e992011-08-24 22:19:48 +00003891 // For now, we're only parsing Thumb1 (for the most part), so
3892 // just ignore ".n" qualifiers. We'll use them to restrict
3893 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003894 if (ExtraToken != ".n") {
3895 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3896 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3897 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003898 }
3899
3900 // Read the remaining operands.
3901 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003902 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003903 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003904 Parser.EatToEndOfStatement();
3905 return true;
3906 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003907
3908 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003909 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003910
3911 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003912 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003913 Parser.EatToEndOfStatement();
3914 return true;
3915 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003916 }
3917 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003918
Chris Lattnercbf8a982010-09-11 16:18:25 +00003919 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00003920 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00003921 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00003922 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003923 }
Bill Wendling146018f2010-11-06 21:42:12 +00003924
Chris Lattner34e53142010-09-08 05:10:46 +00003925 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003926
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003927 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3928 // do and don't have a cc_out optional-def operand. With some spot-checks
3929 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003930 // parse and adjust accordingly before actually matching. We shouldn't ever
3931 // try to remove a cc_out operand that was explicitly set on the the
3932 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3933 // table driven matcher doesn't fit well with the ARM instruction set.
3934 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003935 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3936 Operands.erase(Operands.begin() + 1);
3937 delete Op;
3938 }
3939
Jim Grosbachcf121c32011-07-28 21:57:55 +00003940 // ARM mode 'blx' need special handling, as the register operand version
3941 // is predicable, but the label operand version is not. So, we can't rely
3942 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00003943 // a k_CondCode operand in the list. If we're trying to match the label
3944 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00003945 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3946 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3947 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3948 Operands.erase(Operands.begin() + 1);
3949 delete Op;
3950 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003951
3952 // The vector-compare-to-zero instructions have a literal token "#0" at
3953 // the end that comes to here as an immediate operand. Convert it to a
3954 // token to play nicely with the matcher.
3955 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3956 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3957 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3958 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3959 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3960 if (CE && CE->getValue() == 0) {
3961 Operands.erase(Operands.begin() + 5);
3962 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3963 delete Op;
3964 }
3965 }
Jim Grosbach68259142011-10-03 22:30:24 +00003966 // VCMP{E} does the same thing, but with a different operand count.
3967 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3968 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3969 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3970 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3971 if (CE && CE->getValue() == 0) {
3972 Operands.erase(Operands.begin() + 4);
3973 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3974 delete Op;
3975 }
3976 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003977 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3978 // end. Convert it to a token here.
3979 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3980 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3981 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3982 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3983 if (CE && CE->getValue() == 0) {
3984 Operands.erase(Operands.begin() + 5);
3985 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3986 delete Op;
3987 }
3988 }
3989
Chris Lattner98986712010-01-14 22:21:20 +00003990 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003991}
3992
Jim Grosbach189610f2011-07-26 18:25:39 +00003993// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003994
3995// return 'true' if register list contains non-low GPR registers,
3996// 'false' otherwise. If Reg is in the register list or is HiReg, set
3997// 'containsReg' to true.
3998static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3999 unsigned HiReg, bool &containsReg) {
4000 containsReg = false;
4001 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4002 unsigned OpReg = Inst.getOperand(i).getReg();
4003 if (OpReg == Reg)
4004 containsReg = true;
4005 // Anything other than a low register isn't legal here.
4006 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4007 return true;
4008 }
4009 return false;
4010}
4011
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004012// Check if the specified regisgter is in the register list of the inst,
4013// starting at the indicated operand number.
4014static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4015 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4016 unsigned OpReg = Inst.getOperand(i).getReg();
4017 if (OpReg == Reg)
4018 return true;
4019 }
4020 return false;
4021}
4022
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004023// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4024// the ARMInsts array) instead. Getting that here requires awkward
4025// API changes, though. Better way?
4026namespace llvm {
4027extern MCInstrDesc ARMInsts[];
4028}
4029static MCInstrDesc &getInstDesc(unsigned Opcode) {
4030 return ARMInsts[Opcode];
4031}
4032
Jim Grosbach189610f2011-07-26 18:25:39 +00004033// FIXME: We would really like to be able to tablegen'erate this.
4034bool ARMAsmParser::
4035validateInstruction(MCInst &Inst,
4036 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004037 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4038 SMLoc Loc = Operands[0]->getStartLoc();
4039 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004040 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4041 // being allowed in IT blocks, but not being predicable. It just always
4042 // executes.
4043 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004044 unsigned bit = 1;
4045 if (ITState.FirstCond)
4046 ITState.FirstCond = false;
4047 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004048 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004049 // The instruction must be predicable.
4050 if (!MCID.isPredicable())
4051 return Error(Loc, "instructions in IT block must be predicable");
4052 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4053 unsigned ITCond = bit ? ITState.Cond :
4054 ARMCC::getOppositeCondition(ITState.Cond);
4055 if (Cond != ITCond) {
4056 // Find the condition code Operand to get its SMLoc information.
4057 SMLoc CondLoc;
4058 for (unsigned i = 1; i < Operands.size(); ++i)
4059 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4060 CondLoc = Operands[i]->getStartLoc();
4061 return Error(CondLoc, "incorrect condition in IT block; got '" +
4062 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4063 "', but expected '" +
4064 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4065 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004066 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004067 } else if (isThumbTwo() && MCID.isPredicable() &&
4068 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004069 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4070 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004071 return Error(Loc, "predicated instructions must be in IT block");
4072
Jim Grosbach189610f2011-07-26 18:25:39 +00004073 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004074 case ARM::LDRD:
4075 case ARM::LDRD_PRE:
4076 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004077 case ARM::LDREXD: {
4078 // Rt2 must be Rt + 1.
4079 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4080 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4081 if (Rt2 != Rt + 1)
4082 return Error(Operands[3]->getStartLoc(),
4083 "destination operands must be sequential");
4084 return false;
4085 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004086 case ARM::STRD: {
4087 // Rt2 must be Rt + 1.
4088 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4089 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4090 if (Rt2 != Rt + 1)
4091 return Error(Operands[3]->getStartLoc(),
4092 "source operands must be sequential");
4093 return false;
4094 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004095 case ARM::STRD_PRE:
4096 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004097 case ARM::STREXD: {
4098 // Rt2 must be Rt + 1.
4099 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4100 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4101 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004102 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004103 "source operands must be sequential");
4104 return false;
4105 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004106 case ARM::SBFX:
4107 case ARM::UBFX: {
4108 // width must be in range [1, 32-lsb]
4109 unsigned lsb = Inst.getOperand(2).getImm();
4110 unsigned widthm1 = Inst.getOperand(3).getImm();
4111 if (widthm1 >= 32 - lsb)
4112 return Error(Operands[5]->getStartLoc(),
4113 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004114 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004115 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004116 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004117 // If we're parsing Thumb2, the .w variant is available and handles
4118 // most cases that are normally illegal for a Thumb1 LDM
4119 // instruction. We'll make the transformation in processInstruction()
4120 // if necessary.
4121 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004122 // Thumb LDM instructions are writeback iff the base register is not
4123 // in the register list.
4124 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004125 bool hasWritebackToken =
4126 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4127 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004128 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004129 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004130 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4131 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004132 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004133 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004134 return Error(Operands[2]->getStartLoc(),
4135 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004136 // If we should not have writeback, there must not be a '!'. This is
4137 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004138 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004139 return Error(Operands[3]->getStartLoc(),
4140 "writeback operator '!' not allowed when base register "
4141 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004142
4143 break;
4144 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004145 case ARM::t2LDMIA_UPD: {
4146 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4147 return Error(Operands[4]->getStartLoc(),
4148 "writeback operator '!' not allowed when base register "
4149 "in register list");
4150 break;
4151 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004152 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004153 bool listContainsBase;
4154 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4155 return Error(Operands[2]->getStartLoc(),
4156 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004157 break;
4158 }
4159 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004160 bool listContainsBase;
4161 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4162 return Error(Operands[2]->getStartLoc(),
4163 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004164 break;
4165 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004166 case ARM::tSTMIA_UPD: {
4167 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004168 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004169 return Error(Operands[4]->getStartLoc(),
4170 "registers must be in range r0-r7");
4171 break;
4172 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004173 }
4174
4175 return false;
4176}
4177
Jim Grosbachf8fce712011-08-11 17:35:48 +00004178void ARMAsmParser::
4179processInstruction(MCInst &Inst,
4180 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4181 switch (Inst.getOpcode()) {
4182 case ARM::LDMIA_UPD:
4183 // If this is a load of a single register via a 'pop', then we should use
4184 // a post-indexed LDR instruction instead, per the ARM ARM.
4185 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4186 Inst.getNumOperands() == 5) {
4187 MCInst TmpInst;
4188 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4189 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4190 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4191 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4192 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4193 TmpInst.addOperand(MCOperand::CreateImm(4));
4194 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4195 TmpInst.addOperand(Inst.getOperand(3));
4196 Inst = TmpInst;
4197 }
4198 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004199 case ARM::STMDB_UPD:
4200 // If this is a store of a single register via a 'push', then we should use
4201 // a pre-indexed STR instruction instead, per the ARM ARM.
4202 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4203 Inst.getNumOperands() == 5) {
4204 MCInst TmpInst;
4205 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4206 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4207 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4208 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4209 TmpInst.addOperand(MCOperand::CreateImm(-4));
4210 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4211 TmpInst.addOperand(Inst.getOperand(3));
4212 Inst = TmpInst;
4213 }
4214 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004215 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004216 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4217 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4218 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4219 // to encoding T1 if <Rd> is omitted."
4220 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004221 Inst.setOpcode(ARM::tADDi3);
4222 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004223 case ARM::tSUBi8:
4224 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4225 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4226 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4227 // to encoding T1 if <Rd> is omitted."
4228 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4229 Inst.setOpcode(ARM::tSUBi3);
4230 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004231 case ARM::tB:
4232 // A Thumb conditional branch outside of an IT block is a tBcc.
4233 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4234 Inst.setOpcode(ARM::tBcc);
4235 break;
4236 case ARM::t2B:
4237 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4238 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4239 Inst.setOpcode(ARM::t2Bcc);
4240 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004241 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004242 // If the conditional is AL or we're in an IT block, we really want t2B.
4243 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004244 Inst.setOpcode(ARM::t2B);
4245 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004246 case ARM::tBcc:
4247 // If the conditional is AL, we really want tB.
4248 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4249 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004250 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004251 case ARM::tLDMIA: {
4252 // If the register list contains any high registers, or if the writeback
4253 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4254 // instead if we're in Thumb2. Otherwise, this should have generated
4255 // an error in validateInstruction().
4256 unsigned Rn = Inst.getOperand(0).getReg();
4257 bool hasWritebackToken =
4258 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4259 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4260 bool listContainsBase;
4261 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4262 (!listContainsBase && !hasWritebackToken) ||
4263 (listContainsBase && hasWritebackToken)) {
4264 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4265 assert (isThumbTwo());
4266 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4267 // If we're switching to the updating version, we need to insert
4268 // the writeback tied operand.
4269 if (hasWritebackToken)
4270 Inst.insert(Inst.begin(),
4271 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4272 }
4273 break;
4274 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004275 case ARM::tSTMIA_UPD: {
4276 // If the register list contains any high registers, we need to use
4277 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4278 // should have generated an error in validateInstruction().
4279 unsigned Rn = Inst.getOperand(0).getReg();
4280 bool listContainsBase;
4281 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4282 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4283 assert (isThumbTwo());
4284 Inst.setOpcode(ARM::t2STMIA_UPD);
4285 }
4286 break;
4287 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004288 case ARM::t2MOVi: {
4289 // If we can use the 16-bit encoding and the user didn't explicitly
4290 // request the 32-bit variant, transform it here.
4291 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4292 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004293 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4294 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4295 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004296 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4297 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4298 // The operands aren't in the same order for tMOVi8...
4299 MCInst TmpInst;
4300 TmpInst.setOpcode(ARM::tMOVi8);
4301 TmpInst.addOperand(Inst.getOperand(0));
4302 TmpInst.addOperand(Inst.getOperand(4));
4303 TmpInst.addOperand(Inst.getOperand(1));
4304 TmpInst.addOperand(Inst.getOperand(2));
4305 TmpInst.addOperand(Inst.getOperand(3));
4306 Inst = TmpInst;
4307 }
4308 break;
4309 }
4310 case ARM::t2MOVr: {
4311 // If we can use the 16-bit encoding and the user didn't explicitly
4312 // request the 32-bit variant, transform it here.
4313 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4314 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4315 Inst.getOperand(2).getImm() == ARMCC::AL &&
4316 Inst.getOperand(4).getReg() == ARM::CPSR &&
4317 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4318 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4319 // The operands aren't the same for tMOV[S]r... (no cc_out)
4320 MCInst TmpInst;
4321 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4322 TmpInst.addOperand(Inst.getOperand(0));
4323 TmpInst.addOperand(Inst.getOperand(1));
4324 TmpInst.addOperand(Inst.getOperand(2));
4325 TmpInst.addOperand(Inst.getOperand(3));
4326 Inst = TmpInst;
4327 }
4328 break;
4329 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004330 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004331 case ARM::t2SXTB:
4332 case ARM::t2UXTH:
4333 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004334 // If we can use the 16-bit encoding and the user didn't explicitly
4335 // request the 32-bit variant, transform it here.
4336 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4337 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4338 Inst.getOperand(2).getImm() == 0 &&
4339 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4340 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004341 unsigned NewOpc;
4342 switch (Inst.getOpcode()) {
4343 default: llvm_unreachable("Illegal opcode!");
4344 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4345 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4346 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4347 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4348 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004349 // The operands aren't the same for thumb1 (no rotate operand).
4350 MCInst TmpInst;
4351 TmpInst.setOpcode(NewOpc);
4352 TmpInst.addOperand(Inst.getOperand(0));
4353 TmpInst.addOperand(Inst.getOperand(1));
4354 TmpInst.addOperand(Inst.getOperand(3));
4355 TmpInst.addOperand(Inst.getOperand(4));
4356 Inst = TmpInst;
4357 }
4358 break;
4359 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004360 case ARM::t2IT: {
4361 // The mask bits for all but the first condition are represented as
4362 // the low bit of the condition code value implies 't'. We currently
4363 // always have 1 implies 't', so XOR toggle the bits if the low bit
4364 // of the condition code is zero. The encoding also expects the low
4365 // bit of the condition to be encoded as bit 4 of the mask operand,
4366 // so mask that in if needed
4367 MCOperand &MO = Inst.getOperand(1);
4368 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004369 unsigned OrigMask = Mask;
4370 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004371 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004372 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4373 for (unsigned i = 3; i != TZ; --i)
4374 Mask ^= 1 << i;
4375 } else
4376 Mask |= 0x10;
4377 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004378
4379 // Set up the IT block state according to the IT instruction we just
4380 // matched.
4381 assert(!inITBlock() && "nested IT blocks?!");
4382 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4383 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4384 ITState.CurPosition = 0;
4385 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004386 break;
4387 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004388 }
4389}
4390
Jim Grosbach47a0d522011-08-16 20:45:50 +00004391unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4392 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4393 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004394 unsigned Opc = Inst.getOpcode();
4395 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004396 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4397 assert(MCID.hasOptionalDef() &&
4398 "optionally flag setting instruction missing optional def operand");
4399 assert(MCID.NumOperands == Inst.getNumOperands() &&
4400 "operand count mismatch!");
4401 // Find the optional-def operand (cc_out).
4402 unsigned OpNo;
4403 for (OpNo = 0;
4404 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4405 ++OpNo)
4406 ;
4407 // If we're parsing Thumb1, reject it completely.
4408 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4409 return Match_MnemonicFail;
4410 // If we're parsing Thumb2, which form is legal depends on whether we're
4411 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004412 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4413 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004414 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004415 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4416 inITBlock())
4417 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004418 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004419 // Some high-register supporting Thumb1 encodings only allow both registers
4420 // to be from r0-r7 when in Thumb2.
4421 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4422 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4423 isARMLowRegister(Inst.getOperand(2).getReg()))
4424 return Match_RequiresThumb2;
4425 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004426 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004427 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4428 isARMLowRegister(Inst.getOperand(1).getReg()))
4429 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004430 return Match_Success;
4431}
4432
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004433bool ARMAsmParser::
4434MatchAndEmitInstruction(SMLoc IDLoc,
4435 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4436 MCStreamer &Out) {
4437 MCInst Inst;
4438 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004439 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004440 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004441 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004442 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004443 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004444 // Context sensitive operand constraints aren't handled by the matcher,
4445 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004446 if (validateInstruction(Inst, Operands)) {
4447 // Still progress the IT block, otherwise one wrong condition causes
4448 // nasty cascading errors.
4449 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004450 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004451 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004452
Jim Grosbachf8fce712011-08-11 17:35:48 +00004453 // Some instructions need post-processing to, for example, tweak which
4454 // encoding is selected.
4455 processInstruction(Inst, Operands);
4456
Jim Grosbacha1109882011-09-02 23:22:08 +00004457 // Only move forward at the very end so that everything in validate
4458 // and process gets a consistent answer about whether we're in an IT
4459 // block.
4460 forwardITPosition();
4461
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004462 Out.EmitInstruction(Inst);
4463 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004464 case Match_MissingFeature:
4465 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4466 return true;
4467 case Match_InvalidOperand: {
4468 SMLoc ErrorLoc = IDLoc;
4469 if (ErrorInfo != ~0U) {
4470 if (ErrorInfo >= Operands.size())
4471 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004472
Chris Lattnere73d4f82010-10-28 21:41:58 +00004473 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4474 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4475 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004476
Chris Lattnere73d4f82010-10-28 21:41:58 +00004477 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004478 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004479 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004480 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004481 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004482 // The converter function will have already emited a diagnostic.
4483 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004484 case Match_RequiresNotITBlock:
4485 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004486 case Match_RequiresITBlock:
4487 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004488 case Match_RequiresV6:
4489 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4490 case Match_RequiresThumb2:
4491 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004492 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004493
Eric Christopherc223e2b2010-10-29 09:26:59 +00004494 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004495 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004496}
4497
Jim Grosbach1355cf12011-07-26 17:10:22 +00004498/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004499bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4500 StringRef IDVal = DirectiveID.getIdentifier();
4501 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004502 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004503 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004504 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004505 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004506 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004507 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004508 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004509 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004510 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004511 return true;
4512}
4513
Jim Grosbach1355cf12011-07-26 17:10:22 +00004514/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004515/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004516bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004517 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4518 for (;;) {
4519 const MCExpr *Value;
4520 if (getParser().ParseExpression(Value))
4521 return true;
4522
Chris Lattneraaec2052010-01-19 19:46:13 +00004523 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004524
4525 if (getLexer().is(AsmToken::EndOfStatement))
4526 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004527
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004528 // FIXME: Improve diagnostic.
4529 if (getLexer().isNot(AsmToken::Comma))
4530 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004531 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004532 }
4533 }
4534
Sean Callananb9a25b72010-01-19 20:27:46 +00004535 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004536 return false;
4537}
4538
Jim Grosbach1355cf12011-07-26 17:10:22 +00004539/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004540/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004541bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004542 if (getLexer().isNot(AsmToken::EndOfStatement))
4543 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004544 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004545
4546 // TODO: set thumb mode
4547 // TODO: tell the MC streamer the mode
4548 // getParser().getStreamer().Emit???();
4549 return false;
4550}
4551
Jim Grosbach1355cf12011-07-26 17:10:22 +00004552/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004553/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004554bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004555 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4556 bool isMachO = MAI.hasSubsectionsViaSymbols();
4557 StringRef Name;
4558
4559 // Darwin asm has function name after .thumb_func direction
4560 // ELF doesn't
4561 if (isMachO) {
4562 const AsmToken &Tok = Parser.getTok();
4563 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4564 return Error(L, "unexpected token in .thumb_func directive");
4565 Name = Tok.getString();
4566 Parser.Lex(); // Consume the identifier token.
4567 }
4568
Kevin Enderby515d5092009-10-15 20:48:48 +00004569 if (getLexer().isNot(AsmToken::EndOfStatement))
4570 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004571 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004572
Rafael Espindola64695402011-05-16 16:17:21 +00004573 // FIXME: assuming function name will be the line following .thumb_func
4574 if (!isMachO) {
4575 Name = Parser.getTok().getString();
4576 }
4577
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004578 // Mark symbol as a thumb symbol.
4579 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4580 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004581 return false;
4582}
4583
Jim Grosbach1355cf12011-07-26 17:10:22 +00004584/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004585/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004586bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004587 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004588 if (Tok.isNot(AsmToken::Identifier))
4589 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004590 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004591 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004592 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004593 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004594 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004595 else
4596 return Error(L, "unrecognized syntax mode in .syntax directive");
4597
4598 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004599 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004600 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004601
4602 // TODO tell the MC streamer the mode
4603 // getParser().getStreamer().Emit???();
4604 return false;
4605}
4606
Jim Grosbach1355cf12011-07-26 17:10:22 +00004607/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004608/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004609bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004610 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004611 if (Tok.isNot(AsmToken::Integer))
4612 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004613 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004614 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004615 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004616 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004617 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004618 else
4619 return Error(L, "invalid operand to .code directive");
4620
4621 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004622 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004623 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004624
Evan Cheng32869202011-07-08 22:36:29 +00004625 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004626 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004627 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004628 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004629 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004630 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004631 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004632 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004633 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004634
Kevin Enderby515d5092009-10-15 20:48:48 +00004635 return false;
4636}
4637
Sean Callanan90b70972010-04-07 20:29:34 +00004638extern "C" void LLVMInitializeARMAsmLexer();
4639
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004640/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004641extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004642 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4643 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004644 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004645}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004646
Chris Lattner0692ee62010-09-06 19:11:01 +00004647#define GET_REGISTER_MATCHER
4648#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004649#include "ARMGenAsmMatcher.inc"