blob: c887179fc33e1da266d397c20802c03576a2e920 [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Owen Anderson0c9f2502011-01-13 22:50:36 +000033#include "llvm/ADT/StringExtras.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000034#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000035#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000036
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000037using namespace llvm;
38
Chris Lattner3a697562010-10-28 17:20:03 +000039namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000040
41class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000042
Evan Cheng94b95502011-07-26 00:24:13 +000043class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000044 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000045 MCAsmParser &Parser;
46
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000047 struct {
48 ARMCC::CondCodes Cond; // Condition for IT block.
49 unsigned Mask:4; // Condition mask for instructions.
50 // Starting at first 1 (from lsb).
51 // '1' condition as indicated in IT.
52 // '0' inverse of condition (else).
53 // Count of instructions in IT block is
54 // 4 - trailingzeroes(mask)
55
56 bool FirstCond; // Explicit flag for when we're parsing the
57 // First instruction in the IT block. It's
58 // implied in the mask, so needs special
59 // handling.
60
61 unsigned CurPosition; // Current position in parsing of IT
62 // block. In range [0,3]. Initialized
63 // according to count of instructions in block.
64 // ~0U if no active IT block.
65 } ITState;
66 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000067 void forwardITPosition() {
68 if (!inITBlock()) return;
69 // Move to the next instruction in the IT block, if there is one. If not,
70 // mark the block as done.
71 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
72 if (++ITState.CurPosition == 5 - TZ)
73 ITState.CurPosition = ~0U; // Done with the IT block after this.
74 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000075
76
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
79
80 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
82
Jim Grosbach1355cf12011-07-26 17:10:22 +000083 int tryParseRegister();
84 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000085 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000086 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000087 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000088 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
89 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000090 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
91 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseDirectiveWord(unsigned Size, SMLoc L);
93 bool parseDirectiveThumb(SMLoc L);
94 bool parseDirectiveThumbFunc(SMLoc L);
95 bool parseDirectiveCode(SMLoc L);
96 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000097
Jim Grosbach1355cf12011-07-26 17:10:22 +000098 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000099 bool &CarrySetting, unsigned &ProcessorIMod,
100 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000101 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000102 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000103
Evan Chengebdeeab2011-07-08 01:53:10 +0000104 bool isThumb() const {
105 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000106 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000109 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000111 bool isThumbTwo() const {
112 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
113 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000114 bool hasV6Ops() const {
115 return STI.getFeatureBits() & ARM::HasV6Ops;
116 }
James Molloyacad68d2011-09-28 14:21:38 +0000117 bool hasV7Ops() const {
118 return STI.getFeatureBits() & ARM::HasV7Ops;
119 }
Evan Cheng32869202011-07-08 22:36:29 +0000120 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000121 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
122 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool isMClass() const {
125 return STI.getFeatureBits() & ARM::FeatureMClass;
126 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000127
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000128 /// @name Auto-generated Match Functions
129 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000130
Chris Lattner0692ee62010-09-06 19:11:01 +0000131#define GET_ASSEMBLER_HEADER
132#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134 /// }
135
Jim Grosbach89df9962011-08-26 21:43:41 +0000136 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000137 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000138 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000141 OperandMatchResultTy parseCoprocOptionOperand(
142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000149 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
150 StringRef Op, int Low, int High);
151 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
152 return parsePKHImm(O, "lsl", 0, 31);
153 }
154 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
155 return parsePKHImm(O, "asr", 1, 32);
156 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000157 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000158 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000159 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000160 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000161 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000162 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000163 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000200
201 bool validateInstruction(MCInst &Inst,
202 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000203 void processInstruction(MCInst &Inst,
204 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000205 bool shouldOmitCCOutOperand(StringRef Mnemonic,
206 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000207
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000208public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000209 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000210 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000211 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000212 Match_RequiresV6,
213 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000214 };
215
Evan Chengffc0e732011-07-09 05:47:46 +0000216 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000217 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000218 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000219
Evan Chengebdeeab2011-07-08 01:53:10 +0000220 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000221 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000222
223 // Not in an ITBlock to start with.
224 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000225 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000226
Jim Grosbach1355cf12011-07-26 17:10:22 +0000227 // Implementation of the MCTargetAsmParser interface:
228 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
229 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000230 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000231 bool ParseDirective(AsmToken DirectiveID);
232
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 unsigned checkTargetMatchPredicate(MCInst &Inst);
234
Jim Grosbach1355cf12011-07-26 17:10:22 +0000235 bool MatchAndEmitInstruction(SMLoc IDLoc,
236 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
237 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000238};
Jim Grosbach16c74252010-10-29 14:46:02 +0000239} // end anonymous namespace
240
Chris Lattner3a697562010-10-28 17:20:03 +0000241namespace {
242
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000243/// ARMOperand - Instances of this class represent a parsed ARM machine
244/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000245class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000246 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000247 k_CondCode,
248 k_CCOut,
249 k_ITCondMask,
250 k_CoprocNum,
251 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000252 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000253 k_Immediate,
254 k_FPImmediate,
255 k_MemBarrierOpt,
256 k_Memory,
257 k_PostIndexRegister,
258 k_MSRMask,
259 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000260 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000261 k_Register,
262 k_RegisterList,
263 k_DPRRegisterList,
264 k_SPRRegisterList,
265 k_ShiftedRegister,
266 k_ShiftedImmediate,
267 k_ShifterImmediate,
268 k_RotateImmediate,
269 k_BitfieldDescriptor,
270 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000271 } Kind;
272
Sean Callanan76264762010-04-02 22:27:05 +0000273 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000274 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000275
276 union {
277 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000278 ARMCC::CondCodes Val;
279 } CC;
280
281 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000282 unsigned Val;
283 } Cop;
284
285 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000286 unsigned Val;
287 } CoprocOption;
288
289 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000290 unsigned Mask:4;
291 } ITMask;
292
293 struct {
294 ARM_MB::MemBOpt Val;
295 } MBOpt;
296
297 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000298 ARM_PROC::IFlags Val;
299 } IFlags;
300
301 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000302 unsigned Val;
303 } MMask;
304
305 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000306 const char *Data;
307 unsigned Length;
308 } Tok;
309
310 struct {
311 unsigned RegNum;
312 } Reg;
313
Bill Wendling8155e5b2010-11-06 22:19:43 +0000314 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000315 unsigned Val;
316 } VectorIndex;
317
318 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000319 const MCExpr *Val;
320 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000321
Jim Grosbach9d390362011-10-03 23:38:36 +0000322 struct {
323 unsigned Val; // encoded 8-bit representation
324 } FPImm;
325
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000326 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000327 struct {
328 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000329 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
330 // was specified.
331 const MCConstantExpr *OffsetImm; // Offset immediate value
332 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
333 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000334 unsigned ShiftImm; // shift for OffsetReg.
335 unsigned Alignment; // 0 = no alignment specified
336 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000337 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000338 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000339
340 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000341 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000342 bool isAdd;
343 ARM_AM::ShiftOpc ShiftTy;
344 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000345 } PostIdxReg;
346
347 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000348 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000349 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000350 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000351 struct {
352 ARM_AM::ShiftOpc ShiftTy;
353 unsigned SrcReg;
354 unsigned ShiftReg;
355 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000356 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000357 struct {
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned SrcReg;
360 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000361 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000362 struct {
363 unsigned Imm;
364 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000365 struct {
366 unsigned LSB;
367 unsigned Width;
368 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000369 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000370
Bill Wendling146018f2010-11-06 21:42:12 +0000371 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
372public:
Sean Callanan76264762010-04-02 22:27:05 +0000373 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
374 Kind = o.Kind;
375 StartLoc = o.StartLoc;
376 EndLoc = o.EndLoc;
377 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000378 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000379 CC = o.CC;
380 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000381 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000382 ITMask = o.ITMask;
383 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000384 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000385 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000386 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000387 case k_CCOut:
388 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000389 Reg = o.Reg;
390 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000391 case k_RegisterList:
392 case k_DPRRegisterList:
393 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000394 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_CoprocNum:
397 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000398 Cop = o.Cop;
399 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000400 case k_CoprocOption:
401 CoprocOption = o.CoprocOption;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000404 Imm = o.Imm;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000407 FPImm = o.FPImm;
408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000410 MBOpt = o.MBOpt;
411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000412 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000413 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000414 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000415 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000416 PostIdxReg = o.PostIdxReg;
417 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000418 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000419 MMask = o.MMask;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000422 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000425 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000428 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000431 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000434 RotImm = o.RotImm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000437 Bitfield = o.Bitfield;
438 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000439 case k_VectorIndex:
440 VectorIndex = o.VectorIndex;
441 break;
Sean Callanan76264762010-04-02 22:27:05 +0000442 }
443 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000444
Sean Callanan76264762010-04-02 22:27:05 +0000445 /// getStartLoc - Get the location of the first token of this operand.
446 SMLoc getStartLoc() const { return StartLoc; }
447 /// getEndLoc - Get the location of the last token of this operand.
448 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000449
Daniel Dunbar8462b302010-08-11 06:36:53 +0000450 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000452 return CC.Val;
453 }
454
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000455 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000457 return Cop.Val;
458 }
459
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000460 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000462 return StringRef(Tok.Data, Tok.Length);
463 }
464
465 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000466 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000467 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000468 }
469
Bill Wendling5fa22a12010-11-09 23:28:44 +0000470 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
472 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000473 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000474 }
475
Kevin Enderbycfe07242009-10-13 22:19:02 +0000476 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000477 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000478 return Imm.Val;
479 }
480
Jim Grosbach9d390362011-10-03 23:38:36 +0000481 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000482 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000483 return FPImm.Val;
484 }
485
Jim Grosbach460a9052011-10-07 23:56:00 +0000486 unsigned getVectorIndex() const {
487 assert(Kind == k_VectorIndex && "Invalid access!");
488 return VectorIndex.Val;
489 }
490
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000491 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000492 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000493 return MBOpt.Val;
494 }
495
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000496 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000497 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000498 return IFlags.Val;
499 }
500
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000501 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000502 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000503 return MMask.Val;
504 }
505
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 bool isCoprocNum() const { return Kind == k_CoprocNum; }
507 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000508 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000509 bool isCondCode() const { return Kind == k_CondCode; }
510 bool isCCOut() const { return Kind == k_CCOut; }
511 bool isITMask() const { return Kind == k_ITCondMask; }
512 bool isITCondCode() const { return Kind == k_CondCode; }
513 bool isImm() const { return Kind == k_Immediate; }
514 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000515 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000516 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000517 return false;
518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
519 if (!CE) return false;
520 int64_t Value = CE->getValue();
521 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
522 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000523 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000525 return false;
526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
527 if (!CE) return false;
528 int64_t Value = CE->getValue();
529 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
530 }
531 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000533 return false;
534 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
535 if (!CE) return false;
536 int64_t Value = CE->getValue();
537 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
538 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000539 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000540 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000541 return false;
542 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
543 if (!CE) return false;
544 int64_t Value = CE->getValue();
545 return Value >= 0 && Value < 256;
546 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000547 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000548 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000549 return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int64_t Value = CE->getValue();
553 return Value >= 0 && Value < 8;
554 }
555 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000556 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000557 return false;
558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
559 if (!CE) return false;
560 int64_t Value = CE->getValue();
561 return Value >= 0 && Value < 16;
562 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000563 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000564 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000565 return false;
566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return Value >= 0 && Value < 32;
570 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000571 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000572 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000573 return false;
574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
575 if (!CE) return false;
576 int64_t Value = CE->getValue();
577 return Value > 0 && Value < 17;
578 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000579 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000580 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000581 return false;
582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
583 if (!CE) return false;
584 int64_t Value = CE->getValue();
585 return Value > 0 && Value < 33;
586 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000587 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000588 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000589 return false;
590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
591 if (!CE) return false;
592 int64_t Value = CE->getValue();
593 return Value >= 0 && Value < 65536;
594 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000595 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000596 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000597 return false;
598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 // If it's not a constant expression, it'll generate a fixup and be
600 // handled later.
601 if (!CE) return true;
602 int64_t Value = CE->getValue();
603 return Value >= 0 && Value < 65536;
604 }
Jim Grosbached838482011-07-26 16:24:27 +0000605 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value <= 0xffffff;
612 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000613 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value > 0 && Value < 33;
620 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000621 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value >= 0 && Value < 32;
628 }
629 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000630 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000631 return false;
632 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
633 if (!CE) return false;
634 int64_t Value = CE->getValue();
635 return Value > 0 && Value <= 32;
636 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000637 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000638 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000639 return false;
640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
641 if (!CE) return false;
642 int64_t Value = CE->getValue();
643 return ARM_AM::getSOImmVal(Value) != -1;
644 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000645 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000646 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000647 return false;
648 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
649 if (!CE) return false;
650 int64_t Value = CE->getValue();
651 return ARM_AM::getT2SOImmVal(Value) != -1;
652 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000653 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000654 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000655 return false;
656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Value = CE->getValue();
659 return Value == 1 || Value == 0;
660 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000661 bool isReg() const { return Kind == k_Register; }
662 bool isRegList() const { return Kind == k_RegisterList; }
663 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
664 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
665 bool isToken() const { return Kind == k_Token; }
666 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
667 bool isMemory() const { return Kind == k_Memory; }
668 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
669 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
670 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
671 bool isRotImm() const { return Kind == k_RotateImmediate; }
672 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
673 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000674 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000675 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000676 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000677 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000678 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000679 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000680 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000681 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
682 (alignOK || Memory.Alignment == 0);
683 }
684 bool isAlignedMemory() const {
685 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000686 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000687 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000688 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000689 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000690 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000691 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000692 if (!Memory.OffsetImm) return true;
693 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000694 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000695 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000696 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000697 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000698 return false;
699 // Immediate offset in range [-4095, 4095].
700 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
701 if (!CE) return false;
702 int64_t Val = CE->getValue();
703 return Val > -4096 && Val < 4096;
704 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000705 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000706 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000707 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000708 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000709 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000710 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000711 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000712 if (!Memory.OffsetImm) return true;
713 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000714 return Val > -256 && Val < 256;
715 }
716 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000717 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000718 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000720 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
721 // Immediate offset in range [-255, 255].
722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
723 if (!CE) return false;
724 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000725 // Special case, #-0 is INT32_MIN.
726 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000727 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000728 bool isAddrMode5() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000729 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000730 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000731 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000732 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000733 if (!Memory.OffsetImm) return true;
734 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000735 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
736 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000737 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000738 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000739 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000740 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000741 return false;
742 return true;
743 }
744 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000745 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000746 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
747 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000748 return false;
749 return true;
750 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000751 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000752 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000753 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000754 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000755 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000756 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000757 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
758 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000759 return false;
760 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000761 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000762 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000763 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000764 return false;
765 return true;
766 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000767 bool isMemThumbRR() const {
768 // Thumb reg+reg addressing is simple. Just two registers, a base and
769 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000770 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000771 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000772 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000773 return isARMLowRegister(Memory.BaseRegNum) &&
774 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000775 }
776 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000777 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000778 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000779 return false;
780 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000781 if (!Memory.OffsetImm) return true;
782 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000783 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
784 }
Jim Grosbach38466302011-08-19 18:55:51 +0000785 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000787 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000788 return false;
789 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000790 if (!Memory.OffsetImm) return true;
791 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000792 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
793 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000794 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000795 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000796 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000797 return false;
798 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000799 if (!Memory.OffsetImm) return true;
800 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000801 return Val >= 0 && Val <= 31;
802 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000803 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || Memory.OffsetRegNum != 0 ||
805 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000806 return false;
807 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (!Memory.OffsetImm) return true;
809 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000810 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000811 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000812 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000813 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000814 return false;
815 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000816 if (!Memory.OffsetImm) return true;
817 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000818 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
819 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000820 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000821 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000822 return false;
823 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (!Memory.OffsetImm) return true;
825 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000826 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
827 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000828 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000829 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 return false;
831 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000832 if (!Memory.OffsetImm) return true;
833 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000834 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000835 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000836 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000837 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000838 return false;
839 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000840 if (!Memory.OffsetImm) return true;
841 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000842 return Val >= 0 && Val < 256;
843 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000844 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000846 return false;
847 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000848 if (!Memory.OffsetImm) return true;
849 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000850 return Val > -256 && Val < 0;
851 }
852 bool isMemUImm12Offset() const {
853 // If we have an immediate that's not a constant, treat it as a label
854 // reference needing a fixup. If it is a constant, it's something else
855 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000856 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000857 return true;
858
Jim Grosbach57dcb852011-10-11 17:29:55 +0000859 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000860 return false;
861 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000862 if (!Memory.OffsetImm) return true;
863 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000864 return (Val >= 0 && Val < 4096);
865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000867 // If we have an immediate that's not a constant, treat it as a label
868 // reference needing a fixup. If it is a constant, it's something else
869 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000870 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000871 return true;
872
Jim Grosbach57dcb852011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000874 return false;
875 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000876 if (!Memory.OffsetImm) return true;
877 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000878 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000879 }
880 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000881 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 return false;
883 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
884 if (!CE) return false;
885 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000886 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000887 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000888 bool isPostIdxImm8s4() const {
889 if (Kind != k_Immediate)
890 return false;
891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
892 if (!CE) return false;
893 int64_t Val = CE->getValue();
894 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
895 (Val == INT32_MIN);
896 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000897
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000898 bool isMSRMask() const { return Kind == k_MSRMask; }
899 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000900
Jim Grosbach0e387b22011-10-17 22:26:03 +0000901 // NEON operands.
Jim Grosbach460a9052011-10-07 23:56:00 +0000902 bool isVectorIndex8() const {
903 if (Kind != k_VectorIndex) return false;
904 return VectorIndex.Val < 8;
905 }
906 bool isVectorIndex16() const {
907 if (Kind != k_VectorIndex) return false;
908 return VectorIndex.Val < 4;
909 }
910 bool isVectorIndex32() const {
911 if (Kind != k_VectorIndex) return false;
912 return VectorIndex.Val < 2;
913 }
914
Jim Grosbach0e387b22011-10-17 22:26:03 +0000915 bool isNEONi8splat() const {
916 if (Kind != k_Immediate)
917 return false;
918 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
919 // Must be a constant.
920 if (!CE) return false;
921 int64_t Value = CE->getValue();
922 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
923 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000924 return Value >= 0 && Value < 256;
925 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000926
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000927 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000928 // Add as immediates when possible. Null MCExpr = 0.
929 if (Expr == 0)
930 Inst.addOperand(MCOperand::CreateImm(0));
931 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000932 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
933 else
934 Inst.addOperand(MCOperand::CreateExpr(Expr));
935 }
936
Daniel Dunbar8462b302010-08-11 06:36:53 +0000937 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000938 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000939 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000940 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
941 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000942 }
943
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000944 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
945 assert(N == 1 && "Invalid number of operands!");
946 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
947 }
948
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000949 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
950 assert(N == 1 && "Invalid number of operands!");
951 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
952 }
953
954 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
955 assert(N == 1 && "Invalid number of operands!");
956 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
957 }
958
Jim Grosbach89df9962011-08-26 21:43:41 +0000959 void addITMaskOperands(MCInst &Inst, unsigned N) const {
960 assert(N == 1 && "Invalid number of operands!");
961 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
962 }
963
964 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
965 assert(N == 1 && "Invalid number of operands!");
966 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
967 }
968
Jim Grosbachd67641b2010-12-06 18:21:12 +0000969 void addCCOutOperands(MCInst &Inst, unsigned N) const {
970 assert(N == 1 && "Invalid number of operands!");
971 Inst.addOperand(MCOperand::CreateReg(getReg()));
972 }
973
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000974 void addRegOperands(MCInst &Inst, unsigned N) const {
975 assert(N == 1 && "Invalid number of operands!");
976 Inst.addOperand(MCOperand::CreateReg(getReg()));
977 }
978
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000979 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000980 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000981 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
982 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
983 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000984 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000985 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000986 }
987
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000988 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000989 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000990 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
991 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000992 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000993 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000994 }
995
Jim Grosbach580f4a92011-07-25 22:20:28 +0000996 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000997 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000998 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
999 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001000 }
1001
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001002 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001003 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001004 const SmallVectorImpl<unsigned> &RegList = getRegList();
1005 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001006 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1007 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001008 }
1009
Bill Wendling0f630752010-11-17 04:32:08 +00001010 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1011 addRegListOperands(Inst, N);
1012 }
1013
1014 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1015 addRegListOperands(Inst, N);
1016 }
1017
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001018 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1019 assert(N == 1 && "Invalid number of operands!");
1020 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1021 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1022 }
1023
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001024 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
1026 // Munge the lsb/width into a bitfield mask.
1027 unsigned lsb = Bitfield.LSB;
1028 unsigned width = Bitfield.Width;
1029 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1030 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1031 (32 - (lsb + width)));
1032 Inst.addOperand(MCOperand::CreateImm(Mask));
1033 }
1034
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001035 void addImmOperands(MCInst &Inst, unsigned N) const {
1036 assert(N == 1 && "Invalid number of operands!");
1037 addExpr(Inst, getImm());
1038 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001039
Jim Grosbach9d390362011-10-03 23:38:36 +00001040 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1041 assert(N == 1 && "Invalid number of operands!");
1042 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1043 }
1044
Jim Grosbacha77295d2011-09-08 22:07:06 +00001045 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1046 assert(N == 1 && "Invalid number of operands!");
1047 // FIXME: We really want to scale the value here, but the LDRD/STRD
1048 // instruction don't encode operands that way yet.
1049 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1050 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1051 }
1052
Jim Grosbach72f39f82011-08-24 21:22:15 +00001053 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1054 assert(N == 1 && "Invalid number of operands!");
1055 // The immediate is scaled by four in the encoding and is stored
1056 // in the MCInst as such. Lop off the low two bits here.
1057 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1058 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1059 }
1060
1061 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1062 assert(N == 1 && "Invalid number of operands!");
1063 // The immediate is scaled by four in the encoding and is stored
1064 // in the MCInst as such. Lop off the low two bits here.
1065 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1066 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1067 }
1068
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001069 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1070 assert(N == 1 && "Invalid number of operands!");
1071 addExpr(Inst, getImm());
1072 }
1073
Jim Grosbach83ab0702011-07-13 22:01:08 +00001074 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1075 assert(N == 1 && "Invalid number of operands!");
1076 addExpr(Inst, getImm());
1077 }
1078
1079 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1080 assert(N == 1 && "Invalid number of operands!");
1081 addExpr(Inst, getImm());
1082 }
1083
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001084 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1085 assert(N == 1 && "Invalid number of operands!");
1086 addExpr(Inst, getImm());
1087 }
1088
Jim Grosbachf4943352011-07-25 23:09:14 +00001089 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1090 assert(N == 1 && "Invalid number of operands!");
1091 // The constant encodes as the immediate-1, and we store in the instruction
1092 // the bits as encoded, so subtract off one here.
1093 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1094 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1095 }
1096
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001097 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 // The constant encodes as the immediate-1, and we store in the instruction
1100 // the bits as encoded, so subtract off one here.
1101 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1102 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1103 }
1104
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001105 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1106 assert(N == 1 && "Invalid number of operands!");
1107 addExpr(Inst, getImm());
1108 }
1109
Jim Grosbachffa32252011-07-19 19:13:28 +00001110 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1111 assert(N == 1 && "Invalid number of operands!");
1112 addExpr(Inst, getImm());
1113 }
1114
Jim Grosbached838482011-07-26 16:24:27 +00001115 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1116 assert(N == 1 && "Invalid number of operands!");
1117 addExpr(Inst, getImm());
1118 }
1119
Jim Grosbach70939ee2011-08-17 21:51:27 +00001120 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1121 assert(N == 1 && "Invalid number of operands!");
1122 // The constant encodes as the immediate, except for 32, which encodes as
1123 // zero.
1124 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1125 unsigned Imm = CE->getValue();
1126 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1127 }
1128
Jim Grosbachf6c05252011-07-21 17:23:04 +00001129 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1130 assert(N == 1 && "Invalid number of operands!");
1131 addExpr(Inst, getImm());
1132 }
1133
1134 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
1136 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1137 // the instruction as well.
1138 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1139 int Val = CE->getValue();
1140 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1141 }
1142
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001143 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
1145 addExpr(Inst, getImm());
1146 }
1147
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001148 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!");
1150 addExpr(Inst, getImm());
1151 }
1152
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001153 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
1155 addExpr(Inst, getImm());
1156 }
1157
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001158 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1161 }
1162
Jim Grosbach7ce05792011-08-03 23:50:40 +00001163 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1164 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001165 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001166 }
1167
Jim Grosbach57dcb852011-10-11 17:29:55 +00001168 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1169 assert(N == 2 && "Invalid number of operands!");
1170 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1171 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1172 }
1173
Jim Grosbach7ce05792011-08-03 23:50:40 +00001174 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1175 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001176 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1177 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001178 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1179 // Special case for #-0
1180 if (Val == INT32_MIN) Val = 0;
1181 if (Val < 0) Val = -Val;
1182 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1183 } else {
1184 // For register offset, we encode the shift type and negation flag
1185 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001186 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1187 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001188 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001189 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1190 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001191 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001192 }
1193
Jim Grosbach039c2e12011-08-04 23:01:30 +00001194 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 2 && "Invalid number of operands!");
1196 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1197 assert(CE && "non-constant AM2OffsetImm operand!");
1198 int32_t Val = CE->getValue();
1199 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1200 // Special case for #-0
1201 if (Val == INT32_MIN) Val = 0;
1202 if (Val < 0) Val = -Val;
1203 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1204 Inst.addOperand(MCOperand::CreateReg(0));
1205 Inst.addOperand(MCOperand::CreateImm(Val));
1206 }
1207
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001208 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1209 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001210 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1211 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001212 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1213 // Special case for #-0
1214 if (Val == INT32_MIN) Val = 0;
1215 if (Val < 0) Val = -Val;
1216 Val = ARM_AM::getAM3Opc(AddSub, Val);
1217 } else {
1218 // For register offset, we encode the shift type and negation flag
1219 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001220 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001221 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001222 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1223 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001224 Inst.addOperand(MCOperand::CreateImm(Val));
1225 }
1226
1227 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1228 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001229 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001230 int32_t Val =
1231 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1232 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1233 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001234 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001235 }
1236
1237 // Constant offset.
1238 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1239 int32_t Val = CE->getValue();
1240 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1241 // Special case for #-0
1242 if (Val == INT32_MIN) Val = 0;
1243 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001244 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001245 Inst.addOperand(MCOperand::CreateReg(0));
1246 Inst.addOperand(MCOperand::CreateImm(Val));
1247 }
1248
Jim Grosbach7ce05792011-08-03 23:50:40 +00001249 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1250 assert(N == 2 && "Invalid number of operands!");
1251 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001252 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001253 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1254 // Special case for #-0
1255 if (Val == INT32_MIN) Val = 0;
1256 if (Val < 0) Val = -Val;
1257 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001258 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001259 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001260 }
1261
Jim Grosbacha77295d2011-09-08 22:07:06 +00001262 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1263 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001264 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1265 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001266 Inst.addOperand(MCOperand::CreateImm(Val));
1267 }
1268
Jim Grosbachb6aed502011-09-09 18:37:27 +00001269 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 2 && "Invalid number of operands!");
1271 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001272 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1273 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001274 Inst.addOperand(MCOperand::CreateImm(Val));
1275 }
1276
Jim Grosbach7ce05792011-08-03 23:50:40 +00001277 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1278 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001279 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1280 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001281 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001282 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001283
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001284 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1285 addMemImm8OffsetOperands(Inst, N);
1286 }
1287
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001288 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001289 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001290 }
1291
1292 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1293 assert(N == 2 && "Invalid number of operands!");
1294 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001295 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001296 addExpr(Inst, getImm());
1297 Inst.addOperand(MCOperand::CreateImm(0));
1298 return;
1299 }
1300
1301 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001302 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1303 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001304 Inst.addOperand(MCOperand::CreateImm(Val));
1305 }
1306
Jim Grosbach7ce05792011-08-03 23:50:40 +00001307 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1308 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001309 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001310 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001311 addExpr(Inst, getImm());
1312 Inst.addOperand(MCOperand::CreateImm(0));
1313 return;
1314 }
1315
1316 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001317 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1318 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001319 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001320 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001321
Jim Grosbach7f739be2011-09-19 22:21:13 +00001322 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1323 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001324 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1325 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001326 }
1327
1328 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001330 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1331 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001332 }
1333
Jim Grosbach7ce05792011-08-03 23:50:40 +00001334 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1335 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001336 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1337 Memory.ShiftImm, Memory.ShiftType);
1338 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1339 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001340 Inst.addOperand(MCOperand::CreateImm(Val));
1341 }
1342
Jim Grosbachab899c12011-09-07 23:10:15 +00001343 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1344 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001345 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1346 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1347 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001348 }
1349
Jim Grosbach7ce05792011-08-03 23:50:40 +00001350 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1351 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001352 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1353 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001354 }
1355
Jim Grosbach60f91a32011-08-19 17:55:24 +00001356 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1357 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001358 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1359 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001360 Inst.addOperand(MCOperand::CreateImm(Val));
1361 }
1362
Jim Grosbach38466302011-08-19 18:55:51 +00001363 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1364 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001365 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1366 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001367 Inst.addOperand(MCOperand::CreateImm(Val));
1368 }
1369
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001370 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001372 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1373 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001374 Inst.addOperand(MCOperand::CreateImm(Val));
1375 }
1376
Jim Grosbachecd85892011-08-19 18:13:48 +00001377 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001379 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1380 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001381 Inst.addOperand(MCOperand::CreateImm(Val));
1382 }
1383
Jim Grosbach7ce05792011-08-03 23:50:40 +00001384 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1385 assert(N == 1 && "Invalid number of operands!");
1386 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1387 assert(CE && "non-constant post-idx-imm8 operand!");
1388 int Imm = CE->getValue();
1389 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001390 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001391 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1392 Inst.addOperand(MCOperand::CreateImm(Imm));
1393 }
1394
Jim Grosbach2bd01182011-10-11 21:55:36 +00001395 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1396 assert(N == 1 && "Invalid number of operands!");
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 assert(CE && "non-constant post-idx-imm8s4 operand!");
1399 int Imm = CE->getValue();
1400 bool isAdd = Imm >= 0;
1401 if (Imm == INT32_MIN) Imm = 0;
1402 // Immediate is scaled by 4.
1403 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1404 Inst.addOperand(MCOperand::CreateImm(Imm));
1405 }
1406
Jim Grosbach7ce05792011-08-03 23:50:40 +00001407 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1408 assert(N == 2 && "Invalid number of operands!");
1409 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001410 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1411 }
1412
1413 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1414 assert(N == 2 && "Invalid number of operands!");
1415 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1416 // The sign, shift type, and shift amount are encoded in a single operand
1417 // using the AM2 encoding helpers.
1418 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1419 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1420 PostIdxReg.ShiftTy);
1421 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001422 }
1423
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001424 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1427 }
1428
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001429 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1432 }
1433
Jim Grosbach460a9052011-10-07 23:56:00 +00001434 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1437 }
1438
1439 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1440 assert(N == 1 && "Invalid number of operands!");
1441 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1442 }
1443
1444 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1445 assert(N == 1 && "Invalid number of operands!");
1446 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1447 }
1448
Jim Grosbach0e387b22011-10-17 22:26:03 +00001449 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 1 && "Invalid number of operands!");
1451 // The immediate encodes the type of constant as well as the value.
1452 // Mask in that this is an i8 splat.
1453 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1454 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1455 }
1456
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001457 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001458
Jim Grosbach89df9962011-08-26 21:43:41 +00001459 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001460 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001461 Op->ITMask.Mask = Mask;
1462 Op->StartLoc = S;
1463 Op->EndLoc = S;
1464 return Op;
1465 }
1466
Chris Lattner3a697562010-10-28 17:20:03 +00001467 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001468 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001469 Op->CC.Val = CC;
1470 Op->StartLoc = S;
1471 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001472 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001473 }
1474
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001475 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001476 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001477 Op->Cop.Val = CopVal;
1478 Op->StartLoc = S;
1479 Op->EndLoc = S;
1480 return Op;
1481 }
1482
1483 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001484 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001485 Op->Cop.Val = CopVal;
1486 Op->StartLoc = S;
1487 Op->EndLoc = S;
1488 return Op;
1489 }
1490
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001491 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1492 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1493 Op->Cop.Val = Val;
1494 Op->StartLoc = S;
1495 Op->EndLoc = E;
1496 return Op;
1497 }
1498
Jim Grosbachd67641b2010-12-06 18:21:12 +00001499 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001500 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001501 Op->Reg.RegNum = RegNum;
1502 Op->StartLoc = S;
1503 Op->EndLoc = S;
1504 return Op;
1505 }
1506
Chris Lattner3a697562010-10-28 17:20:03 +00001507 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001508 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001509 Op->Tok.Data = Str.data();
1510 Op->Tok.Length = Str.size();
1511 Op->StartLoc = S;
1512 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001513 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001514 }
1515
Bill Wendling50d0f582010-11-18 23:43:05 +00001516 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001517 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001518 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001519 Op->StartLoc = S;
1520 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001521 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001522 }
1523
Jim Grosbache8606dc2011-07-13 17:50:29 +00001524 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1525 unsigned SrcReg,
1526 unsigned ShiftReg,
1527 unsigned ShiftImm,
1528 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001529 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001530 Op->RegShiftedReg.ShiftTy = ShTy;
1531 Op->RegShiftedReg.SrcReg = SrcReg;
1532 Op->RegShiftedReg.ShiftReg = ShiftReg;
1533 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001534 Op->StartLoc = S;
1535 Op->EndLoc = E;
1536 return Op;
1537 }
1538
Owen Anderson92a20222011-07-21 18:54:16 +00001539 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1540 unsigned SrcReg,
1541 unsigned ShiftImm,
1542 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001543 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001544 Op->RegShiftedImm.ShiftTy = ShTy;
1545 Op->RegShiftedImm.SrcReg = SrcReg;
1546 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001547 Op->StartLoc = S;
1548 Op->EndLoc = E;
1549 return Op;
1550 }
1551
Jim Grosbach580f4a92011-07-25 22:20:28 +00001552 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001553 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001554 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001555 Op->ShifterImm.isASR = isASR;
1556 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001557 Op->StartLoc = S;
1558 Op->EndLoc = E;
1559 return Op;
1560 }
1561
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001562 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001563 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001564 Op->RotImm.Imm = Imm;
1565 Op->StartLoc = S;
1566 Op->EndLoc = E;
1567 return Op;
1568 }
1569
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001570 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1571 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001572 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001573 Op->Bitfield.LSB = LSB;
1574 Op->Bitfield.Width = Width;
1575 Op->StartLoc = S;
1576 Op->EndLoc = E;
1577 return Op;
1578 }
1579
Bill Wendling7729e062010-11-09 22:44:22 +00001580 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001581 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001582 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001583 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001584
Jim Grosbachd300b942011-09-13 22:56:44 +00001585 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001586 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001587 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001588 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001589 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001590
1591 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001592 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001593 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001594 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001595 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001596 Op->StartLoc = StartLoc;
1597 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001598 return Op;
1599 }
1600
Jim Grosbach460a9052011-10-07 23:56:00 +00001601 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1602 MCContext &Ctx) {
1603 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1604 Op->VectorIndex.Val = Idx;
1605 Op->StartLoc = S;
1606 Op->EndLoc = E;
1607 return Op;
1608 }
1609
Chris Lattner3a697562010-10-28 17:20:03 +00001610 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001611 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001612 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001613 Op->StartLoc = S;
1614 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001615 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001616 }
1617
Jim Grosbach9d390362011-10-03 23:38:36 +00001618 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001619 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001620 Op->FPImm.Val = Val;
1621 Op->StartLoc = S;
1622 Op->EndLoc = S;
1623 return Op;
1624 }
1625
Jim Grosbach7ce05792011-08-03 23:50:40 +00001626 static ARMOperand *CreateMem(unsigned BaseRegNum,
1627 const MCConstantExpr *OffsetImm,
1628 unsigned OffsetRegNum,
1629 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001630 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001631 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001632 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001633 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001634 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001635 Op->Memory.BaseRegNum = BaseRegNum;
1636 Op->Memory.OffsetImm = OffsetImm;
1637 Op->Memory.OffsetRegNum = OffsetRegNum;
1638 Op->Memory.ShiftType = ShiftType;
1639 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001640 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001641 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001642 Op->StartLoc = S;
1643 Op->EndLoc = E;
1644 return Op;
1645 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001646
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001647 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1648 ARM_AM::ShiftOpc ShiftTy,
1649 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001650 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001651 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001652 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001653 Op->PostIdxReg.isAdd = isAdd;
1654 Op->PostIdxReg.ShiftTy = ShiftTy;
1655 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001656 Op->StartLoc = S;
1657 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001658 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001659 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001660
1661 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001662 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001663 Op->MBOpt.Val = Opt;
1664 Op->StartLoc = S;
1665 Op->EndLoc = S;
1666 return Op;
1667 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001668
1669 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001670 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001671 Op->IFlags.Val = IFlags;
1672 Op->StartLoc = S;
1673 Op->EndLoc = S;
1674 return Op;
1675 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001676
1677 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001678 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001679 Op->MMask.Val = MMask;
1680 Op->StartLoc = S;
1681 Op->EndLoc = S;
1682 return Op;
1683 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001684};
1685
1686} // end anonymous namespace.
1687
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001688void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001689 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001690 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001691 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1692 << ") >";
1693 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001694 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001695 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001696 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001697 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001698 OS << "<ccout " << getReg() << ">";
1699 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001700 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001701 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1702 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1703 "(tee)", "(eee)" };
1704 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1705 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1706 break;
1707 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001708 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001709 OS << "<coprocessor number: " << getCoproc() << ">";
1710 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001711 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001712 OS << "<coprocessor register: " << getCoproc() << ">";
1713 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001714 case k_CoprocOption:
1715 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1716 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001717 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001718 OS << "<mask: " << getMSRMask() << ">";
1719 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001720 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001721 getImm()->print(OS);
1722 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001723 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001724 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1725 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001726 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001727 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001728 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001729 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001730 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001731 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001732 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1733 << PostIdxReg.RegNum;
1734 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1735 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1736 << PostIdxReg.ShiftImm;
1737 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001738 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001739 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001740 OS << "<ARM_PROC::";
1741 unsigned IFlags = getProcIFlags();
1742 for (int i=2; i >= 0; --i)
1743 if (IFlags & (1 << i))
1744 OS << ARM_PROC::IFlagsToString(1 << i);
1745 OS << ">";
1746 break;
1747 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001748 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001749 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001750 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001751 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001752 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1753 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001754 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001756 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001757 << RegShiftedReg.SrcReg
1758 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1759 << ", " << RegShiftedReg.ShiftReg << ", "
1760 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001761 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001762 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001763 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001764 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001765 << RegShiftedImm.SrcReg
1766 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1767 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001768 << ">";
1769 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001770 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001771 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1772 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001773 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001774 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1775 << ", width: " << Bitfield.Width << ">";
1776 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001777 case k_RegisterList:
1778 case k_DPRRegisterList:
1779 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001780 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001781
Bill Wendling5fa22a12010-11-09 23:28:44 +00001782 const SmallVectorImpl<unsigned> &RegList = getRegList();
1783 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001784 I = RegList.begin(), E = RegList.end(); I != E; ) {
1785 OS << *I;
1786 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001787 }
1788
1789 OS << ">";
1790 break;
1791 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001792 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001793 OS << "'" << getToken() << "'";
1794 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001795 case k_VectorIndex:
1796 OS << "<vectorindex " << getVectorIndex() << ">";
1797 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001798 }
1799}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001800
1801/// @name Auto-generated Match Functions
1802/// {
1803
1804static unsigned MatchRegisterName(StringRef Name);
1805
1806/// }
1807
Bob Wilson69df7232011-02-03 21:46:10 +00001808bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1809 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001810 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001811
1812 return (RegNo == (unsigned)-1);
1813}
1814
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001815/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001816/// and if it is a register name the token is eaten and the register number is
1817/// returned. Otherwise return -1.
1818///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001819int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001820 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001821 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001822
Chris Lattnere5658fa2010-10-30 04:09:10 +00001823 // FIXME: Validate register for the current architecture; we have to do
1824 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001825 std::string upperCase = Tok.getString().str();
1826 std::string lowerCase = LowercaseString(upperCase);
1827 unsigned RegNum = MatchRegisterName(lowerCase);
1828 if (!RegNum) {
1829 RegNum = StringSwitch<unsigned>(lowerCase)
1830 .Case("r13", ARM::SP)
1831 .Case("r14", ARM::LR)
1832 .Case("r15", ARM::PC)
1833 .Case("ip", ARM::R12)
1834 .Default(0);
1835 }
1836 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001837
Chris Lattnere5658fa2010-10-30 04:09:10 +00001838 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001839
1840#if 0
1841 // Also check for an index operand. This is only legal for vector registers,
1842 // but that'll get caught OK in operand matching, so we don't need to
1843 // explicitly filter everything else out here.
1844 if (Parser.getTok().is(AsmToken::LBrac)) {
1845 SMLoc SIdx = Parser.getTok().getLoc();
1846 Parser.Lex(); // Eat left bracket token.
1847
1848 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00001849 if (getParser().ParseExpression(ImmVal))
1850 return MatchOperand_ParseFail;
1851 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1852 if (!MCE) {
1853 TokError("immediate value expected for vector index");
1854 return MatchOperand_ParseFail;
1855 }
1856
1857 SMLoc E = Parser.getTok().getLoc();
1858 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1859 Error(E, "']' expected");
1860 return MatchOperand_ParseFail;
1861 }
1862
1863 Parser.Lex(); // Eat right bracket token.
1864
1865 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1866 SIdx, E,
1867 getContext()));
1868 }
1869#endif
1870
Chris Lattnere5658fa2010-10-30 04:09:10 +00001871 return RegNum;
1872}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001873
Jim Grosbach19906722011-07-13 18:49:30 +00001874// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1875// If a recoverable error occurs, return 1. If an irrecoverable error
1876// occurs, return -1. An irrecoverable error is one where tokens have been
1877// consumed in the process of trying to parse the shifter (i.e., when it is
1878// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001879int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001880 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1881 SMLoc S = Parser.getTok().getLoc();
1882 const AsmToken &Tok = Parser.getTok();
1883 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1884
1885 std::string upperCase = Tok.getString().str();
1886 std::string lowerCase = LowercaseString(upperCase);
1887 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1888 .Case("lsl", ARM_AM::lsl)
1889 .Case("lsr", ARM_AM::lsr)
1890 .Case("asr", ARM_AM::asr)
1891 .Case("ror", ARM_AM::ror)
1892 .Case("rrx", ARM_AM::rrx)
1893 .Default(ARM_AM::no_shift);
1894
1895 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001896 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001897
Jim Grosbache8606dc2011-07-13 17:50:29 +00001898 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001899
Jim Grosbache8606dc2011-07-13 17:50:29 +00001900 // The source register for the shift has already been added to the
1901 // operand list, so we need to pop it off and combine it into the shifted
1902 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001903 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001904 if (!PrevOp->isReg())
1905 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1906 int SrcReg = PrevOp->getReg();
1907 int64_t Imm = 0;
1908 int ShiftReg = 0;
1909 if (ShiftTy == ARM_AM::rrx) {
1910 // RRX Doesn't have an explicit shift amount. The encoder expects
1911 // the shift register to be the same as the source register. Seems odd,
1912 // but OK.
1913 ShiftReg = SrcReg;
1914 } else {
1915 // Figure out if this is shifted by a constant or a register (for non-RRX).
1916 if (Parser.getTok().is(AsmToken::Hash)) {
1917 Parser.Lex(); // Eat hash.
1918 SMLoc ImmLoc = Parser.getTok().getLoc();
1919 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001920 if (getParser().ParseExpression(ShiftExpr)) {
1921 Error(ImmLoc, "invalid immediate shift value");
1922 return -1;
1923 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001924 // The expression must be evaluatable as an immediate.
1925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001926 if (!CE) {
1927 Error(ImmLoc, "invalid immediate shift value");
1928 return -1;
1929 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001930 // Range check the immediate.
1931 // lsl, ror: 0 <= imm <= 31
1932 // lsr, asr: 0 <= imm <= 32
1933 Imm = CE->getValue();
1934 if (Imm < 0 ||
1935 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1936 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001937 Error(ImmLoc, "immediate shift value out of range");
1938 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001939 }
1940 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001941 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001942 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001943 if (ShiftReg == -1) {
1944 Error (L, "expected immediate or register in shift operand");
1945 return -1;
1946 }
1947 } else {
1948 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001949 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001950 return -1;
1951 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001952 }
1953
Owen Anderson92a20222011-07-21 18:54:16 +00001954 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1955 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001956 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001957 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001958 else
1959 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1960 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001961
Jim Grosbach19906722011-07-13 18:49:30 +00001962 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001963}
1964
1965
Bill Wendling50d0f582010-11-18 23:43:05 +00001966/// Try to parse a register name. The token must be an Identifier when called.
1967/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1968/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001969///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001970/// TODO this is likely to change to allow different register types and or to
1971/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001972bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001973tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001974 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001975 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001976 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001977 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001978
Bill Wendling50d0f582010-11-18 23:43:05 +00001979 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001980
Chris Lattnere5658fa2010-10-30 04:09:10 +00001981 const AsmToken &ExclaimTok = Parser.getTok();
1982 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001983 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1984 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001985 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00001986 return false;
1987 }
1988
1989 // Also check for an index operand. This is only legal for vector registers,
1990 // but that'll get caught OK in operand matching, so we don't need to
1991 // explicitly filter everything else out here.
1992 if (Parser.getTok().is(AsmToken::LBrac)) {
1993 SMLoc SIdx = Parser.getTok().getLoc();
1994 Parser.Lex(); // Eat left bracket token.
1995
1996 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00001997 if (getParser().ParseExpression(ImmVal))
1998 return MatchOperand_ParseFail;
1999 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2000 if (!MCE) {
2001 TokError("immediate value expected for vector index");
2002 return MatchOperand_ParseFail;
2003 }
2004
2005 SMLoc E = Parser.getTok().getLoc();
2006 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2007 Error(E, "']' expected");
2008 return MatchOperand_ParseFail;
2009 }
2010
2011 Parser.Lex(); // Eat right bracket token.
2012
2013 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2014 SIdx, E,
2015 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002016 }
2017
Bill Wendling50d0f582010-11-18 23:43:05 +00002018 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002019}
2020
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002021/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2022/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2023/// "c5", ...
2024static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002025 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2026 // but efficient.
2027 switch (Name.size()) {
2028 default: break;
2029 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002030 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002031 return -1;
2032 switch (Name[1]) {
2033 default: return -1;
2034 case '0': return 0;
2035 case '1': return 1;
2036 case '2': return 2;
2037 case '3': return 3;
2038 case '4': return 4;
2039 case '5': return 5;
2040 case '6': return 6;
2041 case '7': return 7;
2042 case '8': return 8;
2043 case '9': return 9;
2044 }
2045 break;
2046 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002047 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002048 return -1;
2049 switch (Name[2]) {
2050 default: return -1;
2051 case '0': return 10;
2052 case '1': return 11;
2053 case '2': return 12;
2054 case '3': return 13;
2055 case '4': return 14;
2056 case '5': return 15;
2057 }
2058 break;
2059 }
2060
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002061 return -1;
2062}
2063
Jim Grosbach89df9962011-08-26 21:43:41 +00002064/// parseITCondCode - Try to parse a condition code for an IT instruction.
2065ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2066parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2067 SMLoc S = Parser.getTok().getLoc();
2068 const AsmToken &Tok = Parser.getTok();
2069 if (!Tok.is(AsmToken::Identifier))
2070 return MatchOperand_NoMatch;
2071 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2072 .Case("eq", ARMCC::EQ)
2073 .Case("ne", ARMCC::NE)
2074 .Case("hs", ARMCC::HS)
2075 .Case("cs", ARMCC::HS)
2076 .Case("lo", ARMCC::LO)
2077 .Case("cc", ARMCC::LO)
2078 .Case("mi", ARMCC::MI)
2079 .Case("pl", ARMCC::PL)
2080 .Case("vs", ARMCC::VS)
2081 .Case("vc", ARMCC::VC)
2082 .Case("hi", ARMCC::HI)
2083 .Case("ls", ARMCC::LS)
2084 .Case("ge", ARMCC::GE)
2085 .Case("lt", ARMCC::LT)
2086 .Case("gt", ARMCC::GT)
2087 .Case("le", ARMCC::LE)
2088 .Case("al", ARMCC::AL)
2089 .Default(~0U);
2090 if (CC == ~0U)
2091 return MatchOperand_NoMatch;
2092 Parser.Lex(); // Eat the token.
2093
2094 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2095
2096 return MatchOperand_Success;
2097}
2098
Jim Grosbach43904292011-07-25 20:14:50 +00002099/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002100/// token must be an Identifier when called, and if it is a coprocessor
2101/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002102ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002103parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002104 SMLoc S = Parser.getTok().getLoc();
2105 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002106 if (Tok.isNot(AsmToken::Identifier))
2107 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002108
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002109 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002110 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002111 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002112
2113 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002114 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002115 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002116}
2117
Jim Grosbach43904292011-07-25 20:14:50 +00002118/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002119/// token must be an Identifier when called, and if it is a coprocessor
2120/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002121ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002122parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002123 SMLoc S = Parser.getTok().getLoc();
2124 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002125 if (Tok.isNot(AsmToken::Identifier))
2126 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002127
2128 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2129 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002130 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002131
2132 Parser.Lex(); // Eat identifier token.
2133 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002134 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002135}
2136
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002137/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2138/// coproc_option : '{' imm0_255 '}'
2139ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2140parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2141 SMLoc S = Parser.getTok().getLoc();
2142
2143 // If this isn't a '{', this isn't a coprocessor immediate operand.
2144 if (Parser.getTok().isNot(AsmToken::LCurly))
2145 return MatchOperand_NoMatch;
2146 Parser.Lex(); // Eat the '{'
2147
2148 const MCExpr *Expr;
2149 SMLoc Loc = Parser.getTok().getLoc();
2150 if (getParser().ParseExpression(Expr)) {
2151 Error(Loc, "illegal expression");
2152 return MatchOperand_ParseFail;
2153 }
2154 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2155 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2156 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2157 return MatchOperand_ParseFail;
2158 }
2159 int Val = CE->getValue();
2160
2161 // Check for and consume the closing '}'
2162 if (Parser.getTok().isNot(AsmToken::RCurly))
2163 return MatchOperand_ParseFail;
2164 SMLoc E = Parser.getTok().getLoc();
2165 Parser.Lex(); // Eat the '}'
2166
2167 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2168 return MatchOperand_Success;
2169}
2170
Jim Grosbachd0588e22011-09-14 18:08:35 +00002171// For register list parsing, we need to map from raw GPR register numbering
2172// to the enumeration values. The enumeration values aren't sorted by
2173// register number due to our using "sp", "lr" and "pc" as canonical names.
2174static unsigned getNextRegister(unsigned Reg) {
2175 // If this is a GPR, we need to do it manually, otherwise we can rely
2176 // on the sort ordering of the enumeration since the other reg-classes
2177 // are sane.
2178 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2179 return Reg + 1;
2180 switch(Reg) {
2181 default: assert(0 && "Invalid GPR number!");
2182 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2183 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2184 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2185 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2186 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2187 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2188 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2189 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2190 }
2191}
2192
2193/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002194bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002195parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002196 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002197 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002198 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002199 Parser.Lex(); // Eat '{' token.
2200 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002201
Jim Grosbachd0588e22011-09-14 18:08:35 +00002202 // Check the first register in the list to see what register class
2203 // this is a list of.
2204 int Reg = tryParseRegister();
2205 if (Reg == -1)
2206 return Error(RegLoc, "register expected");
2207
2208 MCRegisterClass *RC;
2209 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2210 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2211 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2212 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2213 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2214 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2215 else
2216 return Error(RegLoc, "invalid register in register list");
2217
2218 // The reglist instructions have at most 16 registers, so reserve
2219 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002220 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002221 // Store the first register.
2222 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002223
Jim Grosbachd0588e22011-09-14 18:08:35 +00002224 // This starts immediately after the first register token in the list,
2225 // so we can see either a comma or a minus (range separator) as a legal
2226 // next token.
2227 while (Parser.getTok().is(AsmToken::Comma) ||
2228 Parser.getTok().is(AsmToken::Minus)) {
2229 if (Parser.getTok().is(AsmToken::Minus)) {
2230 Parser.Lex(); // Eat the comma.
2231 SMLoc EndLoc = Parser.getTok().getLoc();
2232 int EndReg = tryParseRegister();
2233 if (EndReg == -1)
2234 return Error(EndLoc, "register expected");
2235 // If the register is the same as the start reg, there's nothing
2236 // more to do.
2237 if (Reg == EndReg)
2238 continue;
2239 // The register must be in the same register class as the first.
2240 if (!RC->contains(EndReg))
2241 return Error(EndLoc, "invalid register in register list");
2242 // Ranges must go from low to high.
2243 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2244 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002245
Jim Grosbachd0588e22011-09-14 18:08:35 +00002246 // Add all the registers in the range to the register list.
2247 while (Reg != EndReg) {
2248 Reg = getNextRegister(Reg);
2249 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2250 }
2251 continue;
2252 }
2253 Parser.Lex(); // Eat the comma.
2254 RegLoc = Parser.getTok().getLoc();
2255 int OldReg = Reg;
2256 Reg = tryParseRegister();
2257 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002258 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002259 // The register must be in the same register class as the first.
2260 if (!RC->contains(Reg))
2261 return Error(RegLoc, "invalid register in register list");
2262 // List must be monotonically increasing.
2263 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2264 return Error(RegLoc, "register list not in ascending order");
2265 // VFP register lists must also be contiguous.
2266 // It's OK to use the enumeration values directly here rather, as the
2267 // VFP register classes have the enum sorted properly.
2268 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2269 Reg != OldReg + 1)
2270 return Error(RegLoc, "non-contiguous register range");
2271 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002272 }
2273
Jim Grosbachd0588e22011-09-14 18:08:35 +00002274 SMLoc E = Parser.getTok().getLoc();
2275 if (Parser.getTok().isNot(AsmToken::RCurly))
2276 return Error(E, "'}' expected");
2277 Parser.Lex(); // Eat '}' token.
2278
Bill Wendling50d0f582010-11-18 23:43:05 +00002279 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2280 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002281}
2282
Jim Grosbach43904292011-07-25 20:14:50 +00002283/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002284ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002285parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002286 SMLoc S = Parser.getTok().getLoc();
2287 const AsmToken &Tok = Parser.getTok();
2288 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2289 StringRef OptStr = Tok.getString();
2290
2291 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2292 .Case("sy", ARM_MB::SY)
2293 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002294 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002295 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002296 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002297 .Case("ishst", ARM_MB::ISHST)
2298 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002299 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002300 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002301 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002302 .Case("osh", ARM_MB::OSH)
2303 .Case("oshst", ARM_MB::OSHST)
2304 .Default(~0U);
2305
2306 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002307 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002308
2309 Parser.Lex(); // Eat identifier token.
2310 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002311 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002312}
2313
Jim Grosbach43904292011-07-25 20:14:50 +00002314/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002315ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002316parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002317 SMLoc S = Parser.getTok().getLoc();
2318 const AsmToken &Tok = Parser.getTok();
2319 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2320 StringRef IFlagsStr = Tok.getString();
2321
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002322 // An iflags string of "none" is interpreted to mean that none of the AIF
2323 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002324 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002325 if (IFlagsStr != "none") {
2326 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2327 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2328 .Case("a", ARM_PROC::A)
2329 .Case("i", ARM_PROC::I)
2330 .Case("f", ARM_PROC::F)
2331 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002332
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002333 // If some specific iflag is already set, it means that some letter is
2334 // present more than once, this is not acceptable.
2335 if (Flag == ~0U || (IFlags & Flag))
2336 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002337
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002338 IFlags |= Flag;
2339 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002340 }
2341
2342 Parser.Lex(); // Eat identifier token.
2343 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2344 return MatchOperand_Success;
2345}
2346
Jim Grosbach43904292011-07-25 20:14:50 +00002347/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002348ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002349parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002350 SMLoc S = Parser.getTok().getLoc();
2351 const AsmToken &Tok = Parser.getTok();
2352 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2353 StringRef Mask = Tok.getString();
2354
James Molloyacad68d2011-09-28 14:21:38 +00002355 if (isMClass()) {
2356 // See ARMv6-M 10.1.1
2357 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2358 .Case("apsr", 0)
2359 .Case("iapsr", 1)
2360 .Case("eapsr", 2)
2361 .Case("xpsr", 3)
2362 .Case("ipsr", 5)
2363 .Case("epsr", 6)
2364 .Case("iepsr", 7)
2365 .Case("msp", 8)
2366 .Case("psp", 9)
2367 .Case("primask", 16)
2368 .Case("basepri", 17)
2369 .Case("basepri_max", 18)
2370 .Case("faultmask", 19)
2371 .Case("control", 20)
2372 .Default(~0U);
2373
2374 if (FlagsVal == ~0U)
2375 return MatchOperand_NoMatch;
2376
2377 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2378 // basepri, basepri_max and faultmask only valid for V7m.
2379 return MatchOperand_NoMatch;
2380
2381 Parser.Lex(); // Eat identifier token.
2382 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2383 return MatchOperand_Success;
2384 }
2385
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002386 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2387 size_t Start = 0, Next = Mask.find('_');
2388 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002389 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002390 if (Next != StringRef::npos)
2391 Flags = Mask.slice(Next+1, Mask.size());
2392
2393 // FlagsVal contains the complete mask:
2394 // 3-0: Mask
2395 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2396 unsigned FlagsVal = 0;
2397
2398 if (SpecReg == "apsr") {
2399 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002400 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002401 .Case("g", 0x4) // same as CPSR_s
2402 .Case("nzcvqg", 0xc) // same as CPSR_fs
2403 .Default(~0U);
2404
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002405 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002406 if (!Flags.empty())
2407 return MatchOperand_NoMatch;
2408 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002409 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002410 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002411 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002412 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2413 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002414 for (int i = 0, e = Flags.size(); i != e; ++i) {
2415 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2416 .Case("c", 1)
2417 .Case("x", 2)
2418 .Case("s", 4)
2419 .Case("f", 8)
2420 .Default(~0U);
2421
2422 // If some specific flag is already set, it means that some letter is
2423 // present more than once, this is not acceptable.
2424 if (FlagsVal == ~0U || (FlagsVal & Flag))
2425 return MatchOperand_NoMatch;
2426 FlagsVal |= Flag;
2427 }
2428 } else // No match for special register.
2429 return MatchOperand_NoMatch;
2430
2431 // Special register without flags are equivalent to "fc" flags.
2432 if (!FlagsVal)
2433 FlagsVal = 0x9;
2434
2435 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2436 if (SpecReg == "spsr")
2437 FlagsVal |= 16;
2438
2439 Parser.Lex(); // Eat identifier token.
2440 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2441 return MatchOperand_Success;
2442}
2443
Jim Grosbachf6c05252011-07-21 17:23:04 +00002444ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2445parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2446 int Low, int High) {
2447 const AsmToken &Tok = Parser.getTok();
2448 if (Tok.isNot(AsmToken::Identifier)) {
2449 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2450 return MatchOperand_ParseFail;
2451 }
2452 StringRef ShiftName = Tok.getString();
2453 std::string LowerOp = LowercaseString(Op);
2454 std::string UpperOp = UppercaseString(Op);
2455 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2456 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2457 return MatchOperand_ParseFail;
2458 }
2459 Parser.Lex(); // Eat shift type token.
2460
2461 // There must be a '#' and a shift amount.
2462 if (Parser.getTok().isNot(AsmToken::Hash)) {
2463 Error(Parser.getTok().getLoc(), "'#' expected");
2464 return MatchOperand_ParseFail;
2465 }
2466 Parser.Lex(); // Eat hash token.
2467
2468 const MCExpr *ShiftAmount;
2469 SMLoc Loc = Parser.getTok().getLoc();
2470 if (getParser().ParseExpression(ShiftAmount)) {
2471 Error(Loc, "illegal expression");
2472 return MatchOperand_ParseFail;
2473 }
2474 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2475 if (!CE) {
2476 Error(Loc, "constant expression expected");
2477 return MatchOperand_ParseFail;
2478 }
2479 int Val = CE->getValue();
2480 if (Val < Low || Val > High) {
2481 Error(Loc, "immediate value out of range");
2482 return MatchOperand_ParseFail;
2483 }
2484
2485 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2486
2487 return MatchOperand_Success;
2488}
2489
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002490ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2491parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2492 const AsmToken &Tok = Parser.getTok();
2493 SMLoc S = Tok.getLoc();
2494 if (Tok.isNot(AsmToken::Identifier)) {
2495 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2496 return MatchOperand_ParseFail;
2497 }
2498 int Val = StringSwitch<int>(Tok.getString())
2499 .Case("be", 1)
2500 .Case("le", 0)
2501 .Default(-1);
2502 Parser.Lex(); // Eat the token.
2503
2504 if (Val == -1) {
2505 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2506 return MatchOperand_ParseFail;
2507 }
2508 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2509 getContext()),
2510 S, Parser.getTok().getLoc()));
2511 return MatchOperand_Success;
2512}
2513
Jim Grosbach580f4a92011-07-25 22:20:28 +00002514/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2515/// instructions. Legal values are:
2516/// lsl #n 'n' in [0,31]
2517/// asr #n 'n' in [1,32]
2518/// n == 32 encoded as n == 0.
2519ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2520parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2521 const AsmToken &Tok = Parser.getTok();
2522 SMLoc S = Tok.getLoc();
2523 if (Tok.isNot(AsmToken::Identifier)) {
2524 Error(S, "shift operator 'asr' or 'lsl' expected");
2525 return MatchOperand_ParseFail;
2526 }
2527 StringRef ShiftName = Tok.getString();
2528 bool isASR;
2529 if (ShiftName == "lsl" || ShiftName == "LSL")
2530 isASR = false;
2531 else if (ShiftName == "asr" || ShiftName == "ASR")
2532 isASR = true;
2533 else {
2534 Error(S, "shift operator 'asr' or 'lsl' expected");
2535 return MatchOperand_ParseFail;
2536 }
2537 Parser.Lex(); // Eat the operator.
2538
2539 // A '#' and a shift amount.
2540 if (Parser.getTok().isNot(AsmToken::Hash)) {
2541 Error(Parser.getTok().getLoc(), "'#' expected");
2542 return MatchOperand_ParseFail;
2543 }
2544 Parser.Lex(); // Eat hash token.
2545
2546 const MCExpr *ShiftAmount;
2547 SMLoc E = Parser.getTok().getLoc();
2548 if (getParser().ParseExpression(ShiftAmount)) {
2549 Error(E, "malformed shift expression");
2550 return MatchOperand_ParseFail;
2551 }
2552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2553 if (!CE) {
2554 Error(E, "shift amount must be an immediate");
2555 return MatchOperand_ParseFail;
2556 }
2557
2558 int64_t Val = CE->getValue();
2559 if (isASR) {
2560 // Shift amount must be in [1,32]
2561 if (Val < 1 || Val > 32) {
2562 Error(E, "'asr' shift amount must be in range [1,32]");
2563 return MatchOperand_ParseFail;
2564 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002565 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2566 if (isThumb() && Val == 32) {
2567 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2568 return MatchOperand_ParseFail;
2569 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002570 if (Val == 32) Val = 0;
2571 } else {
2572 // Shift amount must be in [1,32]
2573 if (Val < 0 || Val > 31) {
2574 Error(E, "'lsr' shift amount must be in range [0,31]");
2575 return MatchOperand_ParseFail;
2576 }
2577 }
2578
2579 E = Parser.getTok().getLoc();
2580 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2581
2582 return MatchOperand_Success;
2583}
2584
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002585/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2586/// of instructions. Legal values are:
2587/// ror #n 'n' in {0, 8, 16, 24}
2588ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2589parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2590 const AsmToken &Tok = Parser.getTok();
2591 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002592 if (Tok.isNot(AsmToken::Identifier))
2593 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002594 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002595 if (ShiftName != "ror" && ShiftName != "ROR")
2596 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002597 Parser.Lex(); // Eat the operator.
2598
2599 // A '#' and a rotate amount.
2600 if (Parser.getTok().isNot(AsmToken::Hash)) {
2601 Error(Parser.getTok().getLoc(), "'#' expected");
2602 return MatchOperand_ParseFail;
2603 }
2604 Parser.Lex(); // Eat hash token.
2605
2606 const MCExpr *ShiftAmount;
2607 SMLoc E = Parser.getTok().getLoc();
2608 if (getParser().ParseExpression(ShiftAmount)) {
2609 Error(E, "malformed rotate expression");
2610 return MatchOperand_ParseFail;
2611 }
2612 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2613 if (!CE) {
2614 Error(E, "rotate amount must be an immediate");
2615 return MatchOperand_ParseFail;
2616 }
2617
2618 int64_t Val = CE->getValue();
2619 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2620 // normally, zero is represented in asm by omitting the rotate operand
2621 // entirely.
2622 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2623 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2624 return MatchOperand_ParseFail;
2625 }
2626
2627 E = Parser.getTok().getLoc();
2628 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2629
2630 return MatchOperand_Success;
2631}
2632
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002633ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2634parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2635 SMLoc S = Parser.getTok().getLoc();
2636 // The bitfield descriptor is really two operands, the LSB and the width.
2637 if (Parser.getTok().isNot(AsmToken::Hash)) {
2638 Error(Parser.getTok().getLoc(), "'#' expected");
2639 return MatchOperand_ParseFail;
2640 }
2641 Parser.Lex(); // Eat hash token.
2642
2643 const MCExpr *LSBExpr;
2644 SMLoc E = Parser.getTok().getLoc();
2645 if (getParser().ParseExpression(LSBExpr)) {
2646 Error(E, "malformed immediate expression");
2647 return MatchOperand_ParseFail;
2648 }
2649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2650 if (!CE) {
2651 Error(E, "'lsb' operand must be an immediate");
2652 return MatchOperand_ParseFail;
2653 }
2654
2655 int64_t LSB = CE->getValue();
2656 // The LSB must be in the range [0,31]
2657 if (LSB < 0 || LSB > 31) {
2658 Error(E, "'lsb' operand must be in the range [0,31]");
2659 return MatchOperand_ParseFail;
2660 }
2661 E = Parser.getTok().getLoc();
2662
2663 // Expect another immediate operand.
2664 if (Parser.getTok().isNot(AsmToken::Comma)) {
2665 Error(Parser.getTok().getLoc(), "too few operands");
2666 return MatchOperand_ParseFail;
2667 }
2668 Parser.Lex(); // Eat hash token.
2669 if (Parser.getTok().isNot(AsmToken::Hash)) {
2670 Error(Parser.getTok().getLoc(), "'#' expected");
2671 return MatchOperand_ParseFail;
2672 }
2673 Parser.Lex(); // Eat hash token.
2674
2675 const MCExpr *WidthExpr;
2676 if (getParser().ParseExpression(WidthExpr)) {
2677 Error(E, "malformed immediate expression");
2678 return MatchOperand_ParseFail;
2679 }
2680 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2681 if (!CE) {
2682 Error(E, "'width' operand must be an immediate");
2683 return MatchOperand_ParseFail;
2684 }
2685
2686 int64_t Width = CE->getValue();
2687 // The LSB must be in the range [1,32-lsb]
2688 if (Width < 1 || Width > 32 - LSB) {
2689 Error(E, "'width' operand must be in the range [1,32-lsb]");
2690 return MatchOperand_ParseFail;
2691 }
2692 E = Parser.getTok().getLoc();
2693
2694 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2695
2696 return MatchOperand_Success;
2697}
2698
Jim Grosbach7ce05792011-08-03 23:50:40 +00002699ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2700parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2701 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002702 // postidx_reg := '+' register {, shift}
2703 // | '-' register {, shift}
2704 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002705
2706 // This method must return MatchOperand_NoMatch without consuming any tokens
2707 // in the case where there is no match, as other alternatives take other
2708 // parse methods.
2709 AsmToken Tok = Parser.getTok();
2710 SMLoc S = Tok.getLoc();
2711 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002712 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002713 int Reg = -1;
2714 if (Tok.is(AsmToken::Plus)) {
2715 Parser.Lex(); // Eat the '+' token.
2716 haveEaten = true;
2717 } else if (Tok.is(AsmToken::Minus)) {
2718 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002719 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002720 haveEaten = true;
2721 }
2722 if (Parser.getTok().is(AsmToken::Identifier))
2723 Reg = tryParseRegister();
2724 if (Reg == -1) {
2725 if (!haveEaten)
2726 return MatchOperand_NoMatch;
2727 Error(Parser.getTok().getLoc(), "register expected");
2728 return MatchOperand_ParseFail;
2729 }
2730 SMLoc E = Parser.getTok().getLoc();
2731
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002732 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2733 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002734 if (Parser.getTok().is(AsmToken::Comma)) {
2735 Parser.Lex(); // Eat the ','.
2736 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2737 return MatchOperand_ParseFail;
2738 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002739
2740 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2741 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002742
2743 return MatchOperand_Success;
2744}
2745
Jim Grosbach251bf252011-08-10 21:56:18 +00002746ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2747parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2748 // Check for a post-index addressing register operand. Specifically:
2749 // am3offset := '+' register
2750 // | '-' register
2751 // | register
2752 // | # imm
2753 // | # + imm
2754 // | # - imm
2755
2756 // This method must return MatchOperand_NoMatch without consuming any tokens
2757 // in the case where there is no match, as other alternatives take other
2758 // parse methods.
2759 AsmToken Tok = Parser.getTok();
2760 SMLoc S = Tok.getLoc();
2761
2762 // Do immediates first, as we always parse those if we have a '#'.
2763 if (Parser.getTok().is(AsmToken::Hash)) {
2764 Parser.Lex(); // Eat the '#'.
2765 // Explicitly look for a '-', as we need to encode negative zero
2766 // differently.
2767 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2768 const MCExpr *Offset;
2769 if (getParser().ParseExpression(Offset))
2770 return MatchOperand_ParseFail;
2771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2772 if (!CE) {
2773 Error(S, "constant expression expected");
2774 return MatchOperand_ParseFail;
2775 }
2776 SMLoc E = Tok.getLoc();
2777 // Negative zero is encoded as the flag value INT32_MIN.
2778 int32_t Val = CE->getValue();
2779 if (isNegative && Val == 0)
2780 Val = INT32_MIN;
2781
2782 Operands.push_back(
2783 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2784
2785 return MatchOperand_Success;
2786 }
2787
2788
2789 bool haveEaten = false;
2790 bool isAdd = true;
2791 int Reg = -1;
2792 if (Tok.is(AsmToken::Plus)) {
2793 Parser.Lex(); // Eat the '+' token.
2794 haveEaten = true;
2795 } else if (Tok.is(AsmToken::Minus)) {
2796 Parser.Lex(); // Eat the '-' token.
2797 isAdd = false;
2798 haveEaten = true;
2799 }
2800 if (Parser.getTok().is(AsmToken::Identifier))
2801 Reg = tryParseRegister();
2802 if (Reg == -1) {
2803 if (!haveEaten)
2804 return MatchOperand_NoMatch;
2805 Error(Parser.getTok().getLoc(), "register expected");
2806 return MatchOperand_ParseFail;
2807 }
2808 SMLoc E = Parser.getTok().getLoc();
2809
2810 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2811 0, S, E));
2812
2813 return MatchOperand_Success;
2814}
2815
Jim Grosbacha77295d2011-09-08 22:07:06 +00002816/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2817/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2818/// when they refer multiple MIOperands inside a single one.
2819bool ARMAsmParser::
2820cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2821 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2822 // Rt, Rt2
2823 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2824 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2825 // Create a writeback register dummy placeholder.
2826 Inst.addOperand(MCOperand::CreateReg(0));
2827 // addr
2828 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2829 // pred
2830 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2831 return true;
2832}
2833
2834/// cvtT2StrdPre - Convert parsed operands to MCInst.
2835/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2836/// when they refer multiple MIOperands inside a single one.
2837bool ARMAsmParser::
2838cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2839 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2840 // Create a writeback register dummy placeholder.
2841 Inst.addOperand(MCOperand::CreateReg(0));
2842 // Rt, Rt2
2843 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2844 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2845 // addr
2846 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2847 // pred
2848 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2849 return true;
2850}
2851
Jim Grosbacheeec0252011-09-08 00:39:19 +00002852/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2853/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2854/// when they refer multiple MIOperands inside a single one.
2855bool ARMAsmParser::
2856cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2857 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2858 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2859
2860 // Create a writeback register dummy placeholder.
2861 Inst.addOperand(MCOperand::CreateImm(0));
2862
2863 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2864 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2865 return true;
2866}
2867
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002868/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2869/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2870/// when they refer multiple MIOperands inside a single one.
2871bool ARMAsmParser::
2872cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2873 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2874 // Create a writeback register dummy placeholder.
2875 Inst.addOperand(MCOperand::CreateImm(0));
2876 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2877 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2878 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2879 return true;
2880}
2881
Jim Grosbach1355cf12011-07-26 17:10:22 +00002882/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002883/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2884/// when they refer multiple MIOperands inside a single one.
2885bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002886cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002887 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2888 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2889
2890 // Create a writeback register dummy placeholder.
2891 Inst.addOperand(MCOperand::CreateImm(0));
2892
Jim Grosbach7ce05792011-08-03 23:50:40 +00002893 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002894 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2895 return true;
2896}
2897
Owen Anderson9ab0f252011-08-26 20:43:14 +00002898/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2899/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2900/// when they refer multiple MIOperands inside a single one.
2901bool ARMAsmParser::
2902cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2903 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2904 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2905
2906 // Create a writeback register dummy placeholder.
2907 Inst.addOperand(MCOperand::CreateImm(0));
2908
2909 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2910 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2911 return true;
2912}
2913
2914
Jim Grosbach548340c2011-08-11 19:22:40 +00002915/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2916/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2917/// when they refer multiple MIOperands inside a single one.
2918bool ARMAsmParser::
2919cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2920 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2921 // Create a writeback register dummy placeholder.
2922 Inst.addOperand(MCOperand::CreateImm(0));
2923 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2924 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2925 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2926 return true;
2927}
2928
Jim Grosbach1355cf12011-07-26 17:10:22 +00002929/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002930/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2931/// when they refer multiple MIOperands inside a single one.
2932bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002933cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002934 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2935 // Create a writeback register dummy placeholder.
2936 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002937 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2938 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2939 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002940 return true;
2941}
2942
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002943/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2944/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2945/// when they refer multiple MIOperands inside a single one.
2946bool ARMAsmParser::
2947cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2948 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2949 // Create a writeback register dummy placeholder.
2950 Inst.addOperand(MCOperand::CreateImm(0));
2951 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2952 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2953 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2954 return true;
2955}
2956
Jim Grosbach7ce05792011-08-03 23:50:40 +00002957/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2958/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2959/// when they refer multiple MIOperands inside a single one.
2960bool ARMAsmParser::
2961cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2962 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2963 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002964 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002965 // Create a writeback register dummy placeholder.
2966 Inst.addOperand(MCOperand::CreateImm(0));
2967 // addr
2968 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2969 // offset
2970 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2971 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002972 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2973 return true;
2974}
2975
Jim Grosbach7ce05792011-08-03 23:50:40 +00002976/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002977/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2978/// when they refer multiple MIOperands inside a single one.
2979bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002980cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2981 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2982 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002983 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002984 // Create a writeback register dummy placeholder.
2985 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002986 // addr
2987 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2988 // offset
2989 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2990 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002991 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2992 return true;
2993}
2994
Jim Grosbach7ce05792011-08-03 23:50:40 +00002995/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002996/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2997/// when they refer multiple MIOperands inside a single one.
2998bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002999cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3000 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003001 // Create a writeback register dummy placeholder.
3002 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003003 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003004 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003005 // addr
3006 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3007 // offset
3008 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3009 // pred
3010 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3011 return true;
3012}
3013
3014/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3015/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3016/// when they refer multiple MIOperands inside a single one.
3017bool ARMAsmParser::
3018cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3019 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3020 // Create a writeback register dummy placeholder.
3021 Inst.addOperand(MCOperand::CreateImm(0));
3022 // Rt
3023 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3024 // addr
3025 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3026 // offset
3027 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3028 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003029 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3030 return true;
3031}
3032
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003033/// cvtLdrdPre - Convert parsed operands to MCInst.
3034/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3035/// when they refer multiple MIOperands inside a single one.
3036bool ARMAsmParser::
3037cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3038 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3039 // Rt, Rt2
3040 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3041 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3042 // Create a writeback register dummy placeholder.
3043 Inst.addOperand(MCOperand::CreateImm(0));
3044 // addr
3045 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3046 // pred
3047 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3048 return true;
3049}
3050
Jim Grosbach14605d12011-08-11 20:28:23 +00003051/// cvtStrdPre - Convert parsed operands to MCInst.
3052/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3053/// when they refer multiple MIOperands inside a single one.
3054bool ARMAsmParser::
3055cvtStrdPre(MCInst &Inst, unsigned Opcode,
3056 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3057 // Create a writeback register dummy placeholder.
3058 Inst.addOperand(MCOperand::CreateImm(0));
3059 // Rt, Rt2
3060 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3061 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3062 // addr
3063 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3064 // pred
3065 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3066 return true;
3067}
3068
Jim Grosbach623a4542011-08-10 22:42:16 +00003069/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3070/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3071/// when they refer multiple MIOperands inside a single one.
3072bool ARMAsmParser::
3073cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3074 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3075 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3076 // Create a writeback register dummy placeholder.
3077 Inst.addOperand(MCOperand::CreateImm(0));
3078 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3079 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3080 return true;
3081}
3082
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003083/// cvtThumbMultiple- Convert parsed operands to MCInst.
3084/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3085/// when they refer multiple MIOperands inside a single one.
3086bool ARMAsmParser::
3087cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3088 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3089 // The second source operand must be the same register as the destination
3090 // operand.
3091 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003092 (((ARMOperand*)Operands[3])->getReg() !=
3093 ((ARMOperand*)Operands[5])->getReg()) &&
3094 (((ARMOperand*)Operands[3])->getReg() !=
3095 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003096 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003097 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003098 return false;
3099 }
3100 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3101 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3102 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003103 // If we have a three-operand form, use that, else the second source operand
3104 // is just the destination operand again.
3105 if (Operands.size() == 6)
3106 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3107 else
3108 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003109 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3110
3111 return true;
3112}
Jim Grosbach623a4542011-08-10 22:42:16 +00003113
Bill Wendlinge7176102010-11-06 22:36:58 +00003114/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003115/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003116bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003117parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003118 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003119 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003120 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003121 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003122 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003123
Sean Callanan18b83232010-01-19 21:44:56 +00003124 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003125 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003126 if (BaseRegNum == -1)
3127 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003128
Daniel Dunbar05710932011-01-18 05:34:17 +00003129 // The next token must either be a comma or a closing bracket.
3130 const AsmToken &Tok = Parser.getTok();
3131 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003132 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003133
Jim Grosbach7ce05792011-08-03 23:50:40 +00003134 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003135 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003136 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003137
Jim Grosbach7ce05792011-08-03 23:50:40 +00003138 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003139 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003140
Jim Grosbachfb12f352011-09-19 18:42:21 +00003141 // If there's a pre-indexing writeback marker, '!', just add it as a token
3142 // operand. It's rather odd, but syntactically valid.
3143 if (Parser.getTok().is(AsmToken::Exclaim)) {
3144 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3145 Parser.Lex(); // Eat the '!'.
3146 }
3147
Jim Grosbach7ce05792011-08-03 23:50:40 +00003148 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003149 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003150
Jim Grosbach7ce05792011-08-03 23:50:40 +00003151 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3152 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003153
Jim Grosbach57dcb852011-10-11 17:29:55 +00003154 // If we have a ':', it's an alignment specifier.
3155 if (Parser.getTok().is(AsmToken::Colon)) {
3156 Parser.Lex(); // Eat the ':'.
3157 E = Parser.getTok().getLoc();
3158
3159 const MCExpr *Expr;
3160 if (getParser().ParseExpression(Expr))
3161 return true;
3162
3163 // The expression has to be a constant. Memory references with relocations
3164 // don't come through here, as they use the <label> forms of the relevant
3165 // instructions.
3166 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3167 if (!CE)
3168 return Error (E, "constant expression expected");
3169
3170 unsigned Align = 0;
3171 switch (CE->getValue()) {
3172 default:
3173 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3174 case 64: Align = 8; break;
3175 case 128: Align = 16; break;
3176 case 256: Align = 32; break;
3177 }
3178
3179 // Now we should have the closing ']'
3180 E = Parser.getTok().getLoc();
3181 if (Parser.getTok().isNot(AsmToken::RBrac))
3182 return Error(E, "']' expected");
3183 Parser.Lex(); // Eat right bracket token.
3184
3185 // Don't worry about range checking the value here. That's handled by
3186 // the is*() predicates.
3187 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3188 ARM_AM::no_shift, 0, Align,
3189 false, S, E));
3190
3191 // If there's a pre-indexing writeback marker, '!', just add it as a token
3192 // operand.
3193 if (Parser.getTok().is(AsmToken::Exclaim)) {
3194 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3195 Parser.Lex(); // Eat the '!'.
3196 }
3197
3198 return false;
3199 }
3200
3201 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003202 // offset.
3203 if (Parser.getTok().is(AsmToken::Hash)) {
3204 Parser.Lex(); // Eat the '#'.
3205 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003206
Owen Anderson0da10cf2011-08-29 19:36:44 +00003207 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003208 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003209 if (getParser().ParseExpression(Offset))
3210 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003211
3212 // The expression has to be a constant. Memory references with relocations
3213 // don't come through here, as they use the <label> forms of the relevant
3214 // instructions.
3215 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3216 if (!CE)
3217 return Error (E, "constant expression expected");
3218
Owen Anderson0da10cf2011-08-29 19:36:44 +00003219 // If the constant was #-0, represent it as INT32_MIN.
3220 int32_t Val = CE->getValue();
3221 if (isNegative && Val == 0)
3222 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3223
Jim Grosbach7ce05792011-08-03 23:50:40 +00003224 // Now we should have the closing ']'
3225 E = Parser.getTok().getLoc();
3226 if (Parser.getTok().isNot(AsmToken::RBrac))
3227 return Error(E, "']' expected");
3228 Parser.Lex(); // Eat right bracket token.
3229
3230 // Don't worry about range checking the value here. That's handled by
3231 // the is*() predicates.
3232 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003233 ARM_AM::no_shift, 0, 0,
3234 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003235
3236 // If there's a pre-indexing writeback marker, '!', just add it as a token
3237 // operand.
3238 if (Parser.getTok().is(AsmToken::Exclaim)) {
3239 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3240 Parser.Lex(); // Eat the '!'.
3241 }
3242
3243 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003244 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003245
3246 // The register offset is optionally preceded by a '+' or '-'
3247 bool isNegative = false;
3248 if (Parser.getTok().is(AsmToken::Minus)) {
3249 isNegative = true;
3250 Parser.Lex(); // Eat the '-'.
3251 } else if (Parser.getTok().is(AsmToken::Plus)) {
3252 // Nothing to do.
3253 Parser.Lex(); // Eat the '+'.
3254 }
3255
3256 E = Parser.getTok().getLoc();
3257 int OffsetRegNum = tryParseRegister();
3258 if (OffsetRegNum == -1)
3259 return Error(E, "register expected");
3260
3261 // If there's a shift operator, handle it.
3262 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003263 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003264 if (Parser.getTok().is(AsmToken::Comma)) {
3265 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003266 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003267 return true;
3268 }
3269
3270 // Now we should have the closing ']'
3271 E = Parser.getTok().getLoc();
3272 if (Parser.getTok().isNot(AsmToken::RBrac))
3273 return Error(E, "']' expected");
3274 Parser.Lex(); // Eat right bracket token.
3275
3276 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003277 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003278 S, E));
3279
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003280 // If there's a pre-indexing writeback marker, '!', just add it as a token
3281 // operand.
3282 if (Parser.getTok().is(AsmToken::Exclaim)) {
3283 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3284 Parser.Lex(); // Eat the '!'.
3285 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003286
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003287 return false;
3288}
3289
Jim Grosbach7ce05792011-08-03 23:50:40 +00003290/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003291/// ( lsl | lsr | asr | ror ) , # shift_amount
3292/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003293/// return true if it parses a shift otherwise it returns false.
3294bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3295 unsigned &Amount) {
3296 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003297 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003298 if (Tok.isNot(AsmToken::Identifier))
3299 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003300 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003301 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003302 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003303 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003304 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003305 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003306 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003307 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003308 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003309 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003310 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003311 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003312 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003313 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003314
Jim Grosbach7ce05792011-08-03 23:50:40 +00003315 // rrx stands alone.
3316 Amount = 0;
3317 if (St != ARM_AM::rrx) {
3318 Loc = Parser.getTok().getLoc();
3319 // A '#' and a shift amount.
3320 const AsmToken &HashTok = Parser.getTok();
3321 if (HashTok.isNot(AsmToken::Hash))
3322 return Error(HashTok.getLoc(), "'#' expected");
3323 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003324
Jim Grosbach7ce05792011-08-03 23:50:40 +00003325 const MCExpr *Expr;
3326 if (getParser().ParseExpression(Expr))
3327 return true;
3328 // Range check the immediate.
3329 // lsl, ror: 0 <= imm <= 31
3330 // lsr, asr: 0 <= imm <= 32
3331 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3332 if (!CE)
3333 return Error(Loc, "shift amount must be an immediate");
3334 int64_t Imm = CE->getValue();
3335 if (Imm < 0 ||
3336 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3337 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3338 return Error(Loc, "immediate shift value out of range");
3339 Amount = Imm;
3340 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003341
3342 return false;
3343}
3344
Jim Grosbach9d390362011-10-03 23:38:36 +00003345/// parseFPImm - A floating point immediate expression operand.
3346ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3347parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3348 SMLoc S = Parser.getTok().getLoc();
3349
3350 if (Parser.getTok().isNot(AsmToken::Hash))
3351 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003352
3353 // Disambiguate the VMOV forms that can accept an FP immediate.
3354 // vmov.f32 <sreg>, #imm
3355 // vmov.f64 <dreg>, #imm
3356 // vmov.f32 <dreg>, #imm @ vector f32x2
3357 // vmov.f32 <qreg>, #imm @ vector f32x4
3358 //
3359 // There are also the NEON VMOV instructions which expect an
3360 // integer constant. Make sure we don't try to parse an FPImm
3361 // for these:
3362 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3363 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3364 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3365 TyOp->getToken() != ".f64"))
3366 return MatchOperand_NoMatch;
3367
Jim Grosbach9d390362011-10-03 23:38:36 +00003368 Parser.Lex(); // Eat the '#'.
3369
3370 // Handle negation, as that still comes through as a separate token.
3371 bool isNegative = false;
3372 if (Parser.getTok().is(AsmToken::Minus)) {
3373 isNegative = true;
3374 Parser.Lex();
3375 }
3376 const AsmToken &Tok = Parser.getTok();
3377 if (Tok.is(AsmToken::Real)) {
3378 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3379 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3380 // If we had a '-' in front, toggle the sign bit.
3381 IntVal ^= (uint64_t)isNegative << 63;
3382 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3383 Parser.Lex(); // Eat the token.
3384 if (Val == -1) {
3385 TokError("floating point value out of range");
3386 return MatchOperand_ParseFail;
3387 }
3388 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3389 return MatchOperand_Success;
3390 }
3391 if (Tok.is(AsmToken::Integer)) {
3392 int64_t Val = Tok.getIntVal();
3393 Parser.Lex(); // Eat the token.
3394 if (Val > 255 || Val < 0) {
3395 TokError("encoded floating point value out of range");
3396 return MatchOperand_ParseFail;
3397 }
3398 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3399 return MatchOperand_Success;
3400 }
3401
3402 TokError("invalid floating point immediate");
3403 return MatchOperand_ParseFail;
3404}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003405/// Parse a arm instruction operand. For now this parses the operand regardless
3406/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003407bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003408 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003409 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003410
3411 // Check if the current operand has a custom associated parser, if so, try to
3412 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003413 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3414 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003415 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003416 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3417 // there was a match, but an error occurred, in which case, just return that
3418 // the operand parsing failed.
3419 if (ResTy == MatchOperand_ParseFail)
3420 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003421
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003422 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003423 default:
3424 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003425 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003426 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003427 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003428 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003429 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003430 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003431 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003432 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003433 else if (Res == -1) // irrecoverable error
3434 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003435 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3436 S = Parser.getTok().getLoc();
3437 Parser.Lex();
3438 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3439 return false;
3440 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003441
3442 // Fall though for the Identifier case that is not a register or a
3443 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003444 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003445 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3446 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003447 // This was not a register so parse other operands that start with an
3448 // identifier (like labels) as expressions and create them as immediates.
3449 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003450 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003451 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003452 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003453 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003454 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3455 return false;
3456 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003457 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003458 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003459 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003460 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003461 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003462 // #42 -> immediate.
3463 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003464 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003465 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003466 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003467 const MCExpr *ImmVal;
3468 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003469 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003470 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3471 if (!CE) {
3472 Error(S, "constant expression expected");
3473 return MatchOperand_ParseFail;
3474 }
3475 int32_t Val = CE->getValue();
3476 if (isNegative && Val == 0)
3477 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003478 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003479 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3480 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003481 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003482 case AsmToken::Colon: {
3483 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003484 // FIXME: Check it's an expression prefix,
3485 // e.g. (FOO - :lower16:BAR) isn't legal.
3486 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003487 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003488 return true;
3489
Evan Cheng75972122011-01-13 07:58:56 +00003490 const MCExpr *SubExprVal;
3491 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003492 return true;
3493
Evan Cheng75972122011-01-13 07:58:56 +00003494 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3495 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003496 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003497 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003498 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003499 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003500 }
3501}
3502
Jim Grosbach1355cf12011-07-26 17:10:22 +00003503// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003504// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003505bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003506 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003507
3508 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003509 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003510 Parser.Lex(); // Eat ':'
3511
3512 if (getLexer().isNot(AsmToken::Identifier)) {
3513 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3514 return true;
3515 }
3516
3517 StringRef IDVal = Parser.getTok().getIdentifier();
3518 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003519 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003520 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003521 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003522 } else {
3523 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3524 return true;
3525 }
3526 Parser.Lex();
3527
3528 if (getLexer().isNot(AsmToken::Colon)) {
3529 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3530 return true;
3531 }
3532 Parser.Lex(); // Eat the last ':'
3533 return false;
3534}
3535
Daniel Dunbar352e1482011-01-11 15:59:50 +00003536/// \brief Given a mnemonic, split out possible predication code and carry
3537/// setting letters to form a canonical mnemonic and flags.
3538//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003539// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003540// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003541StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003542 unsigned &PredicationCode,
3543 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003544 unsigned &ProcessorIMod,
3545 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003546 PredicationCode = ARMCC::AL;
3547 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003548 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003549
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003550 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003551 //
3552 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003553 if ((Mnemonic == "movs" && isThumb()) ||
3554 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3555 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3556 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3557 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3558 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3559 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3560 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003561 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003562
Jim Grosbach3f00e312011-07-11 17:09:57 +00003563 // First, split out any predication code. Ignore mnemonics we know aren't
3564 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003565 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003566 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003567 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003568 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003569 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3570 .Case("eq", ARMCC::EQ)
3571 .Case("ne", ARMCC::NE)
3572 .Case("hs", ARMCC::HS)
3573 .Case("cs", ARMCC::HS)
3574 .Case("lo", ARMCC::LO)
3575 .Case("cc", ARMCC::LO)
3576 .Case("mi", ARMCC::MI)
3577 .Case("pl", ARMCC::PL)
3578 .Case("vs", ARMCC::VS)
3579 .Case("vc", ARMCC::VC)
3580 .Case("hi", ARMCC::HI)
3581 .Case("ls", ARMCC::LS)
3582 .Case("ge", ARMCC::GE)
3583 .Case("lt", ARMCC::LT)
3584 .Case("gt", ARMCC::GT)
3585 .Case("le", ARMCC::LE)
3586 .Case("al", ARMCC::AL)
3587 .Default(~0U);
3588 if (CC != ~0U) {
3589 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3590 PredicationCode = CC;
3591 }
Bill Wendling52925b62010-10-29 23:50:21 +00003592 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003593
Daniel Dunbar352e1482011-01-11 15:59:50 +00003594 // Next, determine if we have a carry setting bit. We explicitly ignore all
3595 // the instructions we know end in 's'.
3596 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003597 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003598 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3599 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3600 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003601 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3602 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003603 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3604 CarrySetting = true;
3605 }
3606
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003607 // The "cps" instruction can have a interrupt mode operand which is glued into
3608 // the mnemonic. Check if this is the case, split it and parse the imod op
3609 if (Mnemonic.startswith("cps")) {
3610 // Split out any imod code.
3611 unsigned IMod =
3612 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3613 .Case("ie", ARM_PROC::IE)
3614 .Case("id", ARM_PROC::ID)
3615 .Default(~0U);
3616 if (IMod != ~0U) {
3617 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3618 ProcessorIMod = IMod;
3619 }
3620 }
3621
Jim Grosbach89df9962011-08-26 21:43:41 +00003622 // The "it" instruction has the condition mask on the end of the mnemonic.
3623 if (Mnemonic.startswith("it")) {
3624 ITMask = Mnemonic.slice(2, Mnemonic.size());
3625 Mnemonic = Mnemonic.slice(0, 2);
3626 }
3627
Daniel Dunbar352e1482011-01-11 15:59:50 +00003628 return Mnemonic;
3629}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003630
3631/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3632/// inclusion of carry set or predication code operands.
3633//
3634// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003635void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003636getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003637 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003638 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3639 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003640 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003641 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003642 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003643 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003644 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003645 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003646 Mnemonic == "mla" || Mnemonic == "smlal" ||
3647 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003648 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003649 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003650 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003651
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003652 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3653 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3654 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3655 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003656 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3657 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003658 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003659 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3660 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3661 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003662 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3663 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003664 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003665 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003666 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003667 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003668
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003669 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003670 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003671 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003672 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003673 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003674}
3675
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003676bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3677 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003678 // FIXME: This is all horribly hacky. We really need a better way to deal
3679 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003680
3681 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3682 // another does not. Specifically, the MOVW instruction does not. So we
3683 // special case it here and remove the defaulted (non-setting) cc_out
3684 // operand if that's the instruction we're trying to match.
3685 //
3686 // We do this as post-processing of the explicit operands rather than just
3687 // conditionally adding the cc_out in the first place because we need
3688 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003689 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003690 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3691 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3692 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3693 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003694
3695 // Register-register 'add' for thumb does not have a cc_out operand
3696 // when there are only two register operands.
3697 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3698 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3699 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3700 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3701 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003702 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003703 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3704 // have to check the immediate range here since Thumb2 has a variant
3705 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003706 if (((isThumb() && Mnemonic == "add") ||
3707 (isThumbTwo() && Mnemonic == "sub")) &&
3708 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003709 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3710 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3711 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003712 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3713 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3714 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003715 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003716 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3717 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003718 // selecting via the generic "add" mnemonic, so to know that we
3719 // should remove the cc_out operand, we have to explicitly check that
3720 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003721 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3722 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003723 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3724 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3725 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3726 // Nest conditions rather than one big 'if' statement for readability.
3727 //
3728 // If either register is a high reg, it's either one of the SP
3729 // variants (handled above) or a 32-bit encoding, so we just
3730 // check against T3.
3731 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3732 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3733 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3734 return false;
3735 // If both registers are low, we're in an IT block, and the immediate is
3736 // in range, we should use encoding T1 instead, which has a cc_out.
3737 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003738 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003739 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3740 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3741 return false;
3742
3743 // Otherwise, we use encoding T4, which does not have a cc_out
3744 // operand.
3745 return true;
3746 }
3747
Jim Grosbach64944f42011-09-14 21:00:40 +00003748 // The thumb2 multiply instruction doesn't have a CCOut register, so
3749 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3750 // use the 16-bit encoding or not.
3751 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3752 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3753 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3754 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3755 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3756 // If the registers aren't low regs, the destination reg isn't the
3757 // same as one of the source regs, or the cc_out operand is zero
3758 // outside of an IT block, we have to use the 32-bit encoding, so
3759 // remove the cc_out operand.
3760 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3761 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3762 !inITBlock() ||
3763 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3764 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3765 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3766 static_cast<ARMOperand*>(Operands[4])->getReg())))
3767 return true;
3768
3769
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003770
Jim Grosbachf69c8042011-08-24 21:42:27 +00003771 // Register-register 'add/sub' for thumb does not have a cc_out operand
3772 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3773 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3774 // right, this will result in better diagnostics (which operand is off)
3775 // anyway.
3776 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3777 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003778 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3779 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3780 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3781 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003782
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003783 return false;
3784}
3785
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003786/// Parse an arm instruction mnemonic followed by its operands.
3787bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3788 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3789 // Create the leading tokens for the mnemonic, split by '.' characters.
3790 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003791 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003792
Daniel Dunbar352e1482011-01-11 15:59:50 +00003793 // Split out the predication code and carry setting flag from the mnemonic.
3794 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003795 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003796 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003797 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003798 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003799 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003800
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003801 // In Thumb1, only the branch (B) instruction can be predicated.
3802 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3803 Parser.EatToEndOfStatement();
3804 return Error(NameLoc, "conditional execution not supported in Thumb1");
3805 }
3806
Jim Grosbachffa32252011-07-19 19:13:28 +00003807 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3808
Jim Grosbach89df9962011-08-26 21:43:41 +00003809 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3810 // is the mask as it will be for the IT encoding if the conditional
3811 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3812 // where the conditional bit0 is zero, the instruction post-processing
3813 // will adjust the mask accordingly.
3814 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003815 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3816 if (ITMask.size() > 3) {
3817 Parser.EatToEndOfStatement();
3818 return Error(Loc, "too many conditions on IT instruction");
3819 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003820 unsigned Mask = 8;
3821 for (unsigned i = ITMask.size(); i != 0; --i) {
3822 char pos = ITMask[i - 1];
3823 if (pos != 't' && pos != 'e') {
3824 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003825 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003826 }
3827 Mask >>= 1;
3828 if (ITMask[i - 1] == 't')
3829 Mask |= 8;
3830 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003831 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003832 }
3833
Jim Grosbachffa32252011-07-19 19:13:28 +00003834 // FIXME: This is all a pretty gross hack. We should automatically handle
3835 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003836
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003837 // Next, add the CCOut and ConditionCode operands, if needed.
3838 //
3839 // For mnemonics which can ever incorporate a carry setting bit or predication
3840 // code, our matching model involves us always generating CCOut and
3841 // ConditionCode operands to match the mnemonic "as written" and then we let
3842 // the matcher deal with finding the right instruction or generating an
3843 // appropriate error.
3844 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003845 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003846
Jim Grosbach33c16a22011-07-14 22:04:21 +00003847 // If we had a carry-set on an instruction that can't do that, issue an
3848 // error.
3849 if (!CanAcceptCarrySet && CarrySetting) {
3850 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003851 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003852 "' can not set flags, but 's' suffix specified");
3853 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003854 // If we had a predication code on an instruction that can't do that, issue an
3855 // error.
3856 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3857 Parser.EatToEndOfStatement();
3858 return Error(NameLoc, "instruction '" + Mnemonic +
3859 "' is not predicable, but condition code specified");
3860 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003861
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003862 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003863 if (CanAcceptCarrySet) {
3864 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003865 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003866 Loc));
3867 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003868
3869 // Add the predication code operand, if necessary.
3870 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003871 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3872 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003873 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003874 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003875 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003876
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003877 // Add the processor imod operand, if necessary.
3878 if (ProcessorIMod) {
3879 Operands.push_back(ARMOperand::CreateImm(
3880 MCConstantExpr::Create(ProcessorIMod, getContext()),
3881 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003882 }
3883
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003884 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003885 while (Next != StringRef::npos) {
3886 Start = Next;
3887 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003888 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003889
Jim Grosbach4d23e992011-08-24 22:19:48 +00003890 // For now, we're only parsing Thumb1 (for the most part), so
3891 // just ignore ".n" qualifiers. We'll use them to restrict
3892 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003893 if (ExtraToken != ".n") {
3894 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3895 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3896 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003897 }
3898
3899 // Read the remaining operands.
3900 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003901 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003902 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003903 Parser.EatToEndOfStatement();
3904 return true;
3905 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003906
3907 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003908 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003909
3910 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003911 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003912 Parser.EatToEndOfStatement();
3913 return true;
3914 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003915 }
3916 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003917
Chris Lattnercbf8a982010-09-11 16:18:25 +00003918 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00003919 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00003920 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00003921 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003922 }
Bill Wendling146018f2010-11-06 21:42:12 +00003923
Chris Lattner34e53142010-09-08 05:10:46 +00003924 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003925
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003926 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3927 // do and don't have a cc_out optional-def operand. With some spot-checks
3928 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003929 // parse and adjust accordingly before actually matching. We shouldn't ever
3930 // try to remove a cc_out operand that was explicitly set on the the
3931 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3932 // table driven matcher doesn't fit well with the ARM instruction set.
3933 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003934 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3935 Operands.erase(Operands.begin() + 1);
3936 delete Op;
3937 }
3938
Jim Grosbachcf121c32011-07-28 21:57:55 +00003939 // ARM mode 'blx' need special handling, as the register operand version
3940 // is predicable, but the label operand version is not. So, we can't rely
3941 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00003942 // a k_CondCode operand in the list. If we're trying to match the label
3943 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00003944 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3945 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3946 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3947 Operands.erase(Operands.begin() + 1);
3948 delete Op;
3949 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003950
3951 // The vector-compare-to-zero instructions have a literal token "#0" at
3952 // the end that comes to here as an immediate operand. Convert it to a
3953 // token to play nicely with the matcher.
3954 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3955 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3956 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3957 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3958 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3959 if (CE && CE->getValue() == 0) {
3960 Operands.erase(Operands.begin() + 5);
3961 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3962 delete Op;
3963 }
3964 }
Jim Grosbach68259142011-10-03 22:30:24 +00003965 // VCMP{E} does the same thing, but with a different operand count.
3966 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3967 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3968 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3969 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3970 if (CE && CE->getValue() == 0) {
3971 Operands.erase(Operands.begin() + 4);
3972 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3973 delete Op;
3974 }
3975 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003976 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3977 // end. Convert it to a token here.
3978 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3979 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3980 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3981 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3982 if (CE && CE->getValue() == 0) {
3983 Operands.erase(Operands.begin() + 5);
3984 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3985 delete Op;
3986 }
3987 }
3988
Chris Lattner98986712010-01-14 22:21:20 +00003989 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003990}
3991
Jim Grosbach189610f2011-07-26 18:25:39 +00003992// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003993
3994// return 'true' if register list contains non-low GPR registers,
3995// 'false' otherwise. If Reg is in the register list or is HiReg, set
3996// 'containsReg' to true.
3997static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3998 unsigned HiReg, bool &containsReg) {
3999 containsReg = false;
4000 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4001 unsigned OpReg = Inst.getOperand(i).getReg();
4002 if (OpReg == Reg)
4003 containsReg = true;
4004 // Anything other than a low register isn't legal here.
4005 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4006 return true;
4007 }
4008 return false;
4009}
4010
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004011// Check if the specified regisgter is in the register list of the inst,
4012// starting at the indicated operand number.
4013static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4014 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4015 unsigned OpReg = Inst.getOperand(i).getReg();
4016 if (OpReg == Reg)
4017 return true;
4018 }
4019 return false;
4020}
4021
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004022// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4023// the ARMInsts array) instead. Getting that here requires awkward
4024// API changes, though. Better way?
4025namespace llvm {
4026extern MCInstrDesc ARMInsts[];
4027}
4028static MCInstrDesc &getInstDesc(unsigned Opcode) {
4029 return ARMInsts[Opcode];
4030}
4031
Jim Grosbach189610f2011-07-26 18:25:39 +00004032// FIXME: We would really like to be able to tablegen'erate this.
4033bool ARMAsmParser::
4034validateInstruction(MCInst &Inst,
4035 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004036 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4037 SMLoc Loc = Operands[0]->getStartLoc();
4038 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004039 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4040 // being allowed in IT blocks, but not being predicable. It just always
4041 // executes.
4042 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004043 unsigned bit = 1;
4044 if (ITState.FirstCond)
4045 ITState.FirstCond = false;
4046 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004047 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004048 // The instruction must be predicable.
4049 if (!MCID.isPredicable())
4050 return Error(Loc, "instructions in IT block must be predicable");
4051 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4052 unsigned ITCond = bit ? ITState.Cond :
4053 ARMCC::getOppositeCondition(ITState.Cond);
4054 if (Cond != ITCond) {
4055 // Find the condition code Operand to get its SMLoc information.
4056 SMLoc CondLoc;
4057 for (unsigned i = 1; i < Operands.size(); ++i)
4058 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4059 CondLoc = Operands[i]->getStartLoc();
4060 return Error(CondLoc, "incorrect condition in IT block; got '" +
4061 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4062 "', but expected '" +
4063 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4064 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004065 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004066 } else if (isThumbTwo() && MCID.isPredicable() &&
4067 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004068 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4069 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004070 return Error(Loc, "predicated instructions must be in IT block");
4071
Jim Grosbach189610f2011-07-26 18:25:39 +00004072 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004073 case ARM::LDRD:
4074 case ARM::LDRD_PRE:
4075 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004076 case ARM::LDREXD: {
4077 // Rt2 must be Rt + 1.
4078 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4079 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4080 if (Rt2 != Rt + 1)
4081 return Error(Operands[3]->getStartLoc(),
4082 "destination operands must be sequential");
4083 return false;
4084 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004085 case ARM::STRD: {
4086 // Rt2 must be Rt + 1.
4087 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4088 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4089 if (Rt2 != Rt + 1)
4090 return Error(Operands[3]->getStartLoc(),
4091 "source operands must be sequential");
4092 return false;
4093 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004094 case ARM::STRD_PRE:
4095 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004096 case ARM::STREXD: {
4097 // Rt2 must be Rt + 1.
4098 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4099 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4100 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004101 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004102 "source operands must be sequential");
4103 return false;
4104 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004105 case ARM::SBFX:
4106 case ARM::UBFX: {
4107 // width must be in range [1, 32-lsb]
4108 unsigned lsb = Inst.getOperand(2).getImm();
4109 unsigned widthm1 = Inst.getOperand(3).getImm();
4110 if (widthm1 >= 32 - lsb)
4111 return Error(Operands[5]->getStartLoc(),
4112 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004113 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004114 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004115 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004116 // If we're parsing Thumb2, the .w variant is available and handles
4117 // most cases that are normally illegal for a Thumb1 LDM
4118 // instruction. We'll make the transformation in processInstruction()
4119 // if necessary.
4120 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004121 // Thumb LDM instructions are writeback iff the base register is not
4122 // in the register list.
4123 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004124 bool hasWritebackToken =
4125 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4126 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004127 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004128 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004129 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4130 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004131 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004132 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004133 return Error(Operands[2]->getStartLoc(),
4134 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004135 // If we should not have writeback, there must not be a '!'. This is
4136 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004137 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004138 return Error(Operands[3]->getStartLoc(),
4139 "writeback operator '!' not allowed when base register "
4140 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004141
4142 break;
4143 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004144 case ARM::t2LDMIA_UPD: {
4145 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4146 return Error(Operands[4]->getStartLoc(),
4147 "writeback operator '!' not allowed when base register "
4148 "in register list");
4149 break;
4150 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004151 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004152 bool listContainsBase;
4153 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4154 return Error(Operands[2]->getStartLoc(),
4155 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004156 break;
4157 }
4158 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004159 bool listContainsBase;
4160 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4161 return Error(Operands[2]->getStartLoc(),
4162 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004163 break;
4164 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004165 case ARM::tSTMIA_UPD: {
4166 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004167 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004168 return Error(Operands[4]->getStartLoc(),
4169 "registers must be in range r0-r7");
4170 break;
4171 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004172 }
4173
4174 return false;
4175}
4176
Jim Grosbachf8fce712011-08-11 17:35:48 +00004177void ARMAsmParser::
4178processInstruction(MCInst &Inst,
4179 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4180 switch (Inst.getOpcode()) {
4181 case ARM::LDMIA_UPD:
4182 // If this is a load of a single register via a 'pop', then we should use
4183 // a post-indexed LDR instruction instead, per the ARM ARM.
4184 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4185 Inst.getNumOperands() == 5) {
4186 MCInst TmpInst;
4187 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4188 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4189 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4190 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4191 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4192 TmpInst.addOperand(MCOperand::CreateImm(4));
4193 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4194 TmpInst.addOperand(Inst.getOperand(3));
4195 Inst = TmpInst;
4196 }
4197 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004198 case ARM::STMDB_UPD:
4199 // If this is a store of a single register via a 'push', then we should use
4200 // a pre-indexed STR instruction instead, per the ARM ARM.
4201 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4202 Inst.getNumOperands() == 5) {
4203 MCInst TmpInst;
4204 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4205 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4206 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4207 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4208 TmpInst.addOperand(MCOperand::CreateImm(-4));
4209 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4210 TmpInst.addOperand(Inst.getOperand(3));
4211 Inst = TmpInst;
4212 }
4213 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004214 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004215 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4216 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4217 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4218 // to encoding T1 if <Rd> is omitted."
4219 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004220 Inst.setOpcode(ARM::tADDi3);
4221 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004222 case ARM::tSUBi8:
4223 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4224 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4225 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4226 // to encoding T1 if <Rd> is omitted."
4227 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4228 Inst.setOpcode(ARM::tSUBi3);
4229 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004230 case ARM::tB:
4231 // A Thumb conditional branch outside of an IT block is a tBcc.
4232 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4233 Inst.setOpcode(ARM::tBcc);
4234 break;
4235 case ARM::t2B:
4236 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4237 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4238 Inst.setOpcode(ARM::t2Bcc);
4239 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004240 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004241 // If the conditional is AL or we're in an IT block, we really want t2B.
4242 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004243 Inst.setOpcode(ARM::t2B);
4244 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004245 case ARM::tBcc:
4246 // If the conditional is AL, we really want tB.
4247 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4248 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004249 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004250 case ARM::tLDMIA: {
4251 // If the register list contains any high registers, or if the writeback
4252 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4253 // instead if we're in Thumb2. Otherwise, this should have generated
4254 // an error in validateInstruction().
4255 unsigned Rn = Inst.getOperand(0).getReg();
4256 bool hasWritebackToken =
4257 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4258 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4259 bool listContainsBase;
4260 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4261 (!listContainsBase && !hasWritebackToken) ||
4262 (listContainsBase && hasWritebackToken)) {
4263 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4264 assert (isThumbTwo());
4265 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4266 // If we're switching to the updating version, we need to insert
4267 // the writeback tied operand.
4268 if (hasWritebackToken)
4269 Inst.insert(Inst.begin(),
4270 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4271 }
4272 break;
4273 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004274 case ARM::tSTMIA_UPD: {
4275 // If the register list contains any high registers, we need to use
4276 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4277 // should have generated an error in validateInstruction().
4278 unsigned Rn = Inst.getOperand(0).getReg();
4279 bool listContainsBase;
4280 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4281 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4282 assert (isThumbTwo());
4283 Inst.setOpcode(ARM::t2STMIA_UPD);
4284 }
4285 break;
4286 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004287 case ARM::t2MOVi: {
4288 // If we can use the 16-bit encoding and the user didn't explicitly
4289 // request the 32-bit variant, transform it here.
4290 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4291 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004292 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4293 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4294 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004295 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4296 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4297 // The operands aren't in the same order for tMOVi8...
4298 MCInst TmpInst;
4299 TmpInst.setOpcode(ARM::tMOVi8);
4300 TmpInst.addOperand(Inst.getOperand(0));
4301 TmpInst.addOperand(Inst.getOperand(4));
4302 TmpInst.addOperand(Inst.getOperand(1));
4303 TmpInst.addOperand(Inst.getOperand(2));
4304 TmpInst.addOperand(Inst.getOperand(3));
4305 Inst = TmpInst;
4306 }
4307 break;
4308 }
4309 case ARM::t2MOVr: {
4310 // If we can use the 16-bit encoding and the user didn't explicitly
4311 // request the 32-bit variant, transform it here.
4312 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4313 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4314 Inst.getOperand(2).getImm() == ARMCC::AL &&
4315 Inst.getOperand(4).getReg() == ARM::CPSR &&
4316 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4317 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4318 // The operands aren't the same for tMOV[S]r... (no cc_out)
4319 MCInst TmpInst;
4320 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4321 TmpInst.addOperand(Inst.getOperand(0));
4322 TmpInst.addOperand(Inst.getOperand(1));
4323 TmpInst.addOperand(Inst.getOperand(2));
4324 TmpInst.addOperand(Inst.getOperand(3));
4325 Inst = TmpInst;
4326 }
4327 break;
4328 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004329 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004330 case ARM::t2SXTB:
4331 case ARM::t2UXTH:
4332 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004333 // If we can use the 16-bit encoding and the user didn't explicitly
4334 // request the 32-bit variant, transform it here.
4335 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4336 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4337 Inst.getOperand(2).getImm() == 0 &&
4338 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4339 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004340 unsigned NewOpc;
4341 switch (Inst.getOpcode()) {
4342 default: llvm_unreachable("Illegal opcode!");
4343 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4344 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4345 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4346 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4347 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004348 // The operands aren't the same for thumb1 (no rotate operand).
4349 MCInst TmpInst;
4350 TmpInst.setOpcode(NewOpc);
4351 TmpInst.addOperand(Inst.getOperand(0));
4352 TmpInst.addOperand(Inst.getOperand(1));
4353 TmpInst.addOperand(Inst.getOperand(3));
4354 TmpInst.addOperand(Inst.getOperand(4));
4355 Inst = TmpInst;
4356 }
4357 break;
4358 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004359 case ARM::t2IT: {
4360 // The mask bits for all but the first condition are represented as
4361 // the low bit of the condition code value implies 't'. We currently
4362 // always have 1 implies 't', so XOR toggle the bits if the low bit
4363 // of the condition code is zero. The encoding also expects the low
4364 // bit of the condition to be encoded as bit 4 of the mask operand,
4365 // so mask that in if needed
4366 MCOperand &MO = Inst.getOperand(1);
4367 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004368 unsigned OrigMask = Mask;
4369 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004370 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004371 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4372 for (unsigned i = 3; i != TZ; --i)
4373 Mask ^= 1 << i;
4374 } else
4375 Mask |= 0x10;
4376 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004377
4378 // Set up the IT block state according to the IT instruction we just
4379 // matched.
4380 assert(!inITBlock() && "nested IT blocks?!");
4381 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4382 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4383 ITState.CurPosition = 0;
4384 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004385 break;
4386 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004387 }
4388}
4389
Jim Grosbach47a0d522011-08-16 20:45:50 +00004390unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4391 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4392 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004393 unsigned Opc = Inst.getOpcode();
4394 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004395 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4396 assert(MCID.hasOptionalDef() &&
4397 "optionally flag setting instruction missing optional def operand");
4398 assert(MCID.NumOperands == Inst.getNumOperands() &&
4399 "operand count mismatch!");
4400 // Find the optional-def operand (cc_out).
4401 unsigned OpNo;
4402 for (OpNo = 0;
4403 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4404 ++OpNo)
4405 ;
4406 // If we're parsing Thumb1, reject it completely.
4407 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4408 return Match_MnemonicFail;
4409 // If we're parsing Thumb2, which form is legal depends on whether we're
4410 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004411 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4412 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004413 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004414 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4415 inITBlock())
4416 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004417 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004418 // Some high-register supporting Thumb1 encodings only allow both registers
4419 // to be from r0-r7 when in Thumb2.
4420 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4421 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4422 isARMLowRegister(Inst.getOperand(2).getReg()))
4423 return Match_RequiresThumb2;
4424 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004425 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004426 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4427 isARMLowRegister(Inst.getOperand(1).getReg()))
4428 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004429 return Match_Success;
4430}
4431
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004432bool ARMAsmParser::
4433MatchAndEmitInstruction(SMLoc IDLoc,
4434 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4435 MCStreamer &Out) {
4436 MCInst Inst;
4437 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004438 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004439 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004440 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004441 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004442 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004443 // Context sensitive operand constraints aren't handled by the matcher,
4444 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004445 if (validateInstruction(Inst, Operands)) {
4446 // Still progress the IT block, otherwise one wrong condition causes
4447 // nasty cascading errors.
4448 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004449 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004450 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004451
Jim Grosbachf8fce712011-08-11 17:35:48 +00004452 // Some instructions need post-processing to, for example, tweak which
4453 // encoding is selected.
4454 processInstruction(Inst, Operands);
4455
Jim Grosbacha1109882011-09-02 23:22:08 +00004456 // Only move forward at the very end so that everything in validate
4457 // and process gets a consistent answer about whether we're in an IT
4458 // block.
4459 forwardITPosition();
4460
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004461 Out.EmitInstruction(Inst);
4462 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004463 case Match_MissingFeature:
4464 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4465 return true;
4466 case Match_InvalidOperand: {
4467 SMLoc ErrorLoc = IDLoc;
4468 if (ErrorInfo != ~0U) {
4469 if (ErrorInfo >= Operands.size())
4470 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004471
Chris Lattnere73d4f82010-10-28 21:41:58 +00004472 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4473 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4474 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004475
Chris Lattnere73d4f82010-10-28 21:41:58 +00004476 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004477 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004478 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004479 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004480 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004481 // The converter function will have already emited a diagnostic.
4482 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004483 case Match_RequiresNotITBlock:
4484 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004485 case Match_RequiresITBlock:
4486 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004487 case Match_RequiresV6:
4488 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4489 case Match_RequiresThumb2:
4490 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004491 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004492
Eric Christopherc223e2b2010-10-29 09:26:59 +00004493 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004494 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004495}
4496
Jim Grosbach1355cf12011-07-26 17:10:22 +00004497/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004498bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4499 StringRef IDVal = DirectiveID.getIdentifier();
4500 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004501 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004502 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004503 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004504 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004505 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004506 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004507 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004508 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004509 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004510 return true;
4511}
4512
Jim Grosbach1355cf12011-07-26 17:10:22 +00004513/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004514/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004515bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004516 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4517 for (;;) {
4518 const MCExpr *Value;
4519 if (getParser().ParseExpression(Value))
4520 return true;
4521
Chris Lattneraaec2052010-01-19 19:46:13 +00004522 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004523
4524 if (getLexer().is(AsmToken::EndOfStatement))
4525 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004526
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004527 // FIXME: Improve diagnostic.
4528 if (getLexer().isNot(AsmToken::Comma))
4529 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004530 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004531 }
4532 }
4533
Sean Callananb9a25b72010-01-19 20:27:46 +00004534 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004535 return false;
4536}
4537
Jim Grosbach1355cf12011-07-26 17:10:22 +00004538/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004539/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004540bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004541 if (getLexer().isNot(AsmToken::EndOfStatement))
4542 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004543 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004544
4545 // TODO: set thumb mode
4546 // TODO: tell the MC streamer the mode
4547 // getParser().getStreamer().Emit???();
4548 return false;
4549}
4550
Jim Grosbach1355cf12011-07-26 17:10:22 +00004551/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004552/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004553bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004554 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4555 bool isMachO = MAI.hasSubsectionsViaSymbols();
4556 StringRef Name;
4557
4558 // Darwin asm has function name after .thumb_func direction
4559 // ELF doesn't
4560 if (isMachO) {
4561 const AsmToken &Tok = Parser.getTok();
4562 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4563 return Error(L, "unexpected token in .thumb_func directive");
4564 Name = Tok.getString();
4565 Parser.Lex(); // Consume the identifier token.
4566 }
4567
Kevin Enderby515d5092009-10-15 20:48:48 +00004568 if (getLexer().isNot(AsmToken::EndOfStatement))
4569 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004570 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004571
Rafael Espindola64695402011-05-16 16:17:21 +00004572 // FIXME: assuming function name will be the line following .thumb_func
4573 if (!isMachO) {
4574 Name = Parser.getTok().getString();
4575 }
4576
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004577 // Mark symbol as a thumb symbol.
4578 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4579 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004580 return false;
4581}
4582
Jim Grosbach1355cf12011-07-26 17:10:22 +00004583/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004584/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004585bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004586 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004587 if (Tok.isNot(AsmToken::Identifier))
4588 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004589 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004590 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004591 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004592 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004593 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004594 else
4595 return Error(L, "unrecognized syntax mode in .syntax directive");
4596
4597 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004598 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004599 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004600
4601 // TODO tell the MC streamer the mode
4602 // getParser().getStreamer().Emit???();
4603 return false;
4604}
4605
Jim Grosbach1355cf12011-07-26 17:10:22 +00004606/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004607/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004608bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004609 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004610 if (Tok.isNot(AsmToken::Integer))
4611 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004612 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004613 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004614 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004615 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004616 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004617 else
4618 return Error(L, "invalid operand to .code directive");
4619
4620 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004621 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004622 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004623
Evan Cheng32869202011-07-08 22:36:29 +00004624 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004625 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004626 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004627 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004628 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004629 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004630 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004631 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004632 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004633
Kevin Enderby515d5092009-10-15 20:48:48 +00004634 return false;
4635}
4636
Sean Callanan90b70972010-04-07 20:29:34 +00004637extern "C" void LLVMInitializeARMAsmLexer();
4638
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004639/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004640extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004641 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4642 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004643 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004644}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004645
Chris Lattner0692ee62010-09-06 19:11:01 +00004646#define GET_REGISTER_MATCHER
4647#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004648#include "ARMGenAsmMatcher.inc"