blob: 3ce086a04919acf12672f633f9998c7cc27afc1d [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 Grosbach460a9052011-10-07 23:56:00 +0000901 bool isVectorIndex8() const {
902 if (Kind != k_VectorIndex) return false;
903 return VectorIndex.Val < 8;
904 }
905 bool isVectorIndex16() const {
906 if (Kind != k_VectorIndex) return false;
907 return VectorIndex.Val < 4;
908 }
909 bool isVectorIndex32() const {
910 if (Kind != k_VectorIndex) return false;
911 return VectorIndex.Val < 2;
912 }
913
914
915
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000916 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000917 // Add as immediates when possible. Null MCExpr = 0.
918 if (Expr == 0)
919 Inst.addOperand(MCOperand::CreateImm(0));
920 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000921 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
922 else
923 Inst.addOperand(MCOperand::CreateExpr(Expr));
924 }
925
Daniel Dunbar8462b302010-08-11 06:36:53 +0000926 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000927 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000928 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000929 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
930 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000931 }
932
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000933 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 1 && "Invalid number of operands!");
935 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
936 }
937
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000938 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
939 assert(N == 1 && "Invalid number of operands!");
940 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
941 }
942
943 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
944 assert(N == 1 && "Invalid number of operands!");
945 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
946 }
947
Jim Grosbach89df9962011-08-26 21:43:41 +0000948 void addITMaskOperands(MCInst &Inst, unsigned N) const {
949 assert(N == 1 && "Invalid number of operands!");
950 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
951 }
952
953 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
954 assert(N == 1 && "Invalid number of operands!");
955 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
956 }
957
Jim Grosbachd67641b2010-12-06 18:21:12 +0000958 void addCCOutOperands(MCInst &Inst, unsigned N) const {
959 assert(N == 1 && "Invalid number of operands!");
960 Inst.addOperand(MCOperand::CreateReg(getReg()));
961 }
962
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000963 void addRegOperands(MCInst &Inst, unsigned N) const {
964 assert(N == 1 && "Invalid number of operands!");
965 Inst.addOperand(MCOperand::CreateReg(getReg()));
966 }
967
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000968 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000969 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000970 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
971 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
972 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000973 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000974 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000975 }
976
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000977 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000978 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000979 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
980 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000981 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000982 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000983 }
984
Jim Grosbach580f4a92011-07-25 22:20:28 +0000985 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000986 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000987 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
988 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +0000989 }
990
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000991 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +0000992 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +0000993 const SmallVectorImpl<unsigned> &RegList = getRegList();
994 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +0000995 I = RegList.begin(), E = RegList.end(); I != E; ++I)
996 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000997 }
998
Bill Wendling0f630752010-11-17 04:32:08 +0000999 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1000 addRegListOperands(Inst, N);
1001 }
1002
1003 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1004 addRegListOperands(Inst, N);
1005 }
1006
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001007 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1008 assert(N == 1 && "Invalid number of operands!");
1009 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1010 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1011 }
1012
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001013 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1014 assert(N == 1 && "Invalid number of operands!");
1015 // Munge the lsb/width into a bitfield mask.
1016 unsigned lsb = Bitfield.LSB;
1017 unsigned width = Bitfield.Width;
1018 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1019 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1020 (32 - (lsb + width)));
1021 Inst.addOperand(MCOperand::CreateImm(Mask));
1022 }
1023
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001024 void addImmOperands(MCInst &Inst, unsigned N) const {
1025 assert(N == 1 && "Invalid number of operands!");
1026 addExpr(Inst, getImm());
1027 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001028
Jim Grosbach9d390362011-10-03 23:38:36 +00001029 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1030 assert(N == 1 && "Invalid number of operands!");
1031 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1032 }
1033
Jim Grosbacha77295d2011-09-08 22:07:06 +00001034 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1035 assert(N == 1 && "Invalid number of operands!");
1036 // FIXME: We really want to scale the value here, but the LDRD/STRD
1037 // instruction don't encode operands that way yet.
1038 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1039 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1040 }
1041
Jim Grosbach72f39f82011-08-24 21:22:15 +00001042 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1043 assert(N == 1 && "Invalid number of operands!");
1044 // The immediate is scaled by four in the encoding and is stored
1045 // in the MCInst as such. Lop off the low two bits here.
1046 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1047 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1048 }
1049
1050 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1051 assert(N == 1 && "Invalid number of operands!");
1052 // The immediate is scaled by four in the encoding and is stored
1053 // in the MCInst as such. Lop off the low two bits here.
1054 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1055 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1056 }
1057
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001058 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1059 assert(N == 1 && "Invalid number of operands!");
1060 addExpr(Inst, getImm());
1061 }
1062
Jim Grosbach83ab0702011-07-13 22:01:08 +00001063 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1064 assert(N == 1 && "Invalid number of operands!");
1065 addExpr(Inst, getImm());
1066 }
1067
1068 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070 addExpr(Inst, getImm());
1071 }
1072
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001073 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 addExpr(Inst, getImm());
1076 }
1077
Jim Grosbachf4943352011-07-25 23:09:14 +00001078 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1079 assert(N == 1 && "Invalid number of operands!");
1080 // The constant encodes as the immediate-1, and we store in the instruction
1081 // the bits as encoded, so subtract off one here.
1082 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1083 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1084 }
1085
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001086 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1087 assert(N == 1 && "Invalid number of operands!");
1088 // The constant encodes as the immediate-1, and we store in the instruction
1089 // the bits as encoded, so subtract off one here.
1090 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1091 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1092 }
1093
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001094 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!");
1096 addExpr(Inst, getImm());
1097 }
1098
Jim Grosbachffa32252011-07-19 19:13:28 +00001099 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1100 assert(N == 1 && "Invalid number of operands!");
1101 addExpr(Inst, getImm());
1102 }
1103
Jim Grosbached838482011-07-26 16:24:27 +00001104 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1105 assert(N == 1 && "Invalid number of operands!");
1106 addExpr(Inst, getImm());
1107 }
1108
Jim Grosbach70939ee2011-08-17 21:51:27 +00001109 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1110 assert(N == 1 && "Invalid number of operands!");
1111 // The constant encodes as the immediate, except for 32, which encodes as
1112 // zero.
1113 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1114 unsigned Imm = CE->getValue();
1115 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1116 }
1117
Jim Grosbachf6c05252011-07-21 17:23:04 +00001118 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1119 assert(N == 1 && "Invalid number of operands!");
1120 addExpr(Inst, getImm());
1121 }
1122
1123 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1124 assert(N == 1 && "Invalid number of operands!");
1125 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1126 // the instruction as well.
1127 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1128 int Val = CE->getValue();
1129 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1130 }
1131
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001132 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1133 assert(N == 1 && "Invalid number of operands!");
1134 addExpr(Inst, getImm());
1135 }
1136
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001137 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1138 assert(N == 1 && "Invalid number of operands!");
1139 addExpr(Inst, getImm());
1140 }
1141
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001142 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1143 assert(N == 1 && "Invalid number of operands!");
1144 addExpr(Inst, getImm());
1145 }
1146
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001147 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1148 assert(N == 1 && "Invalid number of operands!");
1149 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1150 }
1151
Jim Grosbach7ce05792011-08-03 23:50:40 +00001152 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1153 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001154 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001155 }
1156
Jim Grosbach57dcb852011-10-11 17:29:55 +00001157 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1158 assert(N == 2 && "Invalid number of operands!");
1159 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1160 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1161 }
1162
Jim Grosbach7ce05792011-08-03 23:50:40 +00001163 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1164 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001165 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1166 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001167 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1168 // Special case for #-0
1169 if (Val == INT32_MIN) Val = 0;
1170 if (Val < 0) Val = -Val;
1171 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1172 } else {
1173 // For register offset, we encode the shift type and negation flag
1174 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001175 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1176 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001177 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001178 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1179 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001180 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001181 }
1182
Jim Grosbach039c2e12011-08-04 23:01:30 +00001183 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1184 assert(N == 2 && "Invalid number of operands!");
1185 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1186 assert(CE && "non-constant AM2OffsetImm operand!");
1187 int32_t Val = CE->getValue();
1188 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1189 // Special case for #-0
1190 if (Val == INT32_MIN) Val = 0;
1191 if (Val < 0) Val = -Val;
1192 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1193 Inst.addOperand(MCOperand::CreateReg(0));
1194 Inst.addOperand(MCOperand::CreateImm(Val));
1195 }
1196
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001197 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1198 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001199 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1200 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001201 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1202 // Special case for #-0
1203 if (Val == INT32_MIN) Val = 0;
1204 if (Val < 0) Val = -Val;
1205 Val = ARM_AM::getAM3Opc(AddSub, Val);
1206 } else {
1207 // For register offset, we encode the shift type and negation flag
1208 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001209 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001210 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001211 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1212 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001213 Inst.addOperand(MCOperand::CreateImm(Val));
1214 }
1215
1216 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001218 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001219 int32_t Val =
1220 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1221 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1222 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001223 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001224 }
1225
1226 // Constant offset.
1227 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1228 int32_t Val = CE->getValue();
1229 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1230 // Special case for #-0
1231 if (Val == INT32_MIN) Val = 0;
1232 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001233 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001234 Inst.addOperand(MCOperand::CreateReg(0));
1235 Inst.addOperand(MCOperand::CreateImm(Val));
1236 }
1237
Jim Grosbach7ce05792011-08-03 23:50:40 +00001238 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1239 assert(N == 2 && "Invalid number of operands!");
1240 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001241 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001242 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1243 // Special case for #-0
1244 if (Val == INT32_MIN) Val = 0;
1245 if (Val < 0) Val = -Val;
1246 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001247 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001248 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001249 }
1250
Jim Grosbacha77295d2011-09-08 22:07:06 +00001251 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001253 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1254 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001255 Inst.addOperand(MCOperand::CreateImm(Val));
1256 }
1257
Jim Grosbachb6aed502011-09-09 18:37:27 +00001258 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1259 assert(N == 2 && "Invalid number of operands!");
1260 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001261 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1262 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001263 Inst.addOperand(MCOperand::CreateImm(Val));
1264 }
1265
Jim Grosbach7ce05792011-08-03 23:50:40 +00001266 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1267 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001268 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1269 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001270 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001271 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001272
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001273 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1274 addMemImm8OffsetOperands(Inst, N);
1275 }
1276
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001277 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001278 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001279 }
1280
1281 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 2 && "Invalid number of operands!");
1283 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001284 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001285 addExpr(Inst, getImm());
1286 Inst.addOperand(MCOperand::CreateImm(0));
1287 return;
1288 }
1289
1290 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001291 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1292 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001293 Inst.addOperand(MCOperand::CreateImm(Val));
1294 }
1295
Jim Grosbach7ce05792011-08-03 23:50:40 +00001296 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1297 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001298 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001299 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001300 addExpr(Inst, getImm());
1301 Inst.addOperand(MCOperand::CreateImm(0));
1302 return;
1303 }
1304
1305 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001306 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1307 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001308 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001309 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001310
Jim Grosbach7f739be2011-09-19 22:21:13 +00001311 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1312 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001313 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1314 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001315 }
1316
1317 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1318 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001319 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1320 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001321 }
1322
Jim Grosbach7ce05792011-08-03 23:50:40 +00001323 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001325 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1326 Memory.ShiftImm, Memory.ShiftType);
1327 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1328 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001329 Inst.addOperand(MCOperand::CreateImm(Val));
1330 }
1331
Jim Grosbachab899c12011-09-07 23:10:15 +00001332 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1333 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001334 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1335 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1336 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001337 }
1338
Jim Grosbach7ce05792011-08-03 23:50:40 +00001339 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1340 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001341 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1342 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001343 }
1344
Jim Grosbach60f91a32011-08-19 17:55:24 +00001345 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001347 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1348 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001349 Inst.addOperand(MCOperand::CreateImm(Val));
1350 }
1351
Jim Grosbach38466302011-08-19 18:55:51 +00001352 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001354 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1355 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001356 Inst.addOperand(MCOperand::CreateImm(Val));
1357 }
1358
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001359 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1360 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001361 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1362 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001363 Inst.addOperand(MCOperand::CreateImm(Val));
1364 }
1365
Jim Grosbachecd85892011-08-19 18:13:48 +00001366 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1367 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001368 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1369 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001370 Inst.addOperand(MCOperand::CreateImm(Val));
1371 }
1372
Jim Grosbach7ce05792011-08-03 23:50:40 +00001373 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1374 assert(N == 1 && "Invalid number of operands!");
1375 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1376 assert(CE && "non-constant post-idx-imm8 operand!");
1377 int Imm = CE->getValue();
1378 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001379 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001380 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1381 Inst.addOperand(MCOperand::CreateImm(Imm));
1382 }
1383
Jim Grosbach2bd01182011-10-11 21:55:36 +00001384 void addPostIdxImm8s4Operands(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-imm8s4 operand!");
1388 int Imm = CE->getValue();
1389 bool isAdd = Imm >= 0;
1390 if (Imm == INT32_MIN) Imm = 0;
1391 // Immediate is scaled by 4.
1392 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1393 Inst.addOperand(MCOperand::CreateImm(Imm));
1394 }
1395
Jim Grosbach7ce05792011-08-03 23:50:40 +00001396 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1397 assert(N == 2 && "Invalid number of operands!");
1398 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001399 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1400 }
1401
1402 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
1404 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1405 // The sign, shift type, and shift amount are encoded in a single operand
1406 // using the AM2 encoding helpers.
1407 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1408 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1409 PostIdxReg.ShiftTy);
1410 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001411 }
1412
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001413 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
1415 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1416 }
1417
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001418 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1419 assert(N == 1 && "Invalid number of operands!");
1420 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1421 }
1422
Jim Grosbach460a9052011-10-07 23:56:00 +00001423 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1424 assert(N == 1 && "Invalid number of operands!");
1425 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1426 }
1427
1428 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1429 assert(N == 1 && "Invalid number of operands!");
1430 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1431 }
1432
1433 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1436 }
1437
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001438 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001439
Jim Grosbach89df9962011-08-26 21:43:41 +00001440 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001441 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001442 Op->ITMask.Mask = Mask;
1443 Op->StartLoc = S;
1444 Op->EndLoc = S;
1445 return Op;
1446 }
1447
Chris Lattner3a697562010-10-28 17:20:03 +00001448 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001449 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001450 Op->CC.Val = CC;
1451 Op->StartLoc = S;
1452 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001453 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001454 }
1455
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001456 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001457 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001458 Op->Cop.Val = CopVal;
1459 Op->StartLoc = S;
1460 Op->EndLoc = S;
1461 return Op;
1462 }
1463
1464 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001465 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001466 Op->Cop.Val = CopVal;
1467 Op->StartLoc = S;
1468 Op->EndLoc = S;
1469 return Op;
1470 }
1471
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001472 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1473 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1474 Op->Cop.Val = Val;
1475 Op->StartLoc = S;
1476 Op->EndLoc = E;
1477 return Op;
1478 }
1479
Jim Grosbachd67641b2010-12-06 18:21:12 +00001480 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001481 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001482 Op->Reg.RegNum = RegNum;
1483 Op->StartLoc = S;
1484 Op->EndLoc = S;
1485 return Op;
1486 }
1487
Chris Lattner3a697562010-10-28 17:20:03 +00001488 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001489 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001490 Op->Tok.Data = Str.data();
1491 Op->Tok.Length = Str.size();
1492 Op->StartLoc = S;
1493 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001494 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001495 }
1496
Bill Wendling50d0f582010-11-18 23:43:05 +00001497 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001498 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001499 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001500 Op->StartLoc = S;
1501 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001502 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001503 }
1504
Jim Grosbache8606dc2011-07-13 17:50:29 +00001505 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1506 unsigned SrcReg,
1507 unsigned ShiftReg,
1508 unsigned ShiftImm,
1509 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001510 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001511 Op->RegShiftedReg.ShiftTy = ShTy;
1512 Op->RegShiftedReg.SrcReg = SrcReg;
1513 Op->RegShiftedReg.ShiftReg = ShiftReg;
1514 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001515 Op->StartLoc = S;
1516 Op->EndLoc = E;
1517 return Op;
1518 }
1519
Owen Anderson92a20222011-07-21 18:54:16 +00001520 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1521 unsigned SrcReg,
1522 unsigned ShiftImm,
1523 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001524 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001525 Op->RegShiftedImm.ShiftTy = ShTy;
1526 Op->RegShiftedImm.SrcReg = SrcReg;
1527 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001528 Op->StartLoc = S;
1529 Op->EndLoc = E;
1530 return Op;
1531 }
1532
Jim Grosbach580f4a92011-07-25 22:20:28 +00001533 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001534 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001535 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001536 Op->ShifterImm.isASR = isASR;
1537 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001538 Op->StartLoc = S;
1539 Op->EndLoc = E;
1540 return Op;
1541 }
1542
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001543 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001544 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001545 Op->RotImm.Imm = Imm;
1546 Op->StartLoc = S;
1547 Op->EndLoc = E;
1548 return Op;
1549 }
1550
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001551 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1552 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001553 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001554 Op->Bitfield.LSB = LSB;
1555 Op->Bitfield.Width = Width;
1556 Op->StartLoc = S;
1557 Op->EndLoc = E;
1558 return Op;
1559 }
1560
Bill Wendling7729e062010-11-09 22:44:22 +00001561 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001562 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001563 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001564 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001565
Jim Grosbachd300b942011-09-13 22:56:44 +00001566 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001567 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001568 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001569 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001570 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001571
1572 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001573 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001574 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001575 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001576 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001577 Op->StartLoc = StartLoc;
1578 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001579 return Op;
1580 }
1581
Jim Grosbach460a9052011-10-07 23:56:00 +00001582 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1583 MCContext &Ctx) {
1584 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1585 Op->VectorIndex.Val = Idx;
1586 Op->StartLoc = S;
1587 Op->EndLoc = E;
1588 return Op;
1589 }
1590
Chris Lattner3a697562010-10-28 17:20:03 +00001591 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001592 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001593 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001594 Op->StartLoc = S;
1595 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001596 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001597 }
1598
Jim Grosbach9d390362011-10-03 23:38:36 +00001599 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001600 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001601 Op->FPImm.Val = Val;
1602 Op->StartLoc = S;
1603 Op->EndLoc = S;
1604 return Op;
1605 }
1606
Jim Grosbach7ce05792011-08-03 23:50:40 +00001607 static ARMOperand *CreateMem(unsigned BaseRegNum,
1608 const MCConstantExpr *OffsetImm,
1609 unsigned OffsetRegNum,
1610 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001611 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001612 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001613 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001614 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001615 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001616 Op->Memory.BaseRegNum = BaseRegNum;
1617 Op->Memory.OffsetImm = OffsetImm;
1618 Op->Memory.OffsetRegNum = OffsetRegNum;
1619 Op->Memory.ShiftType = ShiftType;
1620 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001621 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001622 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001623 Op->StartLoc = S;
1624 Op->EndLoc = E;
1625 return Op;
1626 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001627
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001628 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1629 ARM_AM::ShiftOpc ShiftTy,
1630 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001631 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001632 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001633 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001634 Op->PostIdxReg.isAdd = isAdd;
1635 Op->PostIdxReg.ShiftTy = ShiftTy;
1636 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001637 Op->StartLoc = S;
1638 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001639 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001640 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001641
1642 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001643 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001644 Op->MBOpt.Val = Opt;
1645 Op->StartLoc = S;
1646 Op->EndLoc = S;
1647 return Op;
1648 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001649
1650 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001651 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001652 Op->IFlags.Val = IFlags;
1653 Op->StartLoc = S;
1654 Op->EndLoc = S;
1655 return Op;
1656 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001657
1658 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001659 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001660 Op->MMask.Val = MMask;
1661 Op->StartLoc = S;
1662 Op->EndLoc = S;
1663 return Op;
1664 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001665};
1666
1667} // end anonymous namespace.
1668
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001669void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001670 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001671 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001672 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1673 << ") >";
1674 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001675 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001676 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001677 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001678 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001679 OS << "<ccout " << getReg() << ">";
1680 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001681 case k_ITCondMask: {
Jim Grosbach89df9962011-08-26 21:43:41 +00001682 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1683 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1684 "(tee)", "(eee)" };
1685 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1686 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1687 break;
1688 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001689 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001690 OS << "<coprocessor number: " << getCoproc() << ">";
1691 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001692 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001693 OS << "<coprocessor register: " << getCoproc() << ">";
1694 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001695 case k_CoprocOption:
1696 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1697 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001698 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001699 OS << "<mask: " << getMSRMask() << ">";
1700 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001701 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001702 getImm()->print(OS);
1703 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001704 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001705 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1706 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001707 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001708 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001709 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001710 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001711 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001712 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001713 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1714 << PostIdxReg.RegNum;
1715 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1716 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1717 << PostIdxReg.ShiftImm;
1718 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001719 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001720 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001721 OS << "<ARM_PROC::";
1722 unsigned IFlags = getProcIFlags();
1723 for (int i=2; i >= 0; --i)
1724 if (IFlags & (1 << i))
1725 OS << ARM_PROC::IFlagsToString(1 << i);
1726 OS << ">";
1727 break;
1728 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001729 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001730 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001731 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001732 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001733 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1734 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001735 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001736 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001737 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001738 << RegShiftedReg.SrcReg
1739 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1740 << ", " << RegShiftedReg.ShiftReg << ", "
1741 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001742 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001743 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001744 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001745 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001746 << RegShiftedImm.SrcReg
1747 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1748 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001749 << ">";
1750 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001751 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001752 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1753 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001754 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001755 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1756 << ", width: " << Bitfield.Width << ">";
1757 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001758 case k_RegisterList:
1759 case k_DPRRegisterList:
1760 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001761 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001762
Bill Wendling5fa22a12010-11-09 23:28:44 +00001763 const SmallVectorImpl<unsigned> &RegList = getRegList();
1764 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001765 I = RegList.begin(), E = RegList.end(); I != E; ) {
1766 OS << *I;
1767 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001768 }
1769
1770 OS << ">";
1771 break;
1772 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001773 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001774 OS << "'" << getToken() << "'";
1775 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001776 case k_VectorIndex:
1777 OS << "<vectorindex " << getVectorIndex() << ">";
1778 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001779 }
1780}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001781
1782/// @name Auto-generated Match Functions
1783/// {
1784
1785static unsigned MatchRegisterName(StringRef Name);
1786
1787/// }
1788
Bob Wilson69df7232011-02-03 21:46:10 +00001789bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1790 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001791 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001792
1793 return (RegNo == (unsigned)-1);
1794}
1795
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001796/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001797/// and if it is a register name the token is eaten and the register number is
1798/// returned. Otherwise return -1.
1799///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001800int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001801 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001802 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001803
Chris Lattnere5658fa2010-10-30 04:09:10 +00001804 // FIXME: Validate register for the current architecture; we have to do
1805 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001806 std::string upperCase = Tok.getString().str();
1807 std::string lowerCase = LowercaseString(upperCase);
1808 unsigned RegNum = MatchRegisterName(lowerCase);
1809 if (!RegNum) {
1810 RegNum = StringSwitch<unsigned>(lowerCase)
1811 .Case("r13", ARM::SP)
1812 .Case("r14", ARM::LR)
1813 .Case("r15", ARM::PC)
1814 .Case("ip", ARM::R12)
1815 .Default(0);
1816 }
1817 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001818
Chris Lattnere5658fa2010-10-30 04:09:10 +00001819 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00001820
1821#if 0
1822 // Also check for an index operand. This is only legal for vector registers,
1823 // but that'll get caught OK in operand matching, so we don't need to
1824 // explicitly filter everything else out here.
1825 if (Parser.getTok().is(AsmToken::LBrac)) {
1826 SMLoc SIdx = Parser.getTok().getLoc();
1827 Parser.Lex(); // Eat left bracket token.
1828
1829 const MCExpr *ImmVal;
1830 SMLoc ExprLoc = Parser.getTok().getLoc();
1831 if (getParser().ParseExpression(ImmVal))
1832 return MatchOperand_ParseFail;
1833 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1834 if (!MCE) {
1835 TokError("immediate value expected for vector index");
1836 return MatchOperand_ParseFail;
1837 }
1838
1839 SMLoc E = Parser.getTok().getLoc();
1840 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1841 Error(E, "']' expected");
1842 return MatchOperand_ParseFail;
1843 }
1844
1845 Parser.Lex(); // Eat right bracket token.
1846
1847 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1848 SIdx, E,
1849 getContext()));
1850 }
1851#endif
1852
Chris Lattnere5658fa2010-10-30 04:09:10 +00001853 return RegNum;
1854}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001855
Jim Grosbach19906722011-07-13 18:49:30 +00001856// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1857// If a recoverable error occurs, return 1. If an irrecoverable error
1858// occurs, return -1. An irrecoverable error is one where tokens have been
1859// consumed in the process of trying to parse the shifter (i.e., when it is
1860// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001861int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001862 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1863 SMLoc S = Parser.getTok().getLoc();
1864 const AsmToken &Tok = Parser.getTok();
1865 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1866
1867 std::string upperCase = Tok.getString().str();
1868 std::string lowerCase = LowercaseString(upperCase);
1869 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1870 .Case("lsl", ARM_AM::lsl)
1871 .Case("lsr", ARM_AM::lsr)
1872 .Case("asr", ARM_AM::asr)
1873 .Case("ror", ARM_AM::ror)
1874 .Case("rrx", ARM_AM::rrx)
1875 .Default(ARM_AM::no_shift);
1876
1877 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001878 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001879
Jim Grosbache8606dc2011-07-13 17:50:29 +00001880 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001881
Jim Grosbache8606dc2011-07-13 17:50:29 +00001882 // The source register for the shift has already been added to the
1883 // operand list, so we need to pop it off and combine it into the shifted
1884 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001885 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001886 if (!PrevOp->isReg())
1887 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1888 int SrcReg = PrevOp->getReg();
1889 int64_t Imm = 0;
1890 int ShiftReg = 0;
1891 if (ShiftTy == ARM_AM::rrx) {
1892 // RRX Doesn't have an explicit shift amount. The encoder expects
1893 // the shift register to be the same as the source register. Seems odd,
1894 // but OK.
1895 ShiftReg = SrcReg;
1896 } else {
1897 // Figure out if this is shifted by a constant or a register (for non-RRX).
1898 if (Parser.getTok().is(AsmToken::Hash)) {
1899 Parser.Lex(); // Eat hash.
1900 SMLoc ImmLoc = Parser.getTok().getLoc();
1901 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001902 if (getParser().ParseExpression(ShiftExpr)) {
1903 Error(ImmLoc, "invalid immediate shift value");
1904 return -1;
1905 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001906 // The expression must be evaluatable as an immediate.
1907 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001908 if (!CE) {
1909 Error(ImmLoc, "invalid immediate shift value");
1910 return -1;
1911 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001912 // Range check the immediate.
1913 // lsl, ror: 0 <= imm <= 31
1914 // lsr, asr: 0 <= imm <= 32
1915 Imm = CE->getValue();
1916 if (Imm < 0 ||
1917 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1918 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001919 Error(ImmLoc, "immediate shift value out of range");
1920 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001921 }
1922 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001923 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001924 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001925 if (ShiftReg == -1) {
1926 Error (L, "expected immediate or register in shift operand");
1927 return -1;
1928 }
1929 } else {
1930 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001931 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001932 return -1;
1933 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001934 }
1935
Owen Anderson92a20222011-07-21 18:54:16 +00001936 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1937 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001938 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001939 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001940 else
1941 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1942 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001943
Jim Grosbach19906722011-07-13 18:49:30 +00001944 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001945}
1946
1947
Bill Wendling50d0f582010-11-18 23:43:05 +00001948/// Try to parse a register name. The token must be an Identifier when called.
1949/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1950/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001951///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001952/// TODO this is likely to change to allow different register types and or to
1953/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001954bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001955tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001956 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001957 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001958 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001959 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001960
Bill Wendling50d0f582010-11-18 23:43:05 +00001961 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001962
Chris Lattnere5658fa2010-10-30 04:09:10 +00001963 const AsmToken &ExclaimTok = Parser.getTok();
1964 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001965 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1966 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001967 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00001968 return false;
1969 }
1970
1971 // Also check for an index operand. This is only legal for vector registers,
1972 // but that'll get caught OK in operand matching, so we don't need to
1973 // explicitly filter everything else out here.
1974 if (Parser.getTok().is(AsmToken::LBrac)) {
1975 SMLoc SIdx = Parser.getTok().getLoc();
1976 Parser.Lex(); // Eat left bracket token.
1977
1978 const MCExpr *ImmVal;
1979 SMLoc ExprLoc = Parser.getTok().getLoc();
1980 if (getParser().ParseExpression(ImmVal))
1981 return MatchOperand_ParseFail;
1982 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
1983 if (!MCE) {
1984 TokError("immediate value expected for vector index");
1985 return MatchOperand_ParseFail;
1986 }
1987
1988 SMLoc E = Parser.getTok().getLoc();
1989 if (Parser.getTok().isNot(AsmToken::RBrac)) {
1990 Error(E, "']' expected");
1991 return MatchOperand_ParseFail;
1992 }
1993
1994 Parser.Lex(); // Eat right bracket token.
1995
1996 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
1997 SIdx, E,
1998 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00001999 }
2000
Bill Wendling50d0f582010-11-18 23:43:05 +00002001 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002002}
2003
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002004/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2005/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2006/// "c5", ...
2007static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002008 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2009 // but efficient.
2010 switch (Name.size()) {
2011 default: break;
2012 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002013 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002014 return -1;
2015 switch (Name[1]) {
2016 default: return -1;
2017 case '0': return 0;
2018 case '1': return 1;
2019 case '2': return 2;
2020 case '3': return 3;
2021 case '4': return 4;
2022 case '5': return 5;
2023 case '6': return 6;
2024 case '7': return 7;
2025 case '8': return 8;
2026 case '9': return 9;
2027 }
2028 break;
2029 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002030 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002031 return -1;
2032 switch (Name[2]) {
2033 default: return -1;
2034 case '0': return 10;
2035 case '1': return 11;
2036 case '2': return 12;
2037 case '3': return 13;
2038 case '4': return 14;
2039 case '5': return 15;
2040 }
2041 break;
2042 }
2043
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002044 return -1;
2045}
2046
Jim Grosbach89df9962011-08-26 21:43:41 +00002047/// parseITCondCode - Try to parse a condition code for an IT instruction.
2048ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2049parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2050 SMLoc S = Parser.getTok().getLoc();
2051 const AsmToken &Tok = Parser.getTok();
2052 if (!Tok.is(AsmToken::Identifier))
2053 return MatchOperand_NoMatch;
2054 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2055 .Case("eq", ARMCC::EQ)
2056 .Case("ne", ARMCC::NE)
2057 .Case("hs", ARMCC::HS)
2058 .Case("cs", ARMCC::HS)
2059 .Case("lo", ARMCC::LO)
2060 .Case("cc", ARMCC::LO)
2061 .Case("mi", ARMCC::MI)
2062 .Case("pl", ARMCC::PL)
2063 .Case("vs", ARMCC::VS)
2064 .Case("vc", ARMCC::VC)
2065 .Case("hi", ARMCC::HI)
2066 .Case("ls", ARMCC::LS)
2067 .Case("ge", ARMCC::GE)
2068 .Case("lt", ARMCC::LT)
2069 .Case("gt", ARMCC::GT)
2070 .Case("le", ARMCC::LE)
2071 .Case("al", ARMCC::AL)
2072 .Default(~0U);
2073 if (CC == ~0U)
2074 return MatchOperand_NoMatch;
2075 Parser.Lex(); // Eat the token.
2076
2077 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2078
2079 return MatchOperand_Success;
2080}
2081
Jim Grosbach43904292011-07-25 20:14:50 +00002082/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002083/// token must be an Identifier when called, and if it is a coprocessor
2084/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002085ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002086parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002087 SMLoc S = Parser.getTok().getLoc();
2088 const AsmToken &Tok = Parser.getTok();
2089 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2090
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002091 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002092 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002093 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002094
2095 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002096 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002097 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002098}
2099
Jim Grosbach43904292011-07-25 20:14:50 +00002100/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002101/// token must be an Identifier when called, and if it is a coprocessor
2102/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002103ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002104parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002105 SMLoc S = Parser.getTok().getLoc();
2106 const AsmToken &Tok = Parser.getTok();
2107 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2108
2109 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2110 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002111 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002112
2113 Parser.Lex(); // Eat identifier token.
2114 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002115 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002116}
2117
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002118/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2119/// coproc_option : '{' imm0_255 '}'
2120ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2121parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2122 SMLoc S = Parser.getTok().getLoc();
2123
2124 // If this isn't a '{', this isn't a coprocessor immediate operand.
2125 if (Parser.getTok().isNot(AsmToken::LCurly))
2126 return MatchOperand_NoMatch;
2127 Parser.Lex(); // Eat the '{'
2128
2129 const MCExpr *Expr;
2130 SMLoc Loc = Parser.getTok().getLoc();
2131 if (getParser().ParseExpression(Expr)) {
2132 Error(Loc, "illegal expression");
2133 return MatchOperand_ParseFail;
2134 }
2135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2136 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2137 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2138 return MatchOperand_ParseFail;
2139 }
2140 int Val = CE->getValue();
2141
2142 // Check for and consume the closing '}'
2143 if (Parser.getTok().isNot(AsmToken::RCurly))
2144 return MatchOperand_ParseFail;
2145 SMLoc E = Parser.getTok().getLoc();
2146 Parser.Lex(); // Eat the '}'
2147
2148 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2149 return MatchOperand_Success;
2150}
2151
Jim Grosbachd0588e22011-09-14 18:08:35 +00002152// For register list parsing, we need to map from raw GPR register numbering
2153// to the enumeration values. The enumeration values aren't sorted by
2154// register number due to our using "sp", "lr" and "pc" as canonical names.
2155static unsigned getNextRegister(unsigned Reg) {
2156 // If this is a GPR, we need to do it manually, otherwise we can rely
2157 // on the sort ordering of the enumeration since the other reg-classes
2158 // are sane.
2159 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2160 return Reg + 1;
2161 switch(Reg) {
2162 default: assert(0 && "Invalid GPR number!");
2163 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2164 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2165 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2166 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2167 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2168 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2169 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2170 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2171 }
2172}
2173
2174/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002175bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002176parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002177 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002178 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002179 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002180 Parser.Lex(); // Eat '{' token.
2181 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002182
Jim Grosbachd0588e22011-09-14 18:08:35 +00002183 // Check the first register in the list to see what register class
2184 // this is a list of.
2185 int Reg = tryParseRegister();
2186 if (Reg == -1)
2187 return Error(RegLoc, "register expected");
2188
2189 MCRegisterClass *RC;
2190 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2191 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2192 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2193 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2194 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2195 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2196 else
2197 return Error(RegLoc, "invalid register in register list");
2198
2199 // The reglist instructions have at most 16 registers, so reserve
2200 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002201 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002202 // Store the first register.
2203 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002204
Jim Grosbachd0588e22011-09-14 18:08:35 +00002205 // This starts immediately after the first register token in the list,
2206 // so we can see either a comma or a minus (range separator) as a legal
2207 // next token.
2208 while (Parser.getTok().is(AsmToken::Comma) ||
2209 Parser.getTok().is(AsmToken::Minus)) {
2210 if (Parser.getTok().is(AsmToken::Minus)) {
2211 Parser.Lex(); // Eat the comma.
2212 SMLoc EndLoc = Parser.getTok().getLoc();
2213 int EndReg = tryParseRegister();
2214 if (EndReg == -1)
2215 return Error(EndLoc, "register expected");
2216 // If the register is the same as the start reg, there's nothing
2217 // more to do.
2218 if (Reg == EndReg)
2219 continue;
2220 // The register must be in the same register class as the first.
2221 if (!RC->contains(EndReg))
2222 return Error(EndLoc, "invalid register in register list");
2223 // Ranges must go from low to high.
2224 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2225 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002226
Jim Grosbachd0588e22011-09-14 18:08:35 +00002227 // Add all the registers in the range to the register list.
2228 while (Reg != EndReg) {
2229 Reg = getNextRegister(Reg);
2230 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2231 }
2232 continue;
2233 }
2234 Parser.Lex(); // Eat the comma.
2235 RegLoc = Parser.getTok().getLoc();
2236 int OldReg = Reg;
2237 Reg = tryParseRegister();
2238 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002239 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002240 // The register must be in the same register class as the first.
2241 if (!RC->contains(Reg))
2242 return Error(RegLoc, "invalid register in register list");
2243 // List must be monotonically increasing.
2244 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2245 return Error(RegLoc, "register list not in ascending order");
2246 // VFP register lists must also be contiguous.
2247 // It's OK to use the enumeration values directly here rather, as the
2248 // VFP register classes have the enum sorted properly.
2249 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2250 Reg != OldReg + 1)
2251 return Error(RegLoc, "non-contiguous register range");
2252 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002253 }
2254
Jim Grosbachd0588e22011-09-14 18:08:35 +00002255 SMLoc E = Parser.getTok().getLoc();
2256 if (Parser.getTok().isNot(AsmToken::RCurly))
2257 return Error(E, "'}' expected");
2258 Parser.Lex(); // Eat '}' token.
2259
Bill Wendling50d0f582010-11-18 23:43:05 +00002260 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2261 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002262}
2263
Jim Grosbach43904292011-07-25 20:14:50 +00002264/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002265ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002266parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002267 SMLoc S = Parser.getTok().getLoc();
2268 const AsmToken &Tok = Parser.getTok();
2269 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2270 StringRef OptStr = Tok.getString();
2271
2272 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2273 .Case("sy", ARM_MB::SY)
2274 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002275 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002276 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002277 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002278 .Case("ishst", ARM_MB::ISHST)
2279 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002280 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002281 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002282 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002283 .Case("osh", ARM_MB::OSH)
2284 .Case("oshst", ARM_MB::OSHST)
2285 .Default(~0U);
2286
2287 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002288 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002289
2290 Parser.Lex(); // Eat identifier token.
2291 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002292 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002293}
2294
Jim Grosbach43904292011-07-25 20:14:50 +00002295/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002296ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002297parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002298 SMLoc S = Parser.getTok().getLoc();
2299 const AsmToken &Tok = Parser.getTok();
2300 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2301 StringRef IFlagsStr = Tok.getString();
2302
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002303 // An iflags string of "none" is interpreted to mean that none of the AIF
2304 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002305 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002306 if (IFlagsStr != "none") {
2307 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2308 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2309 .Case("a", ARM_PROC::A)
2310 .Case("i", ARM_PROC::I)
2311 .Case("f", ARM_PROC::F)
2312 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002313
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002314 // If some specific iflag is already set, it means that some letter is
2315 // present more than once, this is not acceptable.
2316 if (Flag == ~0U || (IFlags & Flag))
2317 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002318
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002319 IFlags |= Flag;
2320 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002321 }
2322
2323 Parser.Lex(); // Eat identifier token.
2324 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2325 return MatchOperand_Success;
2326}
2327
Jim Grosbach43904292011-07-25 20:14:50 +00002328/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002329ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002330parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002331 SMLoc S = Parser.getTok().getLoc();
2332 const AsmToken &Tok = Parser.getTok();
2333 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2334 StringRef Mask = Tok.getString();
2335
James Molloyacad68d2011-09-28 14:21:38 +00002336 if (isMClass()) {
2337 // See ARMv6-M 10.1.1
2338 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2339 .Case("apsr", 0)
2340 .Case("iapsr", 1)
2341 .Case("eapsr", 2)
2342 .Case("xpsr", 3)
2343 .Case("ipsr", 5)
2344 .Case("epsr", 6)
2345 .Case("iepsr", 7)
2346 .Case("msp", 8)
2347 .Case("psp", 9)
2348 .Case("primask", 16)
2349 .Case("basepri", 17)
2350 .Case("basepri_max", 18)
2351 .Case("faultmask", 19)
2352 .Case("control", 20)
2353 .Default(~0U);
2354
2355 if (FlagsVal == ~0U)
2356 return MatchOperand_NoMatch;
2357
2358 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2359 // basepri, basepri_max and faultmask only valid for V7m.
2360 return MatchOperand_NoMatch;
2361
2362 Parser.Lex(); // Eat identifier token.
2363 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2364 return MatchOperand_Success;
2365 }
2366
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002367 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2368 size_t Start = 0, Next = Mask.find('_');
2369 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002370 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002371 if (Next != StringRef::npos)
2372 Flags = Mask.slice(Next+1, Mask.size());
2373
2374 // FlagsVal contains the complete mask:
2375 // 3-0: Mask
2376 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2377 unsigned FlagsVal = 0;
2378
2379 if (SpecReg == "apsr") {
2380 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002381 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002382 .Case("g", 0x4) // same as CPSR_s
2383 .Case("nzcvqg", 0xc) // same as CPSR_fs
2384 .Default(~0U);
2385
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002386 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002387 if (!Flags.empty())
2388 return MatchOperand_NoMatch;
2389 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002390 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002391 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002392 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002393 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2394 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002395 for (int i = 0, e = Flags.size(); i != e; ++i) {
2396 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2397 .Case("c", 1)
2398 .Case("x", 2)
2399 .Case("s", 4)
2400 .Case("f", 8)
2401 .Default(~0U);
2402
2403 // If some specific flag is already set, it means that some letter is
2404 // present more than once, this is not acceptable.
2405 if (FlagsVal == ~0U || (FlagsVal & Flag))
2406 return MatchOperand_NoMatch;
2407 FlagsVal |= Flag;
2408 }
2409 } else // No match for special register.
2410 return MatchOperand_NoMatch;
2411
2412 // Special register without flags are equivalent to "fc" flags.
2413 if (!FlagsVal)
2414 FlagsVal = 0x9;
2415
2416 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2417 if (SpecReg == "spsr")
2418 FlagsVal |= 16;
2419
2420 Parser.Lex(); // Eat identifier token.
2421 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2422 return MatchOperand_Success;
2423}
2424
Jim Grosbachf6c05252011-07-21 17:23:04 +00002425ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2426parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2427 int Low, int High) {
2428 const AsmToken &Tok = Parser.getTok();
2429 if (Tok.isNot(AsmToken::Identifier)) {
2430 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2431 return MatchOperand_ParseFail;
2432 }
2433 StringRef ShiftName = Tok.getString();
2434 std::string LowerOp = LowercaseString(Op);
2435 std::string UpperOp = UppercaseString(Op);
2436 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2437 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2438 return MatchOperand_ParseFail;
2439 }
2440 Parser.Lex(); // Eat shift type token.
2441
2442 // There must be a '#' and a shift amount.
2443 if (Parser.getTok().isNot(AsmToken::Hash)) {
2444 Error(Parser.getTok().getLoc(), "'#' expected");
2445 return MatchOperand_ParseFail;
2446 }
2447 Parser.Lex(); // Eat hash token.
2448
2449 const MCExpr *ShiftAmount;
2450 SMLoc Loc = Parser.getTok().getLoc();
2451 if (getParser().ParseExpression(ShiftAmount)) {
2452 Error(Loc, "illegal expression");
2453 return MatchOperand_ParseFail;
2454 }
2455 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2456 if (!CE) {
2457 Error(Loc, "constant expression expected");
2458 return MatchOperand_ParseFail;
2459 }
2460 int Val = CE->getValue();
2461 if (Val < Low || Val > High) {
2462 Error(Loc, "immediate value out of range");
2463 return MatchOperand_ParseFail;
2464 }
2465
2466 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2467
2468 return MatchOperand_Success;
2469}
2470
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002471ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2472parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2473 const AsmToken &Tok = Parser.getTok();
2474 SMLoc S = Tok.getLoc();
2475 if (Tok.isNot(AsmToken::Identifier)) {
2476 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2477 return MatchOperand_ParseFail;
2478 }
2479 int Val = StringSwitch<int>(Tok.getString())
2480 .Case("be", 1)
2481 .Case("le", 0)
2482 .Default(-1);
2483 Parser.Lex(); // Eat the token.
2484
2485 if (Val == -1) {
2486 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2487 return MatchOperand_ParseFail;
2488 }
2489 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2490 getContext()),
2491 S, Parser.getTok().getLoc()));
2492 return MatchOperand_Success;
2493}
2494
Jim Grosbach580f4a92011-07-25 22:20:28 +00002495/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2496/// instructions. Legal values are:
2497/// lsl #n 'n' in [0,31]
2498/// asr #n 'n' in [1,32]
2499/// n == 32 encoded as n == 0.
2500ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2501parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2502 const AsmToken &Tok = Parser.getTok();
2503 SMLoc S = Tok.getLoc();
2504 if (Tok.isNot(AsmToken::Identifier)) {
2505 Error(S, "shift operator 'asr' or 'lsl' expected");
2506 return MatchOperand_ParseFail;
2507 }
2508 StringRef ShiftName = Tok.getString();
2509 bool isASR;
2510 if (ShiftName == "lsl" || ShiftName == "LSL")
2511 isASR = false;
2512 else if (ShiftName == "asr" || ShiftName == "ASR")
2513 isASR = true;
2514 else {
2515 Error(S, "shift operator 'asr' or 'lsl' expected");
2516 return MatchOperand_ParseFail;
2517 }
2518 Parser.Lex(); // Eat the operator.
2519
2520 // A '#' and a shift amount.
2521 if (Parser.getTok().isNot(AsmToken::Hash)) {
2522 Error(Parser.getTok().getLoc(), "'#' expected");
2523 return MatchOperand_ParseFail;
2524 }
2525 Parser.Lex(); // Eat hash token.
2526
2527 const MCExpr *ShiftAmount;
2528 SMLoc E = Parser.getTok().getLoc();
2529 if (getParser().ParseExpression(ShiftAmount)) {
2530 Error(E, "malformed shift expression");
2531 return MatchOperand_ParseFail;
2532 }
2533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2534 if (!CE) {
2535 Error(E, "shift amount must be an immediate");
2536 return MatchOperand_ParseFail;
2537 }
2538
2539 int64_t Val = CE->getValue();
2540 if (isASR) {
2541 // Shift amount must be in [1,32]
2542 if (Val < 1 || Val > 32) {
2543 Error(E, "'asr' shift amount must be in range [1,32]");
2544 return MatchOperand_ParseFail;
2545 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002546 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2547 if (isThumb() && Val == 32) {
2548 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2549 return MatchOperand_ParseFail;
2550 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002551 if (Val == 32) Val = 0;
2552 } else {
2553 // Shift amount must be in [1,32]
2554 if (Val < 0 || Val > 31) {
2555 Error(E, "'lsr' shift amount must be in range [0,31]");
2556 return MatchOperand_ParseFail;
2557 }
2558 }
2559
2560 E = Parser.getTok().getLoc();
2561 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2562
2563 return MatchOperand_Success;
2564}
2565
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002566/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2567/// of instructions. Legal values are:
2568/// ror #n 'n' in {0, 8, 16, 24}
2569ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2570parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2571 const AsmToken &Tok = Parser.getTok();
2572 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002573 if (Tok.isNot(AsmToken::Identifier))
2574 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002575 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002576 if (ShiftName != "ror" && ShiftName != "ROR")
2577 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002578 Parser.Lex(); // Eat the operator.
2579
2580 // A '#' and a rotate amount.
2581 if (Parser.getTok().isNot(AsmToken::Hash)) {
2582 Error(Parser.getTok().getLoc(), "'#' expected");
2583 return MatchOperand_ParseFail;
2584 }
2585 Parser.Lex(); // Eat hash token.
2586
2587 const MCExpr *ShiftAmount;
2588 SMLoc E = Parser.getTok().getLoc();
2589 if (getParser().ParseExpression(ShiftAmount)) {
2590 Error(E, "malformed rotate expression");
2591 return MatchOperand_ParseFail;
2592 }
2593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2594 if (!CE) {
2595 Error(E, "rotate amount must be an immediate");
2596 return MatchOperand_ParseFail;
2597 }
2598
2599 int64_t Val = CE->getValue();
2600 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2601 // normally, zero is represented in asm by omitting the rotate operand
2602 // entirely.
2603 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2604 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2605 return MatchOperand_ParseFail;
2606 }
2607
2608 E = Parser.getTok().getLoc();
2609 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2610
2611 return MatchOperand_Success;
2612}
2613
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002614ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2615parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2616 SMLoc S = Parser.getTok().getLoc();
2617 // The bitfield descriptor is really two operands, the LSB and the width.
2618 if (Parser.getTok().isNot(AsmToken::Hash)) {
2619 Error(Parser.getTok().getLoc(), "'#' expected");
2620 return MatchOperand_ParseFail;
2621 }
2622 Parser.Lex(); // Eat hash token.
2623
2624 const MCExpr *LSBExpr;
2625 SMLoc E = Parser.getTok().getLoc();
2626 if (getParser().ParseExpression(LSBExpr)) {
2627 Error(E, "malformed immediate expression");
2628 return MatchOperand_ParseFail;
2629 }
2630 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2631 if (!CE) {
2632 Error(E, "'lsb' operand must be an immediate");
2633 return MatchOperand_ParseFail;
2634 }
2635
2636 int64_t LSB = CE->getValue();
2637 // The LSB must be in the range [0,31]
2638 if (LSB < 0 || LSB > 31) {
2639 Error(E, "'lsb' operand must be in the range [0,31]");
2640 return MatchOperand_ParseFail;
2641 }
2642 E = Parser.getTok().getLoc();
2643
2644 // Expect another immediate operand.
2645 if (Parser.getTok().isNot(AsmToken::Comma)) {
2646 Error(Parser.getTok().getLoc(), "too few operands");
2647 return MatchOperand_ParseFail;
2648 }
2649 Parser.Lex(); // Eat hash token.
2650 if (Parser.getTok().isNot(AsmToken::Hash)) {
2651 Error(Parser.getTok().getLoc(), "'#' expected");
2652 return MatchOperand_ParseFail;
2653 }
2654 Parser.Lex(); // Eat hash token.
2655
2656 const MCExpr *WidthExpr;
2657 if (getParser().ParseExpression(WidthExpr)) {
2658 Error(E, "malformed immediate expression");
2659 return MatchOperand_ParseFail;
2660 }
2661 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2662 if (!CE) {
2663 Error(E, "'width' operand must be an immediate");
2664 return MatchOperand_ParseFail;
2665 }
2666
2667 int64_t Width = CE->getValue();
2668 // The LSB must be in the range [1,32-lsb]
2669 if (Width < 1 || Width > 32 - LSB) {
2670 Error(E, "'width' operand must be in the range [1,32-lsb]");
2671 return MatchOperand_ParseFail;
2672 }
2673 E = Parser.getTok().getLoc();
2674
2675 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2676
2677 return MatchOperand_Success;
2678}
2679
Jim Grosbach7ce05792011-08-03 23:50:40 +00002680ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2681parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2682 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002683 // postidx_reg := '+' register {, shift}
2684 // | '-' register {, shift}
2685 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002686
2687 // This method must return MatchOperand_NoMatch without consuming any tokens
2688 // in the case where there is no match, as other alternatives take other
2689 // parse methods.
2690 AsmToken Tok = Parser.getTok();
2691 SMLoc S = Tok.getLoc();
2692 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002693 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002694 int Reg = -1;
2695 if (Tok.is(AsmToken::Plus)) {
2696 Parser.Lex(); // Eat the '+' token.
2697 haveEaten = true;
2698 } else if (Tok.is(AsmToken::Minus)) {
2699 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002700 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002701 haveEaten = true;
2702 }
2703 if (Parser.getTok().is(AsmToken::Identifier))
2704 Reg = tryParseRegister();
2705 if (Reg == -1) {
2706 if (!haveEaten)
2707 return MatchOperand_NoMatch;
2708 Error(Parser.getTok().getLoc(), "register expected");
2709 return MatchOperand_ParseFail;
2710 }
2711 SMLoc E = Parser.getTok().getLoc();
2712
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002713 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2714 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002715 if (Parser.getTok().is(AsmToken::Comma)) {
2716 Parser.Lex(); // Eat the ','.
2717 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2718 return MatchOperand_ParseFail;
2719 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002720
2721 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2722 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002723
2724 return MatchOperand_Success;
2725}
2726
Jim Grosbach251bf252011-08-10 21:56:18 +00002727ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2728parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2729 // Check for a post-index addressing register operand. Specifically:
2730 // am3offset := '+' register
2731 // | '-' register
2732 // | register
2733 // | # imm
2734 // | # + imm
2735 // | # - imm
2736
2737 // This method must return MatchOperand_NoMatch without consuming any tokens
2738 // in the case where there is no match, as other alternatives take other
2739 // parse methods.
2740 AsmToken Tok = Parser.getTok();
2741 SMLoc S = Tok.getLoc();
2742
2743 // Do immediates first, as we always parse those if we have a '#'.
2744 if (Parser.getTok().is(AsmToken::Hash)) {
2745 Parser.Lex(); // Eat the '#'.
2746 // Explicitly look for a '-', as we need to encode negative zero
2747 // differently.
2748 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2749 const MCExpr *Offset;
2750 if (getParser().ParseExpression(Offset))
2751 return MatchOperand_ParseFail;
2752 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2753 if (!CE) {
2754 Error(S, "constant expression expected");
2755 return MatchOperand_ParseFail;
2756 }
2757 SMLoc E = Tok.getLoc();
2758 // Negative zero is encoded as the flag value INT32_MIN.
2759 int32_t Val = CE->getValue();
2760 if (isNegative && Val == 0)
2761 Val = INT32_MIN;
2762
2763 Operands.push_back(
2764 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2765
2766 return MatchOperand_Success;
2767 }
2768
2769
2770 bool haveEaten = false;
2771 bool isAdd = true;
2772 int Reg = -1;
2773 if (Tok.is(AsmToken::Plus)) {
2774 Parser.Lex(); // Eat the '+' token.
2775 haveEaten = true;
2776 } else if (Tok.is(AsmToken::Minus)) {
2777 Parser.Lex(); // Eat the '-' token.
2778 isAdd = false;
2779 haveEaten = true;
2780 }
2781 if (Parser.getTok().is(AsmToken::Identifier))
2782 Reg = tryParseRegister();
2783 if (Reg == -1) {
2784 if (!haveEaten)
2785 return MatchOperand_NoMatch;
2786 Error(Parser.getTok().getLoc(), "register expected");
2787 return MatchOperand_ParseFail;
2788 }
2789 SMLoc E = Parser.getTok().getLoc();
2790
2791 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2792 0, S, E));
2793
2794 return MatchOperand_Success;
2795}
2796
Jim Grosbacha77295d2011-09-08 22:07:06 +00002797/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2798/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2799/// when they refer multiple MIOperands inside a single one.
2800bool ARMAsmParser::
2801cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2803 // Rt, Rt2
2804 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2805 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2806 // Create a writeback register dummy placeholder.
2807 Inst.addOperand(MCOperand::CreateReg(0));
2808 // addr
2809 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2810 // pred
2811 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2812 return true;
2813}
2814
2815/// cvtT2StrdPre - Convert parsed operands to MCInst.
2816/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2817/// when they refer multiple MIOperands inside a single one.
2818bool ARMAsmParser::
2819cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2820 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2821 // Create a writeback register dummy placeholder.
2822 Inst.addOperand(MCOperand::CreateReg(0));
2823 // Rt, Rt2
2824 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2825 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2826 // addr
2827 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2828 // pred
2829 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2830 return true;
2831}
2832
Jim Grosbacheeec0252011-09-08 00:39:19 +00002833/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2834/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2835/// when they refer multiple MIOperands inside a single one.
2836bool ARMAsmParser::
2837cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2838 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2839 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2840
2841 // Create a writeback register dummy placeholder.
2842 Inst.addOperand(MCOperand::CreateImm(0));
2843
2844 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2845 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2846 return true;
2847}
2848
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002849/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2850/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2851/// when they refer multiple MIOperands inside a single one.
2852bool ARMAsmParser::
2853cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2854 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2855 // Create a writeback register dummy placeholder.
2856 Inst.addOperand(MCOperand::CreateImm(0));
2857 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2858 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2859 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2860 return true;
2861}
2862
Jim Grosbach1355cf12011-07-26 17:10:22 +00002863/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002864/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2865/// when they refer multiple MIOperands inside a single one.
2866bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002867cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002868 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2869 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2870
2871 // Create a writeback register dummy placeholder.
2872 Inst.addOperand(MCOperand::CreateImm(0));
2873
Jim Grosbach7ce05792011-08-03 23:50:40 +00002874 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002875 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2876 return true;
2877}
2878
Owen Anderson9ab0f252011-08-26 20:43:14 +00002879/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2880/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2881/// when they refer multiple MIOperands inside a single one.
2882bool ARMAsmParser::
2883cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2884 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2885 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2886
2887 // Create a writeback register dummy placeholder.
2888 Inst.addOperand(MCOperand::CreateImm(0));
2889
2890 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2891 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2892 return true;
2893}
2894
2895
Jim Grosbach548340c2011-08-11 19:22:40 +00002896/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2897/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2898/// when they refer multiple MIOperands inside a single one.
2899bool ARMAsmParser::
2900cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2901 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2902 // Create a writeback register dummy placeholder.
2903 Inst.addOperand(MCOperand::CreateImm(0));
2904 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2905 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2906 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2907 return true;
2908}
2909
Jim Grosbach1355cf12011-07-26 17:10:22 +00002910/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002911/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2912/// when they refer multiple MIOperands inside a single one.
2913bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002914cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002915 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2916 // Create a writeback register dummy placeholder.
2917 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002918 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2919 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2920 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002921 return true;
2922}
2923
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002924/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2925/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2926/// when they refer multiple MIOperands inside a single one.
2927bool ARMAsmParser::
2928cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2929 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2930 // Create a writeback register dummy placeholder.
2931 Inst.addOperand(MCOperand::CreateImm(0));
2932 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2933 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2934 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2935 return true;
2936}
2937
Jim Grosbach7ce05792011-08-03 23:50:40 +00002938/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2939/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2940/// when they refer multiple MIOperands inside a single one.
2941bool ARMAsmParser::
2942cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2943 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2944 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002945 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002946 // Create a writeback register dummy placeholder.
2947 Inst.addOperand(MCOperand::CreateImm(0));
2948 // addr
2949 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2950 // offset
2951 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2952 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002953 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2954 return true;
2955}
2956
Jim Grosbach7ce05792011-08-03 23:50:40 +00002957/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002958/// 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::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002961cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2962 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2963 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002964 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002965 // Create a writeback register dummy placeholder.
2966 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002967 // addr
2968 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2969 // offset
2970 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2971 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002972 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2973 return true;
2974}
2975
Jim Grosbach7ce05792011-08-03 23:50:40 +00002976/// cvtStExtTWriteBackImm - 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 +00002980cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2981 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002982 // Create a writeback register dummy placeholder.
2983 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002984 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002985 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002986 // addr
2987 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2988 // offset
2989 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2990 // pred
2991 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2992 return true;
2993}
2994
2995/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2996/// 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::
2999cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3000 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3001 // Create a writeback register dummy placeholder.
3002 Inst.addOperand(MCOperand::CreateImm(0));
3003 // Rt
3004 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3005 // addr
3006 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3007 // offset
3008 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3009 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003010 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3011 return true;
3012}
3013
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003014/// cvtLdrdPre - 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::
3018cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3019 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3020 // Rt, Rt2
3021 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3022 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3023 // Create a writeback register dummy placeholder.
3024 Inst.addOperand(MCOperand::CreateImm(0));
3025 // addr
3026 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3027 // pred
3028 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3029 return true;
3030}
3031
Jim Grosbach14605d12011-08-11 20:28:23 +00003032/// cvtStrdPre - Convert parsed operands to MCInst.
3033/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3034/// when they refer multiple MIOperands inside a single one.
3035bool ARMAsmParser::
3036cvtStrdPre(MCInst &Inst, unsigned Opcode,
3037 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3038 // Create a writeback register dummy placeholder.
3039 Inst.addOperand(MCOperand::CreateImm(0));
3040 // Rt, Rt2
3041 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3042 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3043 // addr
3044 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3045 // pred
3046 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3047 return true;
3048}
3049
Jim Grosbach623a4542011-08-10 22:42:16 +00003050/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3051/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3052/// when they refer multiple MIOperands inside a single one.
3053bool ARMAsmParser::
3054cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3055 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3056 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3057 // Create a writeback register dummy placeholder.
3058 Inst.addOperand(MCOperand::CreateImm(0));
3059 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3060 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3061 return true;
3062}
3063
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003064/// cvtThumbMultiple- Convert parsed operands to MCInst.
3065/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3066/// when they refer multiple MIOperands inside a single one.
3067bool ARMAsmParser::
3068cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3069 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3070 // The second source operand must be the same register as the destination
3071 // operand.
3072 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003073 (((ARMOperand*)Operands[3])->getReg() !=
3074 ((ARMOperand*)Operands[5])->getReg()) &&
3075 (((ARMOperand*)Operands[3])->getReg() !=
3076 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003077 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003078 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003079 return false;
3080 }
3081 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3082 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3083 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003084 // If we have a three-operand form, use that, else the second source operand
3085 // is just the destination operand again.
3086 if (Operands.size() == 6)
3087 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3088 else
3089 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003090 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3091
3092 return true;
3093}
Jim Grosbach623a4542011-08-10 22:42:16 +00003094
Bill Wendlinge7176102010-11-06 22:36:58 +00003095/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003096/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003097bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003098parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003099 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003100 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003101 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003102 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003103 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003104
Sean Callanan18b83232010-01-19 21:44:56 +00003105 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003106 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003107 if (BaseRegNum == -1)
3108 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003109
Daniel Dunbar05710932011-01-18 05:34:17 +00003110 // The next token must either be a comma or a closing bracket.
3111 const AsmToken &Tok = Parser.getTok();
3112 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003113 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003114
Jim Grosbach7ce05792011-08-03 23:50:40 +00003115 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003116 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003117 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003118
Jim Grosbach7ce05792011-08-03 23:50:40 +00003119 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003120 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003121
Jim Grosbachfb12f352011-09-19 18:42:21 +00003122 // If there's a pre-indexing writeback marker, '!', just add it as a token
3123 // operand. It's rather odd, but syntactically valid.
3124 if (Parser.getTok().is(AsmToken::Exclaim)) {
3125 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3126 Parser.Lex(); // Eat the '!'.
3127 }
3128
Jim Grosbach7ce05792011-08-03 23:50:40 +00003129 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003130 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003131
Jim Grosbach7ce05792011-08-03 23:50:40 +00003132 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3133 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003134
Jim Grosbach57dcb852011-10-11 17:29:55 +00003135 // If we have a ':', it's an alignment specifier.
3136 if (Parser.getTok().is(AsmToken::Colon)) {
3137 Parser.Lex(); // Eat the ':'.
3138 E = Parser.getTok().getLoc();
3139
3140 const MCExpr *Expr;
3141 if (getParser().ParseExpression(Expr))
3142 return true;
3143
3144 // The expression has to be a constant. Memory references with relocations
3145 // don't come through here, as they use the <label> forms of the relevant
3146 // instructions.
3147 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3148 if (!CE)
3149 return Error (E, "constant expression expected");
3150
3151 unsigned Align = 0;
3152 switch (CE->getValue()) {
3153 default:
3154 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3155 case 64: Align = 8; break;
3156 case 128: Align = 16; break;
3157 case 256: Align = 32; break;
3158 }
3159
3160 // Now we should have the closing ']'
3161 E = Parser.getTok().getLoc();
3162 if (Parser.getTok().isNot(AsmToken::RBrac))
3163 return Error(E, "']' expected");
3164 Parser.Lex(); // Eat right bracket token.
3165
3166 // Don't worry about range checking the value here. That's handled by
3167 // the is*() predicates.
3168 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3169 ARM_AM::no_shift, 0, Align,
3170 false, S, E));
3171
3172 // If there's a pre-indexing writeback marker, '!', just add it as a token
3173 // operand.
3174 if (Parser.getTok().is(AsmToken::Exclaim)) {
3175 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3176 Parser.Lex(); // Eat the '!'.
3177 }
3178
3179 return false;
3180 }
3181
3182 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003183 // offset.
3184 if (Parser.getTok().is(AsmToken::Hash)) {
3185 Parser.Lex(); // Eat the '#'.
3186 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003187
Owen Anderson0da10cf2011-08-29 19:36:44 +00003188 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003189 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003190 if (getParser().ParseExpression(Offset))
3191 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003192
3193 // The expression has to be a constant. Memory references with relocations
3194 // don't come through here, as they use the <label> forms of the relevant
3195 // instructions.
3196 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3197 if (!CE)
3198 return Error (E, "constant expression expected");
3199
Owen Anderson0da10cf2011-08-29 19:36:44 +00003200 // If the constant was #-0, represent it as INT32_MIN.
3201 int32_t Val = CE->getValue();
3202 if (isNegative && Val == 0)
3203 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3204
Jim Grosbach7ce05792011-08-03 23:50:40 +00003205 // Now we should have the closing ']'
3206 E = Parser.getTok().getLoc();
3207 if (Parser.getTok().isNot(AsmToken::RBrac))
3208 return Error(E, "']' expected");
3209 Parser.Lex(); // Eat right bracket token.
3210
3211 // Don't worry about range checking the value here. That's handled by
3212 // the is*() predicates.
3213 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003214 ARM_AM::no_shift, 0, 0,
3215 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003216
3217 // If there's a pre-indexing writeback marker, '!', just add it as a token
3218 // operand.
3219 if (Parser.getTok().is(AsmToken::Exclaim)) {
3220 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3221 Parser.Lex(); // Eat the '!'.
3222 }
3223
3224 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003225 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003226
3227 // The register offset is optionally preceded by a '+' or '-'
3228 bool isNegative = false;
3229 if (Parser.getTok().is(AsmToken::Minus)) {
3230 isNegative = true;
3231 Parser.Lex(); // Eat the '-'.
3232 } else if (Parser.getTok().is(AsmToken::Plus)) {
3233 // Nothing to do.
3234 Parser.Lex(); // Eat the '+'.
3235 }
3236
3237 E = Parser.getTok().getLoc();
3238 int OffsetRegNum = tryParseRegister();
3239 if (OffsetRegNum == -1)
3240 return Error(E, "register expected");
3241
3242 // If there's a shift operator, handle it.
3243 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003244 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003245 if (Parser.getTok().is(AsmToken::Comma)) {
3246 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003247 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003248 return true;
3249 }
3250
3251 // Now we should have the closing ']'
3252 E = Parser.getTok().getLoc();
3253 if (Parser.getTok().isNot(AsmToken::RBrac))
3254 return Error(E, "']' expected");
3255 Parser.Lex(); // Eat right bracket token.
3256
3257 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003258 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003259 S, E));
3260
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003261 // If there's a pre-indexing writeback marker, '!', just add it as a token
3262 // operand.
3263 if (Parser.getTok().is(AsmToken::Exclaim)) {
3264 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3265 Parser.Lex(); // Eat the '!'.
3266 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003267
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003268 return false;
3269}
3270
Jim Grosbach7ce05792011-08-03 23:50:40 +00003271/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003272/// ( lsl | lsr | asr | ror ) , # shift_amount
3273/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003274/// return true if it parses a shift otherwise it returns false.
3275bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3276 unsigned &Amount) {
3277 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003278 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003279 if (Tok.isNot(AsmToken::Identifier))
3280 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003281 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003282 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003283 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003284 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003285 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003286 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003287 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003288 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003289 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003290 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003291 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003292 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003293 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003294 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003295
Jim Grosbach7ce05792011-08-03 23:50:40 +00003296 // rrx stands alone.
3297 Amount = 0;
3298 if (St != ARM_AM::rrx) {
3299 Loc = Parser.getTok().getLoc();
3300 // A '#' and a shift amount.
3301 const AsmToken &HashTok = Parser.getTok();
3302 if (HashTok.isNot(AsmToken::Hash))
3303 return Error(HashTok.getLoc(), "'#' expected");
3304 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003305
Jim Grosbach7ce05792011-08-03 23:50:40 +00003306 const MCExpr *Expr;
3307 if (getParser().ParseExpression(Expr))
3308 return true;
3309 // Range check the immediate.
3310 // lsl, ror: 0 <= imm <= 31
3311 // lsr, asr: 0 <= imm <= 32
3312 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3313 if (!CE)
3314 return Error(Loc, "shift amount must be an immediate");
3315 int64_t Imm = CE->getValue();
3316 if (Imm < 0 ||
3317 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3318 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3319 return Error(Loc, "immediate shift value out of range");
3320 Amount = Imm;
3321 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003322
3323 return false;
3324}
3325
Jim Grosbach9d390362011-10-03 23:38:36 +00003326/// parseFPImm - A floating point immediate expression operand.
3327ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3328parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3329 SMLoc S = Parser.getTok().getLoc();
3330
3331 if (Parser.getTok().isNot(AsmToken::Hash))
3332 return MatchOperand_NoMatch;
3333 Parser.Lex(); // Eat the '#'.
3334
3335 // Handle negation, as that still comes through as a separate token.
3336 bool isNegative = false;
3337 if (Parser.getTok().is(AsmToken::Minus)) {
3338 isNegative = true;
3339 Parser.Lex();
3340 }
3341 const AsmToken &Tok = Parser.getTok();
3342 if (Tok.is(AsmToken::Real)) {
3343 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3344 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3345 // If we had a '-' in front, toggle the sign bit.
3346 IntVal ^= (uint64_t)isNegative << 63;
3347 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3348 Parser.Lex(); // Eat the token.
3349 if (Val == -1) {
3350 TokError("floating point value out of range");
3351 return MatchOperand_ParseFail;
3352 }
3353 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3354 return MatchOperand_Success;
3355 }
3356 if (Tok.is(AsmToken::Integer)) {
3357 int64_t Val = Tok.getIntVal();
3358 Parser.Lex(); // Eat the token.
3359 if (Val > 255 || Val < 0) {
3360 TokError("encoded floating point value out of range");
3361 return MatchOperand_ParseFail;
3362 }
3363 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3364 return MatchOperand_Success;
3365 }
3366
3367 TokError("invalid floating point immediate");
3368 return MatchOperand_ParseFail;
3369}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003370/// Parse a arm instruction operand. For now this parses the operand regardless
3371/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003372bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003373 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003374 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003375
3376 // Check if the current operand has a custom associated parser, if so, try to
3377 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003378 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3379 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003380 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003381 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3382 // there was a match, but an error occurred, in which case, just return that
3383 // the operand parsing failed.
3384 if (ResTy == MatchOperand_ParseFail)
3385 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003386
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003387 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003388 default:
3389 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003390 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003391 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003392 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003393 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003394 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003395 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003396 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003397 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003398 else if (Res == -1) // irrecoverable error
3399 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003400 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3401 S = Parser.getTok().getLoc();
3402 Parser.Lex();
3403 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3404 return false;
3405 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003406
3407 // Fall though for the Identifier case that is not a register or a
3408 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003409 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003410 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3411 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003412 // This was not a register so parse other operands that start with an
3413 // identifier (like labels) as expressions and create them as immediates.
3414 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003415 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003416 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003417 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003418 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003419 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3420 return false;
3421 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003422 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003423 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003424 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003425 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003426 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003427 // #42 -> immediate.
3428 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003429 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003430 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003431 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003432 const MCExpr *ImmVal;
3433 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003434 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003435 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3436 if (!CE) {
3437 Error(S, "constant expression expected");
3438 return MatchOperand_ParseFail;
3439 }
3440 int32_t Val = CE->getValue();
3441 if (isNegative && Val == 0)
3442 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003443 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003444 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3445 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003446 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003447 case AsmToken::Colon: {
3448 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003449 // FIXME: Check it's an expression prefix,
3450 // e.g. (FOO - :lower16:BAR) isn't legal.
3451 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003452 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003453 return true;
3454
Evan Cheng75972122011-01-13 07:58:56 +00003455 const MCExpr *SubExprVal;
3456 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003457 return true;
3458
Evan Cheng75972122011-01-13 07:58:56 +00003459 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3460 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003461 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003462 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003463 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003464 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003465 }
3466}
3467
Jim Grosbach1355cf12011-07-26 17:10:22 +00003468// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003469// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003470bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003471 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003472
3473 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003474 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003475 Parser.Lex(); // Eat ':'
3476
3477 if (getLexer().isNot(AsmToken::Identifier)) {
3478 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3479 return true;
3480 }
3481
3482 StringRef IDVal = Parser.getTok().getIdentifier();
3483 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003484 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003485 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003486 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003487 } else {
3488 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3489 return true;
3490 }
3491 Parser.Lex();
3492
3493 if (getLexer().isNot(AsmToken::Colon)) {
3494 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3495 return true;
3496 }
3497 Parser.Lex(); // Eat the last ':'
3498 return false;
3499}
3500
Daniel Dunbar352e1482011-01-11 15:59:50 +00003501/// \brief Given a mnemonic, split out possible predication code and carry
3502/// setting letters to form a canonical mnemonic and flags.
3503//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003504// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003505// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003506StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003507 unsigned &PredicationCode,
3508 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003509 unsigned &ProcessorIMod,
3510 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003511 PredicationCode = ARMCC::AL;
3512 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003513 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003514
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003515 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003516 //
3517 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003518 if ((Mnemonic == "movs" && isThumb()) ||
3519 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3520 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3521 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3522 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3523 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3524 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3525 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003526 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003527
Jim Grosbach3f00e312011-07-11 17:09:57 +00003528 // First, split out any predication code. Ignore mnemonics we know aren't
3529 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003530 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003531 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003532 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003533 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003534 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3535 .Case("eq", ARMCC::EQ)
3536 .Case("ne", ARMCC::NE)
3537 .Case("hs", ARMCC::HS)
3538 .Case("cs", ARMCC::HS)
3539 .Case("lo", ARMCC::LO)
3540 .Case("cc", ARMCC::LO)
3541 .Case("mi", ARMCC::MI)
3542 .Case("pl", ARMCC::PL)
3543 .Case("vs", ARMCC::VS)
3544 .Case("vc", ARMCC::VC)
3545 .Case("hi", ARMCC::HI)
3546 .Case("ls", ARMCC::LS)
3547 .Case("ge", ARMCC::GE)
3548 .Case("lt", ARMCC::LT)
3549 .Case("gt", ARMCC::GT)
3550 .Case("le", ARMCC::LE)
3551 .Case("al", ARMCC::AL)
3552 .Default(~0U);
3553 if (CC != ~0U) {
3554 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3555 PredicationCode = CC;
3556 }
Bill Wendling52925b62010-10-29 23:50:21 +00003557 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003558
Daniel Dunbar352e1482011-01-11 15:59:50 +00003559 // Next, determine if we have a carry setting bit. We explicitly ignore all
3560 // the instructions we know end in 's'.
3561 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003562 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003563 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3564 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3565 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003566 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3567 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003568 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3569 CarrySetting = true;
3570 }
3571
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003572 // The "cps" instruction can have a interrupt mode operand which is glued into
3573 // the mnemonic. Check if this is the case, split it and parse the imod op
3574 if (Mnemonic.startswith("cps")) {
3575 // Split out any imod code.
3576 unsigned IMod =
3577 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3578 .Case("ie", ARM_PROC::IE)
3579 .Case("id", ARM_PROC::ID)
3580 .Default(~0U);
3581 if (IMod != ~0U) {
3582 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3583 ProcessorIMod = IMod;
3584 }
3585 }
3586
Jim Grosbach89df9962011-08-26 21:43:41 +00003587 // The "it" instruction has the condition mask on the end of the mnemonic.
3588 if (Mnemonic.startswith("it")) {
3589 ITMask = Mnemonic.slice(2, Mnemonic.size());
3590 Mnemonic = Mnemonic.slice(0, 2);
3591 }
3592
Daniel Dunbar352e1482011-01-11 15:59:50 +00003593 return Mnemonic;
3594}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003595
3596/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3597/// inclusion of carry set or predication code operands.
3598//
3599// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003600void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003601getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003602 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003603 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3604 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003605 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003606 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003607 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003608 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003609 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003610 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003611 Mnemonic == "mla" || Mnemonic == "smlal" ||
3612 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003613 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003614 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003615 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003616
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003617 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3618 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3619 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3620 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003621 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3622 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003623 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00003624 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
3625 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
3626 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003627 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3628 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003629 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003630 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003631 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003632 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003633
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003634 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003635 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003636 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003637 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003638 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003639}
3640
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003641bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3642 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003643 // FIXME: This is all horribly hacky. We really need a better way to deal
3644 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003645
3646 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3647 // another does not. Specifically, the MOVW instruction does not. So we
3648 // special case it here and remove the defaulted (non-setting) cc_out
3649 // operand if that's the instruction we're trying to match.
3650 //
3651 // We do this as post-processing of the explicit operands rather than just
3652 // conditionally adding the cc_out in the first place because we need
3653 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003654 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003655 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3656 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3657 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3658 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003659
3660 // Register-register 'add' for thumb does not have a cc_out operand
3661 // when there are only two register operands.
3662 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3663 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3664 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3665 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3666 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003667 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003668 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3669 // have to check the immediate range here since Thumb2 has a variant
3670 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003671 if (((isThumb() && Mnemonic == "add") ||
3672 (isThumbTwo() && Mnemonic == "sub")) &&
3673 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003674 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3675 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3676 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003677 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3678 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3679 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003680 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003681 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3682 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003683 // selecting via the generic "add" mnemonic, so to know that we
3684 // should remove the cc_out operand, we have to explicitly check that
3685 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003686 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3687 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003688 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3689 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3690 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3691 // Nest conditions rather than one big 'if' statement for readability.
3692 //
3693 // If either register is a high reg, it's either one of the SP
3694 // variants (handled above) or a 32-bit encoding, so we just
3695 // check against T3.
3696 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3697 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3698 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3699 return false;
3700 // If both registers are low, we're in an IT block, and the immediate is
3701 // in range, we should use encoding T1 instead, which has a cc_out.
3702 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003703 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003704 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3705 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3706 return false;
3707
3708 // Otherwise, we use encoding T4, which does not have a cc_out
3709 // operand.
3710 return true;
3711 }
3712
Jim Grosbach64944f42011-09-14 21:00:40 +00003713 // The thumb2 multiply instruction doesn't have a CCOut register, so
3714 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3715 // use the 16-bit encoding or not.
3716 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3717 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3718 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3719 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3720 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3721 // If the registers aren't low regs, the destination reg isn't the
3722 // same as one of the source regs, or the cc_out operand is zero
3723 // outside of an IT block, we have to use the 32-bit encoding, so
3724 // remove the cc_out operand.
3725 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3726 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3727 !inITBlock() ||
3728 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3729 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3730 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3731 static_cast<ARMOperand*>(Operands[4])->getReg())))
3732 return true;
3733
3734
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003735
Jim Grosbachf69c8042011-08-24 21:42:27 +00003736 // Register-register 'add/sub' for thumb does not have a cc_out operand
3737 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3738 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3739 // right, this will result in better diagnostics (which operand is off)
3740 // anyway.
3741 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3742 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003743 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3744 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3745 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3746 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003747
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003748 return false;
3749}
3750
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003751/// Parse an arm instruction mnemonic followed by its operands.
3752bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3753 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3754 // Create the leading tokens for the mnemonic, split by '.' characters.
3755 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003756 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003757
Daniel Dunbar352e1482011-01-11 15:59:50 +00003758 // Split out the predication code and carry setting flag from the mnemonic.
3759 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003760 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003761 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003762 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003763 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003764 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003765
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003766 // In Thumb1, only the branch (B) instruction can be predicated.
3767 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3768 Parser.EatToEndOfStatement();
3769 return Error(NameLoc, "conditional execution not supported in Thumb1");
3770 }
3771
Jim Grosbachffa32252011-07-19 19:13:28 +00003772 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3773
Jim Grosbach89df9962011-08-26 21:43:41 +00003774 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3775 // is the mask as it will be for the IT encoding if the conditional
3776 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3777 // where the conditional bit0 is zero, the instruction post-processing
3778 // will adjust the mask accordingly.
3779 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003780 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3781 if (ITMask.size() > 3) {
3782 Parser.EatToEndOfStatement();
3783 return Error(Loc, "too many conditions on IT instruction");
3784 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003785 unsigned Mask = 8;
3786 for (unsigned i = ITMask.size(); i != 0; --i) {
3787 char pos = ITMask[i - 1];
3788 if (pos != 't' && pos != 'e') {
3789 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003790 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003791 }
3792 Mask >>= 1;
3793 if (ITMask[i - 1] == 't')
3794 Mask |= 8;
3795 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003796 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003797 }
3798
Jim Grosbachffa32252011-07-19 19:13:28 +00003799 // FIXME: This is all a pretty gross hack. We should automatically handle
3800 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003801
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003802 // Next, add the CCOut and ConditionCode operands, if needed.
3803 //
3804 // For mnemonics which can ever incorporate a carry setting bit or predication
3805 // code, our matching model involves us always generating CCOut and
3806 // ConditionCode operands to match the mnemonic "as written" and then we let
3807 // the matcher deal with finding the right instruction or generating an
3808 // appropriate error.
3809 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003810 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003811
Jim Grosbach33c16a22011-07-14 22:04:21 +00003812 // If we had a carry-set on an instruction that can't do that, issue an
3813 // error.
3814 if (!CanAcceptCarrySet && CarrySetting) {
3815 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003816 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003817 "' can not set flags, but 's' suffix specified");
3818 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003819 // If we had a predication code on an instruction that can't do that, issue an
3820 // error.
3821 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3822 Parser.EatToEndOfStatement();
3823 return Error(NameLoc, "instruction '" + Mnemonic +
3824 "' is not predicable, but condition code specified");
3825 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003826
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003827 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003828 if (CanAcceptCarrySet) {
3829 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003830 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003831 Loc));
3832 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003833
3834 // Add the predication code operand, if necessary.
3835 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003836 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3837 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003838 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003839 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003840 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003841
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003842 // Add the processor imod operand, if necessary.
3843 if (ProcessorIMod) {
3844 Operands.push_back(ARMOperand::CreateImm(
3845 MCConstantExpr::Create(ProcessorIMod, getContext()),
3846 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003847 }
3848
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003849 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003850 while (Next != StringRef::npos) {
3851 Start = Next;
3852 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003853 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003854
Jim Grosbach4d23e992011-08-24 22:19:48 +00003855 // For now, we're only parsing Thumb1 (for the most part), so
3856 // just ignore ".n" qualifiers. We'll use them to restrict
3857 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003858 if (ExtraToken != ".n") {
3859 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3860 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3861 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003862 }
3863
3864 // Read the remaining operands.
3865 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003866 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003867 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003868 Parser.EatToEndOfStatement();
3869 return true;
3870 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003871
3872 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003873 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003874
3875 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003876 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003877 Parser.EatToEndOfStatement();
3878 return true;
3879 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003880 }
3881 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003882
Chris Lattnercbf8a982010-09-11 16:18:25 +00003883 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00003884 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00003885 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00003886 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003887 }
Bill Wendling146018f2010-11-06 21:42:12 +00003888
Chris Lattner34e53142010-09-08 05:10:46 +00003889 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003890
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003891 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3892 // do and don't have a cc_out optional-def operand. With some spot-checks
3893 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003894 // parse and adjust accordingly before actually matching. We shouldn't ever
3895 // try to remove a cc_out operand that was explicitly set on the the
3896 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3897 // table driven matcher doesn't fit well with the ARM instruction set.
3898 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003899 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3900 Operands.erase(Operands.begin() + 1);
3901 delete Op;
3902 }
3903
Jim Grosbachcf121c32011-07-28 21:57:55 +00003904 // ARM mode 'blx' need special handling, as the register operand version
3905 // is predicable, but the label operand version is not. So, we can't rely
3906 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00003907 // a k_CondCode operand in the list. If we're trying to match the label
3908 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00003909 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3910 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3911 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3912 Operands.erase(Operands.begin() + 1);
3913 delete Op;
3914 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003915
3916 // The vector-compare-to-zero instructions have a literal token "#0" at
3917 // the end that comes to here as an immediate operand. Convert it to a
3918 // token to play nicely with the matcher.
3919 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3920 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3921 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3922 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3923 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3924 if (CE && CE->getValue() == 0) {
3925 Operands.erase(Operands.begin() + 5);
3926 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3927 delete Op;
3928 }
3929 }
Jim Grosbach68259142011-10-03 22:30:24 +00003930 // VCMP{E} does the same thing, but with a different operand count.
3931 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3932 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3933 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3934 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3935 if (CE && CE->getValue() == 0) {
3936 Operands.erase(Operands.begin() + 4);
3937 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3938 delete Op;
3939 }
3940 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003941 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3942 // end. Convert it to a token here.
3943 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3944 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3945 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3946 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3947 if (CE && CE->getValue() == 0) {
3948 Operands.erase(Operands.begin() + 5);
3949 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3950 delete Op;
3951 }
3952 }
3953
Chris Lattner98986712010-01-14 22:21:20 +00003954 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003955}
3956
Jim Grosbach189610f2011-07-26 18:25:39 +00003957// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003958
3959// return 'true' if register list contains non-low GPR registers,
3960// 'false' otherwise. If Reg is in the register list or is HiReg, set
3961// 'containsReg' to true.
3962static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3963 unsigned HiReg, bool &containsReg) {
3964 containsReg = false;
3965 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3966 unsigned OpReg = Inst.getOperand(i).getReg();
3967 if (OpReg == Reg)
3968 containsReg = true;
3969 // Anything other than a low register isn't legal here.
3970 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3971 return true;
3972 }
3973 return false;
3974}
3975
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003976// Check if the specified regisgter is in the register list of the inst,
3977// starting at the indicated operand number.
3978static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3979 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3980 unsigned OpReg = Inst.getOperand(i).getReg();
3981 if (OpReg == Reg)
3982 return true;
3983 }
3984 return false;
3985}
3986
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003987// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3988// the ARMInsts array) instead. Getting that here requires awkward
3989// API changes, though. Better way?
3990namespace llvm {
3991extern MCInstrDesc ARMInsts[];
3992}
3993static MCInstrDesc &getInstDesc(unsigned Opcode) {
3994 return ARMInsts[Opcode];
3995}
3996
Jim Grosbach189610f2011-07-26 18:25:39 +00003997// FIXME: We would really like to be able to tablegen'erate this.
3998bool ARMAsmParser::
3999validateInstruction(MCInst &Inst,
4000 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004001 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
4002 SMLoc Loc = Operands[0]->getStartLoc();
4003 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004004 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4005 // being allowed in IT blocks, but not being predicable. It just always
4006 // executes.
4007 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004008 unsigned bit = 1;
4009 if (ITState.FirstCond)
4010 ITState.FirstCond = false;
4011 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004012 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004013 // The instruction must be predicable.
4014 if (!MCID.isPredicable())
4015 return Error(Loc, "instructions in IT block must be predicable");
4016 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4017 unsigned ITCond = bit ? ITState.Cond :
4018 ARMCC::getOppositeCondition(ITState.Cond);
4019 if (Cond != ITCond) {
4020 // Find the condition code Operand to get its SMLoc information.
4021 SMLoc CondLoc;
4022 for (unsigned i = 1; i < Operands.size(); ++i)
4023 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4024 CondLoc = Operands[i]->getStartLoc();
4025 return Error(CondLoc, "incorrect condition in IT block; got '" +
4026 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4027 "', but expected '" +
4028 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4029 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004030 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004031 } else if (isThumbTwo() && MCID.isPredicable() &&
4032 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004033 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4034 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004035 return Error(Loc, "predicated instructions must be in IT block");
4036
Jim Grosbach189610f2011-07-26 18:25:39 +00004037 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004038 case ARM::LDRD:
4039 case ARM::LDRD_PRE:
4040 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004041 case ARM::LDREXD: {
4042 // Rt2 must be Rt + 1.
4043 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4044 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4045 if (Rt2 != Rt + 1)
4046 return Error(Operands[3]->getStartLoc(),
4047 "destination operands must be sequential");
4048 return false;
4049 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004050 case ARM::STRD: {
4051 // Rt2 must be Rt + 1.
4052 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4053 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4054 if (Rt2 != Rt + 1)
4055 return Error(Operands[3]->getStartLoc(),
4056 "source operands must be sequential");
4057 return false;
4058 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004059 case ARM::STRD_PRE:
4060 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004061 case ARM::STREXD: {
4062 // Rt2 must be Rt + 1.
4063 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4064 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4065 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004066 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004067 "source operands must be sequential");
4068 return false;
4069 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004070 case ARM::SBFX:
4071 case ARM::UBFX: {
4072 // width must be in range [1, 32-lsb]
4073 unsigned lsb = Inst.getOperand(2).getImm();
4074 unsigned widthm1 = Inst.getOperand(3).getImm();
4075 if (widthm1 >= 32 - lsb)
4076 return Error(Operands[5]->getStartLoc(),
4077 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004078 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004079 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004080 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004081 // If we're parsing Thumb2, the .w variant is available and handles
4082 // most cases that are normally illegal for a Thumb1 LDM
4083 // instruction. We'll make the transformation in processInstruction()
4084 // if necessary.
4085 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004086 // Thumb LDM instructions are writeback iff the base register is not
4087 // in the register list.
4088 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004089 bool hasWritebackToken =
4090 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4091 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004092 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004093 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004094 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4095 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004096 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004097 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004098 return Error(Operands[2]->getStartLoc(),
4099 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004100 // If we should not have writeback, there must not be a '!'. This is
4101 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004102 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004103 return Error(Operands[3]->getStartLoc(),
4104 "writeback operator '!' not allowed when base register "
4105 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004106
4107 break;
4108 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004109 case ARM::t2LDMIA_UPD: {
4110 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4111 return Error(Operands[4]->getStartLoc(),
4112 "writeback operator '!' not allowed when base register "
4113 "in register list");
4114 break;
4115 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004116 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004117 bool listContainsBase;
4118 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4119 return Error(Operands[2]->getStartLoc(),
4120 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004121 break;
4122 }
4123 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004124 bool listContainsBase;
4125 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4126 return Error(Operands[2]->getStartLoc(),
4127 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004128 break;
4129 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004130 case ARM::tSTMIA_UPD: {
4131 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004132 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004133 return Error(Operands[4]->getStartLoc(),
4134 "registers must be in range r0-r7");
4135 break;
4136 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004137 }
4138
4139 return false;
4140}
4141
Jim Grosbachf8fce712011-08-11 17:35:48 +00004142void ARMAsmParser::
4143processInstruction(MCInst &Inst,
4144 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4145 switch (Inst.getOpcode()) {
4146 case ARM::LDMIA_UPD:
4147 // If this is a load of a single register via a 'pop', then we should use
4148 // a post-indexed LDR instruction instead, per the ARM ARM.
4149 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4150 Inst.getNumOperands() == 5) {
4151 MCInst TmpInst;
4152 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4153 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4154 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4155 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4156 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4157 TmpInst.addOperand(MCOperand::CreateImm(4));
4158 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4159 TmpInst.addOperand(Inst.getOperand(3));
4160 Inst = TmpInst;
4161 }
4162 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004163 case ARM::STMDB_UPD:
4164 // If this is a store of a single register via a 'push', then we should use
4165 // a pre-indexed STR instruction instead, per the ARM ARM.
4166 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4167 Inst.getNumOperands() == 5) {
4168 MCInst TmpInst;
4169 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4170 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4171 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4172 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4173 TmpInst.addOperand(MCOperand::CreateImm(-4));
4174 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4175 TmpInst.addOperand(Inst.getOperand(3));
4176 Inst = TmpInst;
4177 }
4178 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004179 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004180 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4181 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4182 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4183 // to encoding T1 if <Rd> is omitted."
4184 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004185 Inst.setOpcode(ARM::tADDi3);
4186 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004187 case ARM::tSUBi8:
4188 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4189 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4190 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4191 // to encoding T1 if <Rd> is omitted."
4192 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4193 Inst.setOpcode(ARM::tSUBi3);
4194 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004195 case ARM::tB:
4196 // A Thumb conditional branch outside of an IT block is a tBcc.
4197 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4198 Inst.setOpcode(ARM::tBcc);
4199 break;
4200 case ARM::t2B:
4201 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4202 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4203 Inst.setOpcode(ARM::t2Bcc);
4204 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004205 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004206 // If the conditional is AL or we're in an IT block, we really want t2B.
4207 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004208 Inst.setOpcode(ARM::t2B);
4209 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004210 case ARM::tBcc:
4211 // If the conditional is AL, we really want tB.
4212 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4213 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004214 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004215 case ARM::tLDMIA: {
4216 // If the register list contains any high registers, or if the writeback
4217 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4218 // instead if we're in Thumb2. Otherwise, this should have generated
4219 // an error in validateInstruction().
4220 unsigned Rn = Inst.getOperand(0).getReg();
4221 bool hasWritebackToken =
4222 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4223 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4224 bool listContainsBase;
4225 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4226 (!listContainsBase && !hasWritebackToken) ||
4227 (listContainsBase && hasWritebackToken)) {
4228 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4229 assert (isThumbTwo());
4230 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4231 // If we're switching to the updating version, we need to insert
4232 // the writeback tied operand.
4233 if (hasWritebackToken)
4234 Inst.insert(Inst.begin(),
4235 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4236 }
4237 break;
4238 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004239 case ARM::tSTMIA_UPD: {
4240 // If the register list contains any high registers, we need to use
4241 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4242 // should have generated an error in validateInstruction().
4243 unsigned Rn = Inst.getOperand(0).getReg();
4244 bool listContainsBase;
4245 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4246 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4247 assert (isThumbTwo());
4248 Inst.setOpcode(ARM::t2STMIA_UPD);
4249 }
4250 break;
4251 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004252 case ARM::t2MOVi: {
4253 // If we can use the 16-bit encoding and the user didn't explicitly
4254 // request the 32-bit variant, transform it here.
4255 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4256 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004257 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4258 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4259 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004260 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4261 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4262 // The operands aren't in the same order for tMOVi8...
4263 MCInst TmpInst;
4264 TmpInst.setOpcode(ARM::tMOVi8);
4265 TmpInst.addOperand(Inst.getOperand(0));
4266 TmpInst.addOperand(Inst.getOperand(4));
4267 TmpInst.addOperand(Inst.getOperand(1));
4268 TmpInst.addOperand(Inst.getOperand(2));
4269 TmpInst.addOperand(Inst.getOperand(3));
4270 Inst = TmpInst;
4271 }
4272 break;
4273 }
4274 case ARM::t2MOVr: {
4275 // If we can use the 16-bit encoding and the user didn't explicitly
4276 // request the 32-bit variant, transform it here.
4277 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4278 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4279 Inst.getOperand(2).getImm() == ARMCC::AL &&
4280 Inst.getOperand(4).getReg() == ARM::CPSR &&
4281 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4282 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4283 // The operands aren't the same for tMOV[S]r... (no cc_out)
4284 MCInst TmpInst;
4285 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4286 TmpInst.addOperand(Inst.getOperand(0));
4287 TmpInst.addOperand(Inst.getOperand(1));
4288 TmpInst.addOperand(Inst.getOperand(2));
4289 TmpInst.addOperand(Inst.getOperand(3));
4290 Inst = TmpInst;
4291 }
4292 break;
4293 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004294 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004295 case ARM::t2SXTB:
4296 case ARM::t2UXTH:
4297 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004298 // If we can use the 16-bit encoding and the user didn't explicitly
4299 // request the 32-bit variant, transform it here.
4300 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4301 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4302 Inst.getOperand(2).getImm() == 0 &&
4303 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4304 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004305 unsigned NewOpc;
4306 switch (Inst.getOpcode()) {
4307 default: llvm_unreachable("Illegal opcode!");
4308 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4309 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4310 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4311 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4312 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004313 // The operands aren't the same for thumb1 (no rotate operand).
4314 MCInst TmpInst;
4315 TmpInst.setOpcode(NewOpc);
4316 TmpInst.addOperand(Inst.getOperand(0));
4317 TmpInst.addOperand(Inst.getOperand(1));
4318 TmpInst.addOperand(Inst.getOperand(3));
4319 TmpInst.addOperand(Inst.getOperand(4));
4320 Inst = TmpInst;
4321 }
4322 break;
4323 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004324 case ARM::t2IT: {
4325 // The mask bits for all but the first condition are represented as
4326 // the low bit of the condition code value implies 't'. We currently
4327 // always have 1 implies 't', so XOR toggle the bits if the low bit
4328 // of the condition code is zero. The encoding also expects the low
4329 // bit of the condition to be encoded as bit 4 of the mask operand,
4330 // so mask that in if needed
4331 MCOperand &MO = Inst.getOperand(1);
4332 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004333 unsigned OrigMask = Mask;
4334 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004335 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004336 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4337 for (unsigned i = 3; i != TZ; --i)
4338 Mask ^= 1 << i;
4339 } else
4340 Mask |= 0x10;
4341 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004342
4343 // Set up the IT block state according to the IT instruction we just
4344 // matched.
4345 assert(!inITBlock() && "nested IT blocks?!");
4346 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4347 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4348 ITState.CurPosition = 0;
4349 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004350 break;
4351 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004352 }
4353}
4354
Jim Grosbach47a0d522011-08-16 20:45:50 +00004355unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4356 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4357 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004358 unsigned Opc = Inst.getOpcode();
4359 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004360 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4361 assert(MCID.hasOptionalDef() &&
4362 "optionally flag setting instruction missing optional def operand");
4363 assert(MCID.NumOperands == Inst.getNumOperands() &&
4364 "operand count mismatch!");
4365 // Find the optional-def operand (cc_out).
4366 unsigned OpNo;
4367 for (OpNo = 0;
4368 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4369 ++OpNo)
4370 ;
4371 // If we're parsing Thumb1, reject it completely.
4372 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4373 return Match_MnemonicFail;
4374 // If we're parsing Thumb2, which form is legal depends on whether we're
4375 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004376 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4377 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004378 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004379 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4380 inITBlock())
4381 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004382 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004383 // Some high-register supporting Thumb1 encodings only allow both registers
4384 // to be from r0-r7 when in Thumb2.
4385 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4386 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4387 isARMLowRegister(Inst.getOperand(2).getReg()))
4388 return Match_RequiresThumb2;
4389 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004390 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004391 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4392 isARMLowRegister(Inst.getOperand(1).getReg()))
4393 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004394 return Match_Success;
4395}
4396
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004397bool ARMAsmParser::
4398MatchAndEmitInstruction(SMLoc IDLoc,
4399 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4400 MCStreamer &Out) {
4401 MCInst Inst;
4402 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004403 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004404 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004405 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004406 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004407 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004408 // Context sensitive operand constraints aren't handled by the matcher,
4409 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004410 if (validateInstruction(Inst, Operands)) {
4411 // Still progress the IT block, otherwise one wrong condition causes
4412 // nasty cascading errors.
4413 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004414 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004415 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004416
Jim Grosbachf8fce712011-08-11 17:35:48 +00004417 // Some instructions need post-processing to, for example, tweak which
4418 // encoding is selected.
4419 processInstruction(Inst, Operands);
4420
Jim Grosbacha1109882011-09-02 23:22:08 +00004421 // Only move forward at the very end so that everything in validate
4422 // and process gets a consistent answer about whether we're in an IT
4423 // block.
4424 forwardITPosition();
4425
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004426 Out.EmitInstruction(Inst);
4427 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004428 case Match_MissingFeature:
4429 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4430 return true;
4431 case Match_InvalidOperand: {
4432 SMLoc ErrorLoc = IDLoc;
4433 if (ErrorInfo != ~0U) {
4434 if (ErrorInfo >= Operands.size())
4435 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004436
Chris Lattnere73d4f82010-10-28 21:41:58 +00004437 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4438 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4439 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004440
Chris Lattnere73d4f82010-10-28 21:41:58 +00004441 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004442 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004443 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004444 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004445 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004446 // The converter function will have already emited a diagnostic.
4447 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004448 case Match_RequiresNotITBlock:
4449 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004450 case Match_RequiresITBlock:
4451 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004452 case Match_RequiresV6:
4453 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4454 case Match_RequiresThumb2:
4455 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004456 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004457
Eric Christopherc223e2b2010-10-29 09:26:59 +00004458 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004459 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004460}
4461
Jim Grosbach1355cf12011-07-26 17:10:22 +00004462/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004463bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4464 StringRef IDVal = DirectiveID.getIdentifier();
4465 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004466 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004467 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004468 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004469 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004470 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004471 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004472 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004473 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004474 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004475 return true;
4476}
4477
Jim Grosbach1355cf12011-07-26 17:10:22 +00004478/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004479/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004480bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004481 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4482 for (;;) {
4483 const MCExpr *Value;
4484 if (getParser().ParseExpression(Value))
4485 return true;
4486
Chris Lattneraaec2052010-01-19 19:46:13 +00004487 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004488
4489 if (getLexer().is(AsmToken::EndOfStatement))
4490 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004491
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004492 // FIXME: Improve diagnostic.
4493 if (getLexer().isNot(AsmToken::Comma))
4494 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004495 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004496 }
4497 }
4498
Sean Callananb9a25b72010-01-19 20:27:46 +00004499 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004500 return false;
4501}
4502
Jim Grosbach1355cf12011-07-26 17:10:22 +00004503/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004504/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004505bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004506 if (getLexer().isNot(AsmToken::EndOfStatement))
4507 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004508 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004509
4510 // TODO: set thumb mode
4511 // TODO: tell the MC streamer the mode
4512 // getParser().getStreamer().Emit???();
4513 return false;
4514}
4515
Jim Grosbach1355cf12011-07-26 17:10:22 +00004516/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004517/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004518bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004519 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4520 bool isMachO = MAI.hasSubsectionsViaSymbols();
4521 StringRef Name;
4522
4523 // Darwin asm has function name after .thumb_func direction
4524 // ELF doesn't
4525 if (isMachO) {
4526 const AsmToken &Tok = Parser.getTok();
4527 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4528 return Error(L, "unexpected token in .thumb_func directive");
4529 Name = Tok.getString();
4530 Parser.Lex(); // Consume the identifier token.
4531 }
4532
Kevin Enderby515d5092009-10-15 20:48:48 +00004533 if (getLexer().isNot(AsmToken::EndOfStatement))
4534 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004535 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004536
Rafael Espindola64695402011-05-16 16:17:21 +00004537 // FIXME: assuming function name will be the line following .thumb_func
4538 if (!isMachO) {
4539 Name = Parser.getTok().getString();
4540 }
4541
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004542 // Mark symbol as a thumb symbol.
4543 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4544 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004545 return false;
4546}
4547
Jim Grosbach1355cf12011-07-26 17:10:22 +00004548/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004549/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004550bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004551 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004552 if (Tok.isNot(AsmToken::Identifier))
4553 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004554 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004555 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004556 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004557 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004558 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004559 else
4560 return Error(L, "unrecognized syntax mode in .syntax directive");
4561
4562 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004563 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004564 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004565
4566 // TODO tell the MC streamer the mode
4567 // getParser().getStreamer().Emit???();
4568 return false;
4569}
4570
Jim Grosbach1355cf12011-07-26 17:10:22 +00004571/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004572/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004573bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004574 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004575 if (Tok.isNot(AsmToken::Integer))
4576 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004577 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004578 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004579 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004580 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004581 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004582 else
4583 return Error(L, "invalid operand to .code directive");
4584
4585 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004586 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004587 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004588
Evan Cheng32869202011-07-08 22:36:29 +00004589 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004590 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004591 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004592 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004593 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004594 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004595 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004596 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004597 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004598
Kevin Enderby515d5092009-10-15 20:48:48 +00004599 return false;
4600}
4601
Sean Callanan90b70972010-04-07 20:29:34 +00004602extern "C" void LLVMInitializeARMAsmLexer();
4603
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004604/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004605extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004606 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4607 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004608 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004609}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004610
Chris Lattner0692ee62010-09-06 19:11:01 +00004611#define GET_REGISTER_MATCHER
4612#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004613#include "ARMGenAsmMatcher.inc"