blob: 0abfabefc72113e8750807351d492d3c1b69e04e [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*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000164 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000165
166 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000167 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
168 const SmallVectorImpl<MCParsedAsmOperand*> &);
169 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000171 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000173 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000175 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000177 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000179 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000181 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000183 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000185 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
187 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000193 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000195 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000197 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000199 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000201 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
203 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000205 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
207 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000209
210 bool validateInstruction(MCInst &Inst,
211 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000212 void processInstruction(MCInst &Inst,
213 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000214 bool shouldOmitCCOutOperand(StringRef Mnemonic,
215 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000216
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000217public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000218 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000219 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000220 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000221 Match_RequiresV6,
222 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000223 };
224
Evan Chengffc0e732011-07-09 05:47:46 +0000225 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000226 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000227 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000228
Evan Chengebdeeab2011-07-08 01:53:10 +0000229 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000230 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000231
232 // Not in an ITBlock to start with.
233 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000234 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000235
Jim Grosbach1355cf12011-07-26 17:10:22 +0000236 // Implementation of the MCTargetAsmParser interface:
237 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
238 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000239 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000240 bool ParseDirective(AsmToken DirectiveID);
241
Jim Grosbach47a0d522011-08-16 20:45:50 +0000242 unsigned checkTargetMatchPredicate(MCInst &Inst);
243
Jim Grosbach1355cf12011-07-26 17:10:22 +0000244 bool MatchAndEmitInstruction(SMLoc IDLoc,
245 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
246 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000247};
Jim Grosbach16c74252010-10-29 14:46:02 +0000248} // end anonymous namespace
249
Chris Lattner3a697562010-10-28 17:20:03 +0000250namespace {
251
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000252/// ARMOperand - Instances of this class represent a parsed ARM machine
253/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000254class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000255 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000256 k_CondCode,
257 k_CCOut,
258 k_ITCondMask,
259 k_CoprocNum,
260 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000261 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000262 k_Immediate,
263 k_FPImmediate,
264 k_MemBarrierOpt,
265 k_Memory,
266 k_PostIndexRegister,
267 k_MSRMask,
268 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000269 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000270 k_Register,
271 k_RegisterList,
272 k_DPRRegisterList,
273 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000274 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000275 k_ShiftedRegister,
276 k_ShiftedImmediate,
277 k_ShifterImmediate,
278 k_RotateImmediate,
279 k_BitfieldDescriptor,
280 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000281 } Kind;
282
Sean Callanan76264762010-04-02 22:27:05 +0000283 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000284 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000285
286 union {
287 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000288 ARMCC::CondCodes Val;
289 } CC;
290
291 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000292 unsigned Val;
293 } Cop;
294
295 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000296 unsigned Val;
297 } CoprocOption;
298
299 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000300 unsigned Mask:4;
301 } ITMask;
302
303 struct {
304 ARM_MB::MemBOpt Val;
305 } MBOpt;
306
307 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000308 ARM_PROC::IFlags Val;
309 } IFlags;
310
311 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000312 unsigned Val;
313 } MMask;
314
315 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000316 const char *Data;
317 unsigned Length;
318 } Tok;
319
320 struct {
321 unsigned RegNum;
322 } Reg;
323
Jim Grosbach862019c2011-10-18 23:02:30 +0000324 // A vector register list is a sequential list of 1 to 4 registers.
325 struct {
326 unsigned RegNum;
327 unsigned Count;
328 } VectorList;
329
Bill Wendling8155e5b2010-11-06 22:19:43 +0000330 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000331 unsigned Val;
332 } VectorIndex;
333
334 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000335 const MCExpr *Val;
336 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000337
Jim Grosbach9d390362011-10-03 23:38:36 +0000338 struct {
339 unsigned Val; // encoded 8-bit representation
340 } FPImm;
341
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000342 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000343 struct {
344 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000345 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
346 // was specified.
347 const MCConstantExpr *OffsetImm; // Offset immediate value
348 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
349 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000350 unsigned ShiftImm; // shift for OffsetReg.
351 unsigned Alignment; // 0 = no alignment specified
352 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000353 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000354 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000355
356 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000357 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000358 bool isAdd;
359 ARM_AM::ShiftOpc ShiftTy;
360 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000361 } PostIdxReg;
362
363 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000364 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000365 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000366 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000367 struct {
368 ARM_AM::ShiftOpc ShiftTy;
369 unsigned SrcReg;
370 unsigned ShiftReg;
371 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000372 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000373 struct {
374 ARM_AM::ShiftOpc ShiftTy;
375 unsigned SrcReg;
376 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000377 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000378 struct {
379 unsigned Imm;
380 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000381 struct {
382 unsigned LSB;
383 unsigned Width;
384 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000385 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000386
Bill Wendling146018f2010-11-06 21:42:12 +0000387 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
388public:
Sean Callanan76264762010-04-02 22:27:05 +0000389 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
390 Kind = o.Kind;
391 StartLoc = o.StartLoc;
392 EndLoc = o.EndLoc;
393 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000394 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000395 CC = o.CC;
396 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000397 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000398 ITMask = o.ITMask;
399 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000400 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000401 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_CCOut:
404 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000405 Reg = o.Reg;
406 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000407 case k_RegisterList:
408 case k_DPRRegisterList:
409 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000410 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000411 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000412 case k_VectorList:
413 VectorList = o.VectorList;
414 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000415 case k_CoprocNum:
416 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000417 Cop = o.Cop;
418 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000419 case k_CoprocOption:
420 CoprocOption = o.CoprocOption;
421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000423 Imm = o.Imm;
424 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000425 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000426 FPImm = o.FPImm;
427 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000428 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000429 MBOpt = o.MBOpt;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000432 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000433 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000434 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000435 PostIdxReg = o.PostIdxReg;
436 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000437 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000438 MMask = o.MMask;
439 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000440 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000441 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000442 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000443 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000444 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000447 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000450 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000453 RotImm = o.RotImm;
454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000456 Bitfield = o.Bitfield;
457 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000458 case k_VectorIndex:
459 VectorIndex = o.VectorIndex;
460 break;
Sean Callanan76264762010-04-02 22:27:05 +0000461 }
462 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000463
Sean Callanan76264762010-04-02 22:27:05 +0000464 /// getStartLoc - Get the location of the first token of this operand.
465 SMLoc getStartLoc() const { return StartLoc; }
466 /// getEndLoc - Get the location of the last token of this operand.
467 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000468
Daniel Dunbar8462b302010-08-11 06:36:53 +0000469 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000470 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000471 return CC.Val;
472 }
473
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000474 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000475 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000476 return Cop.Val;
477 }
478
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000479 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000480 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000481 return StringRef(Tok.Data, Tok.Length);
482 }
483
484 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000485 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000486 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 }
488
Bill Wendling5fa22a12010-11-09 23:28:44 +0000489 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000490 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
491 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000492 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000493 }
494
Kevin Enderbycfe07242009-10-13 22:19:02 +0000495 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000497 return Imm.Val;
498 }
499
Jim Grosbach9d390362011-10-03 23:38:36 +0000500 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000502 return FPImm.Val;
503 }
504
Jim Grosbach460a9052011-10-07 23:56:00 +0000505 unsigned getVectorIndex() const {
506 assert(Kind == k_VectorIndex && "Invalid access!");
507 return VectorIndex.Val;
508 }
509
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000510 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000511 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000512 return MBOpt.Val;
513 }
514
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000515 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000516 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000517 return IFlags.Val;
518 }
519
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000520 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000521 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000522 return MMask.Val;
523 }
524
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000525 bool isCoprocNum() const { return Kind == k_CoprocNum; }
526 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000527 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000528 bool isCondCode() const { return Kind == k_CondCode; }
529 bool isCCOut() const { return Kind == k_CCOut; }
530 bool isITMask() const { return Kind == k_ITCondMask; }
531 bool isITCondCode() const { return Kind == k_CondCode; }
532 bool isImm() const { return Kind == k_Immediate; }
533 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000534 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000535 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000536 return false;
537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
538 if (!CE) return false;
539 int64_t Value = CE->getValue();
540 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
541 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000542 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
549 }
550 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
557 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000558 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return Value >= 0 && Value < 256;
565 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000566 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value >= 0 && Value < 8;
573 }
574 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 16;
581 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000582 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000583 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 32;
589 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000590 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value > 0 && Value < 17;
597 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000598 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value > 0 && Value < 33;
605 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000606 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 65536;
613 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000614 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 // If it's not a constant expression, it'll generate a fixup and be
619 // handled later.
620 if (!CE) return true;
621 int64_t Value = CE->getValue();
622 return Value >= 0 && Value < 65536;
623 }
Jim Grosbached838482011-07-26 16:24:27 +0000624 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000625 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000626 return false;
627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
628 if (!CE) return false;
629 int64_t Value = CE->getValue();
630 return Value >= 0 && Value <= 0xffffff;
631 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000632 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000633 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000634 return false;
635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
636 if (!CE) return false;
637 int64_t Value = CE->getValue();
638 return Value > 0 && Value < 33;
639 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000640 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000641 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000642 return false;
643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644 if (!CE) return false;
645 int64_t Value = CE->getValue();
646 return Value >= 0 && Value < 32;
647 }
648 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000649 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000650 return false;
651 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
652 if (!CE) return false;
653 int64_t Value = CE->getValue();
654 return Value > 0 && Value <= 32;
655 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000656 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000657 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000658 return false;
659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
660 if (!CE) return false;
661 int64_t Value = CE->getValue();
662 return ARM_AM::getSOImmVal(Value) != -1;
663 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000664 bool isARMSOImmNot() const {
665 if (Kind != k_Immediate)
666 return false;
667 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
668 if (!CE) return false;
669 int64_t Value = CE->getValue();
670 return ARM_AM::getSOImmVal(~Value) != -1;
671 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000672 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000673 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000674 return false;
675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
676 if (!CE) return false;
677 int64_t Value = CE->getValue();
678 return ARM_AM::getT2SOImmVal(Value) != -1;
679 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000680 bool isT2SOImmNot() const {
681 if (Kind != k_Immediate)
682 return false;
683 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
684 if (!CE) return false;
685 int64_t Value = CE->getValue();
686 return ARM_AM::getT2SOImmVal(~Value) != -1;
687 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000688 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000689 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000690 return false;
691 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
692 if (!CE) return false;
693 int64_t Value = CE->getValue();
694 return Value == 1 || Value == 0;
695 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000696 bool isReg() const { return Kind == k_Register; }
697 bool isRegList() const { return Kind == k_RegisterList; }
698 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
699 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
700 bool isToken() const { return Kind == k_Token; }
701 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
702 bool isMemory() const { return Kind == k_Memory; }
703 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
704 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
705 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
706 bool isRotImm() const { return Kind == k_RotateImmediate; }
707 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
708 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000709 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000710 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000711 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000712 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000713 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000714 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000715 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000716 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
717 (alignOK || Memory.Alignment == 0);
718 }
719 bool isAlignedMemory() const {
720 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000721 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000722 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000723 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000724 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000725 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000726 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000727 if (!Memory.OffsetImm) return true;
728 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000729 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000730 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000731 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000732 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000733 return false;
734 // Immediate offset in range [-4095, 4095].
735 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
736 if (!CE) return false;
737 int64_t Val = CE->getValue();
738 return Val > -4096 && Val < 4096;
739 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000740 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000741 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000742 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000743 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000744 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000745 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000746 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000747 if (!Memory.OffsetImm) return true;
748 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000749 return Val > -256 && Val < 256;
750 }
751 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000752 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000753 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000754 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000755 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
756 // Immediate offset in range [-255, 255].
757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000760 // Special case, #-0 is INT32_MIN.
761 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000762 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000763 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000764 // If we have an immediate that's not a constant, treat it as a label
765 // reference needing a fixup. If it is a constant, it's something else
766 // and we reject it.
767 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
768 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000769 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000770 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000771 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000772 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000773 if (!Memory.OffsetImm) return true;
774 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000775 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000776 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000777 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000778 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000779 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000780 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000781 return false;
782 return true;
783 }
784 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000785 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000786 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
787 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000788 return false;
789 return true;
790 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000791 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000793 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000794 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000795 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000796 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000797 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
798 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000799 return false;
800 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000801 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000802 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000803 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000804 return false;
805 return true;
806 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000807 bool isMemThumbRR() const {
808 // Thumb reg+reg addressing is simple. Just two registers, a base and
809 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000810 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000811 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000812 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000813 return isARMLowRegister(Memory.BaseRegNum) &&
814 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000815 }
816 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000817 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000819 return false;
820 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000821 if (!Memory.OffsetImm) return true;
822 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000823 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
824 }
Jim Grosbach38466302011-08-19 18:55:51 +0000825 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000826 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000828 return false;
829 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000830 if (!Memory.OffsetImm) return true;
831 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000832 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
833 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000834 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000835 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000836 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000837 return false;
838 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000839 if (!Memory.OffsetImm) return true;
840 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000841 return Val >= 0 && Val <= 31;
842 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000843 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000844 if (!isMemory() || Memory.OffsetRegNum != 0 ||
845 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000846 return false;
847 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000848 if (!Memory.OffsetImm) return true;
849 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000850 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000851 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000852 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000853 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000854 return false;
855 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000856 if (!Memory.OffsetImm) return true;
857 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000858 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
859 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000860 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000861 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000862 return false;
863 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000864 if (!Memory.OffsetImm) return true;
865 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000866 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
867 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000869 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 return false;
871 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000872 if (!Memory.OffsetImm) return true;
873 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000874 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000875 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000876 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000877 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000878 return false;
879 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000880 if (!Memory.OffsetImm) return true;
881 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000882 return Val >= 0 && Val < 256;
883 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000884 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000885 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000886 return false;
887 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000888 if (!Memory.OffsetImm) return true;
889 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000890 return Val > -256 && Val < 0;
891 }
892 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000893 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000894 return false;
895 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000896 if (!Memory.OffsetImm) return true;
897 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000898 return (Val >= 0 && Val < 4096);
899 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000900 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000901 // If we have an immediate that's not a constant, treat it as a label
902 // reference needing a fixup. If it is a constant, it's something else
903 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000904 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000905 return true;
906
Jim Grosbach57dcb852011-10-11 17:29:55 +0000907 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000908 return false;
909 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000910 if (!Memory.OffsetImm) return true;
911 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000912 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000913 }
914 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000915 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000916 return false;
917 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
918 if (!CE) return false;
919 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000920 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000922 bool isPostIdxImm8s4() const {
923 if (Kind != k_Immediate)
924 return false;
925 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
926 if (!CE) return false;
927 int64_t Val = CE->getValue();
928 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
929 (Val == INT32_MIN);
930 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000931
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000932 bool isMSRMask() const { return Kind == k_MSRMask; }
933 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000934
Jim Grosbach0e387b22011-10-17 22:26:03 +0000935 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000936 bool isVecListOneD() const {
937 if (Kind != k_VectorList) return false;
938 return VectorList.Count == 1;
939 }
940
Jim Grosbach280dfad2011-10-21 18:54:25 +0000941 bool isVecListTwoD() const {
942 if (Kind != k_VectorList) return false;
943 return VectorList.Count == 2;
944 }
945
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000946 bool isVecListThreeD() const {
947 if (Kind != k_VectorList) return false;
948 return VectorList.Count == 3;
949 }
950
Jim Grosbachb6310312011-10-21 20:35:01 +0000951 bool isVecListFourD() const {
952 if (Kind != k_VectorList) return false;
953 return VectorList.Count == 4;
954 }
955
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000956 bool isVecListTwoQ() const {
957 if (Kind != k_VectorList) return false;
958 //FIXME: We haven't taught the parser to handle by-two register lists
959 // yet, so don't pretend to know one.
960 return VectorList.Count == 2 && false;
961 }
962
Jim Grosbach460a9052011-10-07 23:56:00 +0000963 bool isVectorIndex8() const {
964 if (Kind != k_VectorIndex) return false;
965 return VectorIndex.Val < 8;
966 }
967 bool isVectorIndex16() const {
968 if (Kind != k_VectorIndex) return false;
969 return VectorIndex.Val < 4;
970 }
971 bool isVectorIndex32() const {
972 if (Kind != k_VectorIndex) return false;
973 return VectorIndex.Val < 2;
974 }
975
Jim Grosbach0e387b22011-10-17 22:26:03 +0000976 bool isNEONi8splat() const {
977 if (Kind != k_Immediate)
978 return false;
979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
980 // Must be a constant.
981 if (!CE) return false;
982 int64_t Value = CE->getValue();
983 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
984 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000985 return Value >= 0 && Value < 256;
986 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000987
Jim Grosbachea461102011-10-17 23:09:09 +0000988 bool isNEONi16splat() const {
989 if (Kind != k_Immediate)
990 return false;
991 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
992 // Must be a constant.
993 if (!CE) return false;
994 int64_t Value = CE->getValue();
995 // i16 value in the range [0,255] or [0x0100, 0xff00]
996 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
997 }
998
Jim Grosbach6248a542011-10-18 00:22:00 +0000999 bool isNEONi32splat() const {
1000 if (Kind != k_Immediate)
1001 return false;
1002 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1003 // Must be a constant.
1004 if (!CE) return false;
1005 int64_t Value = CE->getValue();
1006 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1007 return (Value >= 0 && Value < 256) ||
1008 (Value >= 0x0100 && Value <= 0xff00) ||
1009 (Value >= 0x010000 && Value <= 0xff0000) ||
1010 (Value >= 0x01000000 && Value <= 0xff000000);
1011 }
1012
1013 bool isNEONi32vmov() const {
1014 if (Kind != k_Immediate)
1015 return false;
1016 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1017 // Must be a constant.
1018 if (!CE) return false;
1019 int64_t Value = CE->getValue();
1020 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1021 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1022 return (Value >= 0 && Value < 256) ||
1023 (Value >= 0x0100 && Value <= 0xff00) ||
1024 (Value >= 0x010000 && Value <= 0xff0000) ||
1025 (Value >= 0x01000000 && Value <= 0xff000000) ||
1026 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1027 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1028 }
1029
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001030 bool isNEONi64splat() const {
1031 if (Kind != k_Immediate)
1032 return false;
1033 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1034 // Must be a constant.
1035 if (!CE) return false;
1036 uint64_t Value = CE->getValue();
1037 // i64 value with each byte being either 0 or 0xff.
1038 for (unsigned i = 0; i < 8; ++i)
1039 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1040 return true;
1041 }
1042
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001043 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001044 // Add as immediates when possible. Null MCExpr = 0.
1045 if (Expr == 0)
1046 Inst.addOperand(MCOperand::CreateImm(0));
1047 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001048 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1049 else
1050 Inst.addOperand(MCOperand::CreateExpr(Expr));
1051 }
1052
Daniel Dunbar8462b302010-08-11 06:36:53 +00001053 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001054 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001055 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001056 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1057 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001058 }
1059
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001060 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1061 assert(N == 1 && "Invalid number of operands!");
1062 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1063 }
1064
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001065 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1066 assert(N == 1 && "Invalid number of operands!");
1067 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1068 }
1069
1070 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1071 assert(N == 1 && "Invalid number of operands!");
1072 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1073 }
1074
Jim Grosbach89df9962011-08-26 21:43:41 +00001075 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1076 assert(N == 1 && "Invalid number of operands!");
1077 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1078 }
1079
1080 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1081 assert(N == 1 && "Invalid number of operands!");
1082 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1083 }
1084
Jim Grosbachd67641b2010-12-06 18:21:12 +00001085 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1086 assert(N == 1 && "Invalid number of operands!");
1087 Inst.addOperand(MCOperand::CreateReg(getReg()));
1088 }
1089
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001090 void addRegOperands(MCInst &Inst, unsigned N) const {
1091 assert(N == 1 && "Invalid number of operands!");
1092 Inst.addOperand(MCOperand::CreateReg(getReg()));
1093 }
1094
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001095 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001096 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001097 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1098 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1099 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001100 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001101 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001102 }
1103
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001104 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001105 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001106 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1107 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001108 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001109 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001110 }
1111
Jim Grosbach580f4a92011-07-25 22:20:28 +00001112 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001113 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001114 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1115 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001116 }
1117
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001118 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001119 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001120 const SmallVectorImpl<unsigned> &RegList = getRegList();
1121 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001122 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1123 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001124 }
1125
Bill Wendling0f630752010-11-17 04:32:08 +00001126 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1127 addRegListOperands(Inst, N);
1128 }
1129
1130 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1131 addRegListOperands(Inst, N);
1132 }
1133
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001134 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1135 assert(N == 1 && "Invalid number of operands!");
1136 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1137 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1138 }
1139
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001140 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1141 assert(N == 1 && "Invalid number of operands!");
1142 // Munge the lsb/width into a bitfield mask.
1143 unsigned lsb = Bitfield.LSB;
1144 unsigned width = Bitfield.Width;
1145 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1146 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1147 (32 - (lsb + width)));
1148 Inst.addOperand(MCOperand::CreateImm(Mask));
1149 }
1150
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001151 void addImmOperands(MCInst &Inst, unsigned N) const {
1152 assert(N == 1 && "Invalid number of operands!");
1153 addExpr(Inst, getImm());
1154 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001155
Jim Grosbach9d390362011-10-03 23:38:36 +00001156 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1157 assert(N == 1 && "Invalid number of operands!");
1158 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1159 }
1160
Jim Grosbacha77295d2011-09-08 22:07:06 +00001161 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1162 assert(N == 1 && "Invalid number of operands!");
1163 // FIXME: We really want to scale the value here, but the LDRD/STRD
1164 // instruction don't encode operands that way yet.
1165 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1166 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1167 }
1168
Jim Grosbach72f39f82011-08-24 21:22:15 +00001169 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!");
1171 // The immediate is scaled by four in the encoding and is stored
1172 // in the MCInst as such. Lop off the low two bits here.
1173 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1174 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1175 }
1176
1177 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1178 assert(N == 1 && "Invalid number of operands!");
1179 // The immediate is scaled by four in the encoding and is stored
1180 // in the MCInst as such. Lop off the low two bits here.
1181 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1182 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1183 }
1184
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001185 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 addExpr(Inst, getImm());
1188 }
1189
Jim Grosbach83ab0702011-07-13 22:01:08 +00001190 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1191 assert(N == 1 && "Invalid number of operands!");
1192 addExpr(Inst, getImm());
1193 }
1194
1195 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1196 assert(N == 1 && "Invalid number of operands!");
1197 addExpr(Inst, getImm());
1198 }
1199
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001200 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1201 assert(N == 1 && "Invalid number of operands!");
1202 addExpr(Inst, getImm());
1203 }
1204
Jim Grosbachf4943352011-07-25 23:09:14 +00001205 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1206 assert(N == 1 && "Invalid number of operands!");
1207 // The constant encodes as the immediate-1, and we store in the instruction
1208 // the bits as encoded, so subtract off one here.
1209 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1210 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1211 }
1212
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001213 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1214 assert(N == 1 && "Invalid number of operands!");
1215 // The constant encodes as the immediate-1, and we store in the instruction
1216 // the bits as encoded, so subtract off one here.
1217 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1218 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1219 }
1220
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001221 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223 addExpr(Inst, getImm());
1224 }
1225
Jim Grosbachffa32252011-07-19 19:13:28 +00001226 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 addExpr(Inst, getImm());
1229 }
1230
Jim Grosbached838482011-07-26 16:24:27 +00001231 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 addExpr(Inst, getImm());
1234 }
1235
Jim Grosbach70939ee2011-08-17 21:51:27 +00001236 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 // The constant encodes as the immediate, except for 32, which encodes as
1239 // zero.
1240 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1241 unsigned Imm = CE->getValue();
1242 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1243 }
1244
Jim Grosbachf6c05252011-07-21 17:23:04 +00001245 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1246 assert(N == 1 && "Invalid number of operands!");
1247 addExpr(Inst, getImm());
1248 }
1249
1250 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1251 assert(N == 1 && "Invalid number of operands!");
1252 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1253 // the instruction as well.
1254 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1255 int Val = CE->getValue();
1256 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1257 }
1258
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001259 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 addExpr(Inst, getImm());
1262 }
1263
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001264 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 1 && "Invalid number of operands!");
1266 addExpr(Inst, getImm());
1267 }
1268
Jim Grosbach89a63372011-10-28 22:36:30 +00001269 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 1 && "Invalid number of operands!");
1271 // The operand is actually a t2_so_imm, but we have its bitwise
1272 // negation in the assembly source, so twiddle it here.
1273 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1274 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1275 }
1276
Jim Grosbache70ec842011-10-28 22:50:54 +00001277 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
1279 // The operand is actually a so_imm, but we have its bitwise
1280 // negation in the assembly source, so twiddle it here.
1281 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1282 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1283 }
1284
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001285 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
1287 addExpr(Inst, getImm());
1288 }
1289
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001290 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1293 }
1294
Jim Grosbach7ce05792011-08-03 23:50:40 +00001295 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001297 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001298 }
1299
Jim Grosbach57dcb852011-10-11 17:29:55 +00001300 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1301 assert(N == 2 && "Invalid number of operands!");
1302 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1303 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1304 }
1305
Jim Grosbach7ce05792011-08-03 23:50:40 +00001306 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1307 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001308 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1309 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001310 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1311 // Special case for #-0
1312 if (Val == INT32_MIN) Val = 0;
1313 if (Val < 0) Val = -Val;
1314 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1315 } else {
1316 // For register offset, we encode the shift type and negation flag
1317 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001318 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1319 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001320 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001321 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1322 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001323 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001324 }
1325
Jim Grosbach039c2e12011-08-04 23:01:30 +00001326 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1327 assert(N == 2 && "Invalid number of operands!");
1328 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1329 assert(CE && "non-constant AM2OffsetImm operand!");
1330 int32_t Val = CE->getValue();
1331 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1332 // Special case for #-0
1333 if (Val == INT32_MIN) Val = 0;
1334 if (Val < 0) Val = -Val;
1335 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1336 Inst.addOperand(MCOperand::CreateReg(0));
1337 Inst.addOperand(MCOperand::CreateImm(Val));
1338 }
1339
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001340 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001342 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1343 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001344 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1345 // Special case for #-0
1346 if (Val == INT32_MIN) Val = 0;
1347 if (Val < 0) Val = -Val;
1348 Val = ARM_AM::getAM3Opc(AddSub, Val);
1349 } else {
1350 // For register offset, we encode the shift type and negation flag
1351 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001352 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001353 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001354 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1355 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001356 Inst.addOperand(MCOperand::CreateImm(Val));
1357 }
1358
1359 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1360 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001361 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001362 int32_t Val =
1363 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1364 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1365 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001366 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001367 }
1368
1369 // Constant offset.
1370 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1371 int32_t Val = CE->getValue();
1372 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1373 // Special case for #-0
1374 if (Val == INT32_MIN) Val = 0;
1375 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001376 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001377 Inst.addOperand(MCOperand::CreateReg(0));
1378 Inst.addOperand(MCOperand::CreateImm(Val));
1379 }
1380
Jim Grosbach7ce05792011-08-03 23:50:40 +00001381 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1382 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001383 // If we have an immediate that's not a constant, treat it as a label
1384 // reference needing a fixup. If it is a constant, it's something else
1385 // and we reject it.
1386 if (isImm()) {
1387 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1388 Inst.addOperand(MCOperand::CreateImm(0));
1389 return;
1390 }
1391
Jim Grosbach7ce05792011-08-03 23:50:40 +00001392 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001393 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001394 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1395 // Special case for #-0
1396 if (Val == INT32_MIN) Val = 0;
1397 if (Val < 0) Val = -Val;
1398 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001399 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001400 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001401 }
1402
Jim Grosbacha77295d2011-09-08 22:07:06 +00001403 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1404 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001405 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1406 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001407 Inst.addOperand(MCOperand::CreateImm(Val));
1408 }
1409
Jim Grosbachb6aed502011-09-09 18:37:27 +00001410 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1411 assert(N == 2 && "Invalid number of operands!");
1412 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001413 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1414 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001415 Inst.addOperand(MCOperand::CreateImm(Val));
1416 }
1417
Jim Grosbach7ce05792011-08-03 23:50:40 +00001418 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1419 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001420 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1421 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001422 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001423 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001424
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001425 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1426 addMemImm8OffsetOperands(Inst, N);
1427 }
1428
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001429 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001430 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001431 }
1432
1433 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 2 && "Invalid number of operands!");
1435 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001436 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001437 addExpr(Inst, getImm());
1438 Inst.addOperand(MCOperand::CreateImm(0));
1439 return;
1440 }
1441
1442 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001443 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1444 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001445 Inst.addOperand(MCOperand::CreateImm(Val));
1446 }
1447
Jim Grosbach7ce05792011-08-03 23:50:40 +00001448 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1449 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001450 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001451 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001452 addExpr(Inst, getImm());
1453 Inst.addOperand(MCOperand::CreateImm(0));
1454 return;
1455 }
1456
1457 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001458 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1459 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001460 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001461 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001462
Jim Grosbach7f739be2011-09-19 22:21:13 +00001463 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1464 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001465 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1466 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001467 }
1468
1469 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1470 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001471 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1472 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001473 }
1474
Jim Grosbach7ce05792011-08-03 23:50:40 +00001475 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001477 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1478 Memory.ShiftImm, Memory.ShiftType);
1479 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1480 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001481 Inst.addOperand(MCOperand::CreateImm(Val));
1482 }
1483
Jim Grosbachab899c12011-09-07 23:10:15 +00001484 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001486 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1487 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1488 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001489 }
1490
Jim Grosbach7ce05792011-08-03 23:50:40 +00001491 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001493 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1494 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001495 }
1496
Jim Grosbach60f91a32011-08-19 17:55:24 +00001497 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1498 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001499 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1500 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001501 Inst.addOperand(MCOperand::CreateImm(Val));
1502 }
1503
Jim Grosbach38466302011-08-19 18:55:51 +00001504 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1505 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001506 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1507 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001508 Inst.addOperand(MCOperand::CreateImm(Val));
1509 }
1510
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001511 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1512 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001513 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1514 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001515 Inst.addOperand(MCOperand::CreateImm(Val));
1516 }
1517
Jim Grosbachecd85892011-08-19 18:13:48 +00001518 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1519 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001520 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1521 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001522 Inst.addOperand(MCOperand::CreateImm(Val));
1523 }
1524
Jim Grosbach7ce05792011-08-03 23:50:40 +00001525 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1528 assert(CE && "non-constant post-idx-imm8 operand!");
1529 int Imm = CE->getValue();
1530 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001531 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001532 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1533 Inst.addOperand(MCOperand::CreateImm(Imm));
1534 }
1535
Jim Grosbach2bd01182011-10-11 21:55:36 +00001536 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1537 assert(N == 1 && "Invalid number of operands!");
1538 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1539 assert(CE && "non-constant post-idx-imm8s4 operand!");
1540 int Imm = CE->getValue();
1541 bool isAdd = Imm >= 0;
1542 if (Imm == INT32_MIN) Imm = 0;
1543 // Immediate is scaled by 4.
1544 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1545 Inst.addOperand(MCOperand::CreateImm(Imm));
1546 }
1547
Jim Grosbach7ce05792011-08-03 23:50:40 +00001548 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1549 assert(N == 2 && "Invalid number of operands!");
1550 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001551 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1552 }
1553
1554 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1555 assert(N == 2 && "Invalid number of operands!");
1556 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1557 // The sign, shift type, and shift amount are encoded in a single operand
1558 // using the AM2 encoding helpers.
1559 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1560 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1561 PostIdxReg.ShiftTy);
1562 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001563 }
1564
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001565 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1568 }
1569
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001570 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
1572 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1573 }
1574
Jim Grosbach862019c2011-10-18 23:02:30 +00001575 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1578 }
1579
Jim Grosbach280dfad2011-10-21 18:54:25 +00001580 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 // Only the first register actually goes on the instruction. The rest
1583 // are implied by the opcode.
1584 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1585 }
1586
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001587 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1588 assert(N == 1 && "Invalid number of operands!");
1589 // Only the first register actually goes on the instruction. The rest
1590 // are implied by the opcode.
1591 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1592 }
1593
Jim Grosbachb6310312011-10-21 20:35:01 +00001594 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596 // Only the first register actually goes on the instruction. The rest
1597 // are implied by the opcode.
1598 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1599 }
1600
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001601 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1602 assert(N == 1 && "Invalid number of operands!");
1603 // Only the first register actually goes on the instruction. The rest
1604 // are implied by the opcode.
1605 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1606 }
1607
Jim Grosbach460a9052011-10-07 23:56:00 +00001608 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1611 }
1612
1613 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1616 }
1617
1618 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1619 assert(N == 1 && "Invalid number of operands!");
1620 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1621 }
1622
Jim Grosbach0e387b22011-10-17 22:26:03 +00001623 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1624 assert(N == 1 && "Invalid number of operands!");
1625 // The immediate encodes the type of constant as well as the value.
1626 // Mask in that this is an i8 splat.
1627 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1628 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1629 }
1630
Jim Grosbachea461102011-10-17 23:09:09 +00001631 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1632 assert(N == 1 && "Invalid number of operands!");
1633 // The immediate encodes the type of constant as well as the value.
1634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1635 unsigned Value = CE->getValue();
1636 if (Value >= 256)
1637 Value = (Value >> 8) | 0xa00;
1638 else
1639 Value |= 0x800;
1640 Inst.addOperand(MCOperand::CreateImm(Value));
1641 }
1642
Jim Grosbach6248a542011-10-18 00:22:00 +00001643 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1644 assert(N == 1 && "Invalid number of operands!");
1645 // The immediate encodes the type of constant as well as the value.
1646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1647 unsigned Value = CE->getValue();
1648 if (Value >= 256 && Value <= 0xff00)
1649 Value = (Value >> 8) | 0x200;
1650 else if (Value > 0xffff && Value <= 0xff0000)
1651 Value = (Value >> 16) | 0x400;
1652 else if (Value > 0xffffff)
1653 Value = (Value >> 24) | 0x600;
1654 Inst.addOperand(MCOperand::CreateImm(Value));
1655 }
1656
1657 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1658 assert(N == 1 && "Invalid number of operands!");
1659 // The immediate encodes the type of constant as well as the value.
1660 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1661 unsigned Value = CE->getValue();
1662 if (Value >= 256 && Value <= 0xffff)
1663 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1664 else if (Value > 0xffff && Value <= 0xffffff)
1665 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1666 else if (Value > 0xffffff)
1667 Value = (Value >> 24) | 0x600;
1668 Inst.addOperand(MCOperand::CreateImm(Value));
1669 }
1670
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001671 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1672 assert(N == 1 && "Invalid number of operands!");
1673 // The immediate encodes the type of constant as well as the value.
1674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1675 uint64_t Value = CE->getValue();
1676 unsigned Imm = 0;
1677 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1678 Imm |= (Value & 1) << i;
1679 }
1680 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1681 }
1682
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001683 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001684
Jim Grosbach89df9962011-08-26 21:43:41 +00001685 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001686 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001687 Op->ITMask.Mask = Mask;
1688 Op->StartLoc = S;
1689 Op->EndLoc = S;
1690 return Op;
1691 }
1692
Chris Lattner3a697562010-10-28 17:20:03 +00001693 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001694 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001695 Op->CC.Val = CC;
1696 Op->StartLoc = S;
1697 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001698 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001699 }
1700
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001701 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001702 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001703 Op->Cop.Val = CopVal;
1704 Op->StartLoc = S;
1705 Op->EndLoc = S;
1706 return Op;
1707 }
1708
1709 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001710 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001711 Op->Cop.Val = CopVal;
1712 Op->StartLoc = S;
1713 Op->EndLoc = S;
1714 return Op;
1715 }
1716
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001717 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1718 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1719 Op->Cop.Val = Val;
1720 Op->StartLoc = S;
1721 Op->EndLoc = E;
1722 return Op;
1723 }
1724
Jim Grosbachd67641b2010-12-06 18:21:12 +00001725 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001726 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001727 Op->Reg.RegNum = RegNum;
1728 Op->StartLoc = S;
1729 Op->EndLoc = S;
1730 return Op;
1731 }
1732
Chris Lattner3a697562010-10-28 17:20:03 +00001733 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001734 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001735 Op->Tok.Data = Str.data();
1736 Op->Tok.Length = Str.size();
1737 Op->StartLoc = S;
1738 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001739 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001740 }
1741
Bill Wendling50d0f582010-11-18 23:43:05 +00001742 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001743 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001744 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001745 Op->StartLoc = S;
1746 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001747 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001748 }
1749
Jim Grosbache8606dc2011-07-13 17:50:29 +00001750 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1751 unsigned SrcReg,
1752 unsigned ShiftReg,
1753 unsigned ShiftImm,
1754 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001756 Op->RegShiftedReg.ShiftTy = ShTy;
1757 Op->RegShiftedReg.SrcReg = SrcReg;
1758 Op->RegShiftedReg.ShiftReg = ShiftReg;
1759 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001760 Op->StartLoc = S;
1761 Op->EndLoc = E;
1762 return Op;
1763 }
1764
Owen Anderson92a20222011-07-21 18:54:16 +00001765 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1766 unsigned SrcReg,
1767 unsigned ShiftImm,
1768 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001769 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001770 Op->RegShiftedImm.ShiftTy = ShTy;
1771 Op->RegShiftedImm.SrcReg = SrcReg;
1772 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001773 Op->StartLoc = S;
1774 Op->EndLoc = E;
1775 return Op;
1776 }
1777
Jim Grosbach580f4a92011-07-25 22:20:28 +00001778 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001779 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001780 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001781 Op->ShifterImm.isASR = isASR;
1782 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001783 Op->StartLoc = S;
1784 Op->EndLoc = E;
1785 return Op;
1786 }
1787
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001788 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001789 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001790 Op->RotImm.Imm = Imm;
1791 Op->StartLoc = S;
1792 Op->EndLoc = E;
1793 return Op;
1794 }
1795
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001796 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1797 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001798 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001799 Op->Bitfield.LSB = LSB;
1800 Op->Bitfield.Width = Width;
1801 Op->StartLoc = S;
1802 Op->EndLoc = E;
1803 return Op;
1804 }
1805
Bill Wendling7729e062010-11-09 22:44:22 +00001806 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001807 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001808 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001809 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001810
Jim Grosbachd300b942011-09-13 22:56:44 +00001811 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001812 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001813 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001814 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001815 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001816
1817 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001818 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001819 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001820 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001821 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001822 Op->StartLoc = StartLoc;
1823 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001824 return Op;
1825 }
1826
Jim Grosbach862019c2011-10-18 23:02:30 +00001827 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1828 SMLoc S, SMLoc E) {
1829 ARMOperand *Op = new ARMOperand(k_VectorList);
1830 Op->VectorList.RegNum = RegNum;
1831 Op->VectorList.Count = Count;
1832 Op->StartLoc = S;
1833 Op->EndLoc = E;
1834 return Op;
1835 }
1836
Jim Grosbach460a9052011-10-07 23:56:00 +00001837 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1838 MCContext &Ctx) {
1839 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1840 Op->VectorIndex.Val = Idx;
1841 Op->StartLoc = S;
1842 Op->EndLoc = E;
1843 return Op;
1844 }
1845
Chris Lattner3a697562010-10-28 17:20:03 +00001846 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001847 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001848 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001849 Op->StartLoc = S;
1850 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001851 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001852 }
1853
Jim Grosbach9d390362011-10-03 23:38:36 +00001854 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001855 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001856 Op->FPImm.Val = Val;
1857 Op->StartLoc = S;
1858 Op->EndLoc = S;
1859 return Op;
1860 }
1861
Jim Grosbach7ce05792011-08-03 23:50:40 +00001862 static ARMOperand *CreateMem(unsigned BaseRegNum,
1863 const MCConstantExpr *OffsetImm,
1864 unsigned OffsetRegNum,
1865 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001866 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001867 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001868 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001869 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001870 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001871 Op->Memory.BaseRegNum = BaseRegNum;
1872 Op->Memory.OffsetImm = OffsetImm;
1873 Op->Memory.OffsetRegNum = OffsetRegNum;
1874 Op->Memory.ShiftType = ShiftType;
1875 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001876 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001877 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001878 Op->StartLoc = S;
1879 Op->EndLoc = E;
1880 return Op;
1881 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001882
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001883 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1884 ARM_AM::ShiftOpc ShiftTy,
1885 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001886 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001887 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001888 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001889 Op->PostIdxReg.isAdd = isAdd;
1890 Op->PostIdxReg.ShiftTy = ShiftTy;
1891 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001892 Op->StartLoc = S;
1893 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001894 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001895 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001896
1897 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001898 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001899 Op->MBOpt.Val = Opt;
1900 Op->StartLoc = S;
1901 Op->EndLoc = S;
1902 return Op;
1903 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001904
1905 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001906 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001907 Op->IFlags.Val = IFlags;
1908 Op->StartLoc = S;
1909 Op->EndLoc = S;
1910 return Op;
1911 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001912
1913 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001914 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001915 Op->MMask.Val = MMask;
1916 Op->StartLoc = S;
1917 Op->EndLoc = S;
1918 return Op;
1919 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001920};
1921
1922} // end anonymous namespace.
1923
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001924void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001925 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001926 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001927 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1928 << ") >";
1929 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001930 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001931 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001932 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001933 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001934 OS << "<ccout " << getReg() << ">";
1935 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001936 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001937 static const char *MaskStr[] = {
1938 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1939 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1940 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001941 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1942 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1943 break;
1944 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001945 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001946 OS << "<coprocessor number: " << getCoproc() << ">";
1947 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001948 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001949 OS << "<coprocessor register: " << getCoproc() << ">";
1950 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001951 case k_CoprocOption:
1952 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1953 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001954 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001955 OS << "<mask: " << getMSRMask() << ">";
1956 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001957 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001958 getImm()->print(OS);
1959 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001960 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001961 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1962 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001963 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001964 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001965 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001966 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001967 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001968 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001969 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1970 << PostIdxReg.RegNum;
1971 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1972 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1973 << PostIdxReg.ShiftImm;
1974 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001975 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001976 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001977 OS << "<ARM_PROC::";
1978 unsigned IFlags = getProcIFlags();
1979 for (int i=2; i >= 0; --i)
1980 if (IFlags & (1 << i))
1981 OS << ARM_PROC::IFlagsToString(1 << i);
1982 OS << ">";
1983 break;
1984 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001986 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001987 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001989 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1990 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001991 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001992 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001993 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001994 << RegShiftedReg.SrcReg
1995 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1996 << ", " << RegShiftedReg.ShiftReg << ", "
1997 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001998 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001999 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002000 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002001 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002002 << RegShiftedImm.SrcReg
2003 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
2004 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00002005 << ">";
2006 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002007 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002008 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2009 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002010 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002011 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2012 << ", width: " << Bitfield.Width << ">";
2013 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002014 case k_RegisterList:
2015 case k_DPRRegisterList:
2016 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002017 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002018
Bill Wendling5fa22a12010-11-09 23:28:44 +00002019 const SmallVectorImpl<unsigned> &RegList = getRegList();
2020 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002021 I = RegList.begin(), E = RegList.end(); I != E; ) {
2022 OS << *I;
2023 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002024 }
2025
2026 OS << ">";
2027 break;
2028 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002029 case k_VectorList:
2030 OS << "<vector_list " << VectorList.Count << " * "
2031 << VectorList.RegNum << ">";
2032 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002033 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002034 OS << "'" << getToken() << "'";
2035 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002036 case k_VectorIndex:
2037 OS << "<vectorindex " << getVectorIndex() << ">";
2038 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002039 }
2040}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002041
2042/// @name Auto-generated Match Functions
2043/// {
2044
2045static unsigned MatchRegisterName(StringRef Name);
2046
2047/// }
2048
Bob Wilson69df7232011-02-03 21:46:10 +00002049bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2050 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002051 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002052
2053 return (RegNo == (unsigned)-1);
2054}
2055
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002056/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002057/// and if it is a register name the token is eaten and the register number is
2058/// returned. Otherwise return -1.
2059///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002060int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002061 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002062 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002063
Chris Lattnere5658fa2010-10-30 04:09:10 +00002064 // FIXME: Validate register for the current architecture; we have to do
2065 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00002066 std::string upperCase = Tok.getString().str();
2067 std::string lowerCase = LowercaseString(upperCase);
2068 unsigned RegNum = MatchRegisterName(lowerCase);
2069 if (!RegNum) {
2070 RegNum = StringSwitch<unsigned>(lowerCase)
2071 .Case("r13", ARM::SP)
2072 .Case("r14", ARM::LR)
2073 .Case("r15", ARM::PC)
2074 .Case("ip", ARM::R12)
2075 .Default(0);
2076 }
2077 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002078
Chris Lattnere5658fa2010-10-30 04:09:10 +00002079 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002080
Chris Lattnere5658fa2010-10-30 04:09:10 +00002081 return RegNum;
2082}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002083
Jim Grosbach19906722011-07-13 18:49:30 +00002084// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2085// If a recoverable error occurs, return 1. If an irrecoverable error
2086// occurs, return -1. An irrecoverable error is one where tokens have been
2087// consumed in the process of trying to parse the shifter (i.e., when it is
2088// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002089int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002090 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2091 SMLoc S = Parser.getTok().getLoc();
2092 const AsmToken &Tok = Parser.getTok();
2093 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2094
2095 std::string upperCase = Tok.getString().str();
2096 std::string lowerCase = LowercaseString(upperCase);
2097 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2098 .Case("lsl", ARM_AM::lsl)
2099 .Case("lsr", ARM_AM::lsr)
2100 .Case("asr", ARM_AM::asr)
2101 .Case("ror", ARM_AM::ror)
2102 .Case("rrx", ARM_AM::rrx)
2103 .Default(ARM_AM::no_shift);
2104
2105 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002106 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002107
Jim Grosbache8606dc2011-07-13 17:50:29 +00002108 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002109
Jim Grosbache8606dc2011-07-13 17:50:29 +00002110 // The source register for the shift has already been added to the
2111 // operand list, so we need to pop it off and combine it into the shifted
2112 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002113 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002114 if (!PrevOp->isReg())
2115 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2116 int SrcReg = PrevOp->getReg();
2117 int64_t Imm = 0;
2118 int ShiftReg = 0;
2119 if (ShiftTy == ARM_AM::rrx) {
2120 // RRX Doesn't have an explicit shift amount. The encoder expects
2121 // the shift register to be the same as the source register. Seems odd,
2122 // but OK.
2123 ShiftReg = SrcReg;
2124 } else {
2125 // Figure out if this is shifted by a constant or a register (for non-RRX).
2126 if (Parser.getTok().is(AsmToken::Hash)) {
2127 Parser.Lex(); // Eat hash.
2128 SMLoc ImmLoc = Parser.getTok().getLoc();
2129 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002130 if (getParser().ParseExpression(ShiftExpr)) {
2131 Error(ImmLoc, "invalid immediate shift value");
2132 return -1;
2133 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002134 // The expression must be evaluatable as an immediate.
2135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002136 if (!CE) {
2137 Error(ImmLoc, "invalid immediate shift value");
2138 return -1;
2139 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002140 // Range check the immediate.
2141 // lsl, ror: 0 <= imm <= 31
2142 // lsr, asr: 0 <= imm <= 32
2143 Imm = CE->getValue();
2144 if (Imm < 0 ||
2145 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2146 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002147 Error(ImmLoc, "immediate shift value out of range");
2148 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002149 }
2150 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002151 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002152 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002153 if (ShiftReg == -1) {
2154 Error (L, "expected immediate or register in shift operand");
2155 return -1;
2156 }
2157 } else {
2158 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002159 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002160 return -1;
2161 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002162 }
2163
Owen Anderson92a20222011-07-21 18:54:16 +00002164 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2165 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002166 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002167 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002168 else
2169 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2170 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002171
Jim Grosbach19906722011-07-13 18:49:30 +00002172 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002173}
2174
2175
Bill Wendling50d0f582010-11-18 23:43:05 +00002176/// Try to parse a register name. The token must be an Identifier when called.
2177/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2178/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002179///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002180/// TODO this is likely to change to allow different register types and or to
2181/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002182bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002183tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002184 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002185 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002186 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002187 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002188
Bill Wendling50d0f582010-11-18 23:43:05 +00002189 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002190
Chris Lattnere5658fa2010-10-30 04:09:10 +00002191 const AsmToken &ExclaimTok = Parser.getTok();
2192 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002193 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2194 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002195 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002196 return false;
2197 }
2198
2199 // Also check for an index operand. This is only legal for vector registers,
2200 // but that'll get caught OK in operand matching, so we don't need to
2201 // explicitly filter everything else out here.
2202 if (Parser.getTok().is(AsmToken::LBrac)) {
2203 SMLoc SIdx = Parser.getTok().getLoc();
2204 Parser.Lex(); // Eat left bracket token.
2205
2206 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002207 if (getParser().ParseExpression(ImmVal))
2208 return MatchOperand_ParseFail;
2209 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2210 if (!MCE) {
2211 TokError("immediate value expected for vector index");
2212 return MatchOperand_ParseFail;
2213 }
2214
2215 SMLoc E = Parser.getTok().getLoc();
2216 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2217 Error(E, "']' expected");
2218 return MatchOperand_ParseFail;
2219 }
2220
2221 Parser.Lex(); // Eat right bracket token.
2222
2223 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2224 SIdx, E,
2225 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002226 }
2227
Bill Wendling50d0f582010-11-18 23:43:05 +00002228 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002229}
2230
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002231/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2232/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2233/// "c5", ...
2234static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002235 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2236 // but efficient.
2237 switch (Name.size()) {
2238 default: break;
2239 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002240 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002241 return -1;
2242 switch (Name[1]) {
2243 default: return -1;
2244 case '0': return 0;
2245 case '1': return 1;
2246 case '2': return 2;
2247 case '3': return 3;
2248 case '4': return 4;
2249 case '5': return 5;
2250 case '6': return 6;
2251 case '7': return 7;
2252 case '8': return 8;
2253 case '9': return 9;
2254 }
2255 break;
2256 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002257 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002258 return -1;
2259 switch (Name[2]) {
2260 default: return -1;
2261 case '0': return 10;
2262 case '1': return 11;
2263 case '2': return 12;
2264 case '3': return 13;
2265 case '4': return 14;
2266 case '5': return 15;
2267 }
2268 break;
2269 }
2270
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002271 return -1;
2272}
2273
Jim Grosbach89df9962011-08-26 21:43:41 +00002274/// parseITCondCode - Try to parse a condition code for an IT instruction.
2275ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2276parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2277 SMLoc S = Parser.getTok().getLoc();
2278 const AsmToken &Tok = Parser.getTok();
2279 if (!Tok.is(AsmToken::Identifier))
2280 return MatchOperand_NoMatch;
2281 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2282 .Case("eq", ARMCC::EQ)
2283 .Case("ne", ARMCC::NE)
2284 .Case("hs", ARMCC::HS)
2285 .Case("cs", ARMCC::HS)
2286 .Case("lo", ARMCC::LO)
2287 .Case("cc", ARMCC::LO)
2288 .Case("mi", ARMCC::MI)
2289 .Case("pl", ARMCC::PL)
2290 .Case("vs", ARMCC::VS)
2291 .Case("vc", ARMCC::VC)
2292 .Case("hi", ARMCC::HI)
2293 .Case("ls", ARMCC::LS)
2294 .Case("ge", ARMCC::GE)
2295 .Case("lt", ARMCC::LT)
2296 .Case("gt", ARMCC::GT)
2297 .Case("le", ARMCC::LE)
2298 .Case("al", ARMCC::AL)
2299 .Default(~0U);
2300 if (CC == ~0U)
2301 return MatchOperand_NoMatch;
2302 Parser.Lex(); // Eat the token.
2303
2304 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2305
2306 return MatchOperand_Success;
2307}
2308
Jim Grosbach43904292011-07-25 20:14:50 +00002309/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002310/// token must be an Identifier when called, and if it is a coprocessor
2311/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002312ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002313parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002314 SMLoc S = Parser.getTok().getLoc();
2315 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002316 if (Tok.isNot(AsmToken::Identifier))
2317 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002318
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002319 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002320 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002321 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002322
2323 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002324 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002325 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002326}
2327
Jim Grosbach43904292011-07-25 20:14:50 +00002328/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002329/// token must be an Identifier when called, and if it is a coprocessor
2330/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002331ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002332parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002333 SMLoc S = Parser.getTok().getLoc();
2334 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002335 if (Tok.isNot(AsmToken::Identifier))
2336 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002337
2338 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2339 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002340 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002341
2342 Parser.Lex(); // Eat identifier token.
2343 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002344 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002345}
2346
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002347/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2348/// coproc_option : '{' imm0_255 '}'
2349ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2350parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2351 SMLoc S = Parser.getTok().getLoc();
2352
2353 // If this isn't a '{', this isn't a coprocessor immediate operand.
2354 if (Parser.getTok().isNot(AsmToken::LCurly))
2355 return MatchOperand_NoMatch;
2356 Parser.Lex(); // Eat the '{'
2357
2358 const MCExpr *Expr;
2359 SMLoc Loc = Parser.getTok().getLoc();
2360 if (getParser().ParseExpression(Expr)) {
2361 Error(Loc, "illegal expression");
2362 return MatchOperand_ParseFail;
2363 }
2364 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2365 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2366 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2367 return MatchOperand_ParseFail;
2368 }
2369 int Val = CE->getValue();
2370
2371 // Check for and consume the closing '}'
2372 if (Parser.getTok().isNot(AsmToken::RCurly))
2373 return MatchOperand_ParseFail;
2374 SMLoc E = Parser.getTok().getLoc();
2375 Parser.Lex(); // Eat the '}'
2376
2377 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2378 return MatchOperand_Success;
2379}
2380
Jim Grosbachd0588e22011-09-14 18:08:35 +00002381// For register list parsing, we need to map from raw GPR register numbering
2382// to the enumeration values. The enumeration values aren't sorted by
2383// register number due to our using "sp", "lr" and "pc" as canonical names.
2384static unsigned getNextRegister(unsigned Reg) {
2385 // If this is a GPR, we need to do it manually, otherwise we can rely
2386 // on the sort ordering of the enumeration since the other reg-classes
2387 // are sane.
2388 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2389 return Reg + 1;
2390 switch(Reg) {
2391 default: assert(0 && "Invalid GPR number!");
2392 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2393 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2394 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2395 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2396 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2397 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2398 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2399 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2400 }
2401}
2402
2403/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002404bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002405parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002406 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002407 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002408 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002409 Parser.Lex(); // Eat '{' token.
2410 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002411
Jim Grosbachd0588e22011-09-14 18:08:35 +00002412 // Check the first register in the list to see what register class
2413 // this is a list of.
2414 int Reg = tryParseRegister();
2415 if (Reg == -1)
2416 return Error(RegLoc, "register expected");
2417
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002418 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002419 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2420 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2421 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2422 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2423 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2424 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2425 else
2426 return Error(RegLoc, "invalid register in register list");
2427
2428 // The reglist instructions have at most 16 registers, so reserve
2429 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002430 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002431 // Store the first register.
2432 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002433
Jim Grosbachd0588e22011-09-14 18:08:35 +00002434 // This starts immediately after the first register token in the list,
2435 // so we can see either a comma or a minus (range separator) as a legal
2436 // next token.
2437 while (Parser.getTok().is(AsmToken::Comma) ||
2438 Parser.getTok().is(AsmToken::Minus)) {
2439 if (Parser.getTok().is(AsmToken::Minus)) {
2440 Parser.Lex(); // Eat the comma.
2441 SMLoc EndLoc = Parser.getTok().getLoc();
2442 int EndReg = tryParseRegister();
2443 if (EndReg == -1)
2444 return Error(EndLoc, "register expected");
2445 // If the register is the same as the start reg, there's nothing
2446 // more to do.
2447 if (Reg == EndReg)
2448 continue;
2449 // The register must be in the same register class as the first.
2450 if (!RC->contains(EndReg))
2451 return Error(EndLoc, "invalid register in register list");
2452 // Ranges must go from low to high.
2453 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2454 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002455
Jim Grosbachd0588e22011-09-14 18:08:35 +00002456 // Add all the registers in the range to the register list.
2457 while (Reg != EndReg) {
2458 Reg = getNextRegister(Reg);
2459 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2460 }
2461 continue;
2462 }
2463 Parser.Lex(); // Eat the comma.
2464 RegLoc = Parser.getTok().getLoc();
2465 int OldReg = Reg;
2466 Reg = tryParseRegister();
2467 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002468 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002469 // The register must be in the same register class as the first.
2470 if (!RC->contains(Reg))
2471 return Error(RegLoc, "invalid register in register list");
2472 // List must be monotonically increasing.
2473 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2474 return Error(RegLoc, "register list not in ascending order");
2475 // VFP register lists must also be contiguous.
2476 // It's OK to use the enumeration values directly here rather, as the
2477 // VFP register classes have the enum sorted properly.
2478 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2479 Reg != OldReg + 1)
2480 return Error(RegLoc, "non-contiguous register range");
2481 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002482 }
2483
Jim Grosbachd0588e22011-09-14 18:08:35 +00002484 SMLoc E = Parser.getTok().getLoc();
2485 if (Parser.getTok().isNot(AsmToken::RCurly))
2486 return Error(E, "'}' expected");
2487 Parser.Lex(); // Eat '}' token.
2488
Bill Wendling50d0f582010-11-18 23:43:05 +00002489 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2490 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002491}
2492
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002493// Return the low-subreg of a given Q register.
2494static unsigned getDRegFromQReg(unsigned QReg) {
2495 switch (QReg) {
2496 default: llvm_unreachable("expected a Q register!");
2497 case ARM::Q0: return ARM::D0;
2498 case ARM::Q1: return ARM::D2;
2499 case ARM::Q2: return ARM::D4;
2500 case ARM::Q3: return ARM::D6;
2501 case ARM::Q4: return ARM::D8;
2502 case ARM::Q5: return ARM::D10;
2503 case ARM::Q6: return ARM::D12;
2504 case ARM::Q7: return ARM::D14;
2505 case ARM::Q8: return ARM::D16;
2506 case ARM::Q9: return ARM::D19;
2507 case ARM::Q10: return ARM::D20;
2508 case ARM::Q11: return ARM::D22;
2509 case ARM::Q12: return ARM::D24;
2510 case ARM::Q13: return ARM::D26;
2511 case ARM::Q14: return ARM::D28;
2512 case ARM::Q15: return ARM::D30;
2513 }
2514}
2515
Jim Grosbach862019c2011-10-18 23:02:30 +00002516// parse a vector register list
2517ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2518parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2519 if(Parser.getTok().isNot(AsmToken::LCurly))
2520 return MatchOperand_NoMatch;
2521
2522 SMLoc S = Parser.getTok().getLoc();
2523 Parser.Lex(); // Eat '{' token.
2524 SMLoc RegLoc = Parser.getTok().getLoc();
2525
2526 int Reg = tryParseRegister();
2527 if (Reg == -1) {
2528 Error(RegLoc, "register expected");
2529 return MatchOperand_ParseFail;
2530 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002531 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002532 unsigned FirstReg = Reg;
2533 // The list is of D registers, but we also allow Q regs and just interpret
2534 // them as the two D sub-registers.
2535 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2536 FirstReg = Reg = getDRegFromQReg(Reg);
2537 ++Reg;
2538 ++Count;
2539 }
2540
Jim Grosbach862019c2011-10-18 23:02:30 +00002541 while (Parser.getTok().is(AsmToken::Comma)) {
2542 Parser.Lex(); // Eat the comma.
2543 RegLoc = Parser.getTok().getLoc();
2544 int OldReg = Reg;
2545 Reg = tryParseRegister();
2546 if (Reg == -1) {
2547 Error(RegLoc, "register expected");
2548 return MatchOperand_ParseFail;
2549 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002550 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002551 // It's OK to use the enumeration values directly here rather, as the
2552 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002553 //
2554 // The list is of D registers, but we also allow Q regs and just interpret
2555 // them as the two D sub-registers.
2556 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2557 Reg = getDRegFromQReg(Reg);
2558 if (Reg != OldReg + 1) {
2559 Error(RegLoc, "non-contiguous register range");
2560 return MatchOperand_ParseFail;
2561 }
2562 ++Reg;
2563 Count += 2;
2564 continue;
2565 }
2566 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002567 if (Reg != OldReg + 1) {
2568 Error(RegLoc, "non-contiguous register range");
2569 return MatchOperand_ParseFail;
2570 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002571 ++Count;
2572 }
2573
2574 SMLoc E = Parser.getTok().getLoc();
2575 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2576 Error(E, "'}' expected");
2577 return MatchOperand_ParseFail;
2578 }
2579 Parser.Lex(); // Eat '}' token.
2580
2581 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2582 return MatchOperand_Success;
2583}
2584
Jim Grosbach43904292011-07-25 20:14:50 +00002585/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002586ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002587parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002588 SMLoc S = Parser.getTok().getLoc();
2589 const AsmToken &Tok = Parser.getTok();
2590 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2591 StringRef OptStr = Tok.getString();
2592
2593 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2594 .Case("sy", ARM_MB::SY)
2595 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002596 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002597 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002598 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002599 .Case("ishst", ARM_MB::ISHST)
2600 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002601 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002602 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002603 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002604 .Case("osh", ARM_MB::OSH)
2605 .Case("oshst", ARM_MB::OSHST)
2606 .Default(~0U);
2607
2608 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002609 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002610
2611 Parser.Lex(); // Eat identifier token.
2612 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002613 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002614}
2615
Jim Grosbach43904292011-07-25 20:14:50 +00002616/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002617ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002618parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002619 SMLoc S = Parser.getTok().getLoc();
2620 const AsmToken &Tok = Parser.getTok();
2621 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2622 StringRef IFlagsStr = Tok.getString();
2623
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002624 // An iflags string of "none" is interpreted to mean that none of the AIF
2625 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002626 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002627 if (IFlagsStr != "none") {
2628 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2629 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2630 .Case("a", ARM_PROC::A)
2631 .Case("i", ARM_PROC::I)
2632 .Case("f", ARM_PROC::F)
2633 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002634
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002635 // If some specific iflag is already set, it means that some letter is
2636 // present more than once, this is not acceptable.
2637 if (Flag == ~0U || (IFlags & Flag))
2638 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002639
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002640 IFlags |= Flag;
2641 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002642 }
2643
2644 Parser.Lex(); // Eat identifier token.
2645 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2646 return MatchOperand_Success;
2647}
2648
Jim Grosbach43904292011-07-25 20:14:50 +00002649/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002650ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002651parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002652 SMLoc S = Parser.getTok().getLoc();
2653 const AsmToken &Tok = Parser.getTok();
2654 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2655 StringRef Mask = Tok.getString();
2656
James Molloyacad68d2011-09-28 14:21:38 +00002657 if (isMClass()) {
2658 // See ARMv6-M 10.1.1
2659 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2660 .Case("apsr", 0)
2661 .Case("iapsr", 1)
2662 .Case("eapsr", 2)
2663 .Case("xpsr", 3)
2664 .Case("ipsr", 5)
2665 .Case("epsr", 6)
2666 .Case("iepsr", 7)
2667 .Case("msp", 8)
2668 .Case("psp", 9)
2669 .Case("primask", 16)
2670 .Case("basepri", 17)
2671 .Case("basepri_max", 18)
2672 .Case("faultmask", 19)
2673 .Case("control", 20)
2674 .Default(~0U);
2675
2676 if (FlagsVal == ~0U)
2677 return MatchOperand_NoMatch;
2678
2679 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2680 // basepri, basepri_max and faultmask only valid for V7m.
2681 return MatchOperand_NoMatch;
2682
2683 Parser.Lex(); // Eat identifier token.
2684 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2685 return MatchOperand_Success;
2686 }
2687
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002688 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2689 size_t Start = 0, Next = Mask.find('_');
2690 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002691 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002692 if (Next != StringRef::npos)
2693 Flags = Mask.slice(Next+1, Mask.size());
2694
2695 // FlagsVal contains the complete mask:
2696 // 3-0: Mask
2697 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2698 unsigned FlagsVal = 0;
2699
2700 if (SpecReg == "apsr") {
2701 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002702 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002703 .Case("g", 0x4) // same as CPSR_s
2704 .Case("nzcvqg", 0xc) // same as CPSR_fs
2705 .Default(~0U);
2706
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002707 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002708 if (!Flags.empty())
2709 return MatchOperand_NoMatch;
2710 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002711 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002712 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002713 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002714 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2715 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002716 for (int i = 0, e = Flags.size(); i != e; ++i) {
2717 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2718 .Case("c", 1)
2719 .Case("x", 2)
2720 .Case("s", 4)
2721 .Case("f", 8)
2722 .Default(~0U);
2723
2724 // If some specific flag is already set, it means that some letter is
2725 // present more than once, this is not acceptable.
2726 if (FlagsVal == ~0U || (FlagsVal & Flag))
2727 return MatchOperand_NoMatch;
2728 FlagsVal |= Flag;
2729 }
2730 } else // No match for special register.
2731 return MatchOperand_NoMatch;
2732
Owen Anderson7784f1d2011-10-21 18:43:28 +00002733 // Special register without flags is NOT equivalent to "fc" flags.
2734 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2735 // two lines would enable gas compatibility at the expense of breaking
2736 // round-tripping.
2737 //
2738 // if (!FlagsVal)
2739 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002740
2741 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2742 if (SpecReg == "spsr")
2743 FlagsVal |= 16;
2744
2745 Parser.Lex(); // Eat identifier token.
2746 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2747 return MatchOperand_Success;
2748}
2749
Jim Grosbachf6c05252011-07-21 17:23:04 +00002750ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2751parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2752 int Low, int High) {
2753 const AsmToken &Tok = Parser.getTok();
2754 if (Tok.isNot(AsmToken::Identifier)) {
2755 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2756 return MatchOperand_ParseFail;
2757 }
2758 StringRef ShiftName = Tok.getString();
2759 std::string LowerOp = LowercaseString(Op);
2760 std::string UpperOp = UppercaseString(Op);
2761 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2762 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2763 return MatchOperand_ParseFail;
2764 }
2765 Parser.Lex(); // Eat shift type token.
2766
2767 // There must be a '#' and a shift amount.
2768 if (Parser.getTok().isNot(AsmToken::Hash)) {
2769 Error(Parser.getTok().getLoc(), "'#' expected");
2770 return MatchOperand_ParseFail;
2771 }
2772 Parser.Lex(); // Eat hash token.
2773
2774 const MCExpr *ShiftAmount;
2775 SMLoc Loc = Parser.getTok().getLoc();
2776 if (getParser().ParseExpression(ShiftAmount)) {
2777 Error(Loc, "illegal expression");
2778 return MatchOperand_ParseFail;
2779 }
2780 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2781 if (!CE) {
2782 Error(Loc, "constant expression expected");
2783 return MatchOperand_ParseFail;
2784 }
2785 int Val = CE->getValue();
2786 if (Val < Low || Val > High) {
2787 Error(Loc, "immediate value out of range");
2788 return MatchOperand_ParseFail;
2789 }
2790
2791 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2792
2793 return MatchOperand_Success;
2794}
2795
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002796ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2797parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2798 const AsmToken &Tok = Parser.getTok();
2799 SMLoc S = Tok.getLoc();
2800 if (Tok.isNot(AsmToken::Identifier)) {
2801 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2802 return MatchOperand_ParseFail;
2803 }
2804 int Val = StringSwitch<int>(Tok.getString())
2805 .Case("be", 1)
2806 .Case("le", 0)
2807 .Default(-1);
2808 Parser.Lex(); // Eat the token.
2809
2810 if (Val == -1) {
2811 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2812 return MatchOperand_ParseFail;
2813 }
2814 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2815 getContext()),
2816 S, Parser.getTok().getLoc()));
2817 return MatchOperand_Success;
2818}
2819
Jim Grosbach580f4a92011-07-25 22:20:28 +00002820/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2821/// instructions. Legal values are:
2822/// lsl #n 'n' in [0,31]
2823/// asr #n 'n' in [1,32]
2824/// n == 32 encoded as n == 0.
2825ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2826parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2827 const AsmToken &Tok = Parser.getTok();
2828 SMLoc S = Tok.getLoc();
2829 if (Tok.isNot(AsmToken::Identifier)) {
2830 Error(S, "shift operator 'asr' or 'lsl' expected");
2831 return MatchOperand_ParseFail;
2832 }
2833 StringRef ShiftName = Tok.getString();
2834 bool isASR;
2835 if (ShiftName == "lsl" || ShiftName == "LSL")
2836 isASR = false;
2837 else if (ShiftName == "asr" || ShiftName == "ASR")
2838 isASR = true;
2839 else {
2840 Error(S, "shift operator 'asr' or 'lsl' expected");
2841 return MatchOperand_ParseFail;
2842 }
2843 Parser.Lex(); // Eat the operator.
2844
2845 // A '#' and a shift amount.
2846 if (Parser.getTok().isNot(AsmToken::Hash)) {
2847 Error(Parser.getTok().getLoc(), "'#' expected");
2848 return MatchOperand_ParseFail;
2849 }
2850 Parser.Lex(); // Eat hash token.
2851
2852 const MCExpr *ShiftAmount;
2853 SMLoc E = Parser.getTok().getLoc();
2854 if (getParser().ParseExpression(ShiftAmount)) {
2855 Error(E, "malformed shift expression");
2856 return MatchOperand_ParseFail;
2857 }
2858 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2859 if (!CE) {
2860 Error(E, "shift amount must be an immediate");
2861 return MatchOperand_ParseFail;
2862 }
2863
2864 int64_t Val = CE->getValue();
2865 if (isASR) {
2866 // Shift amount must be in [1,32]
2867 if (Val < 1 || Val > 32) {
2868 Error(E, "'asr' shift amount must be in range [1,32]");
2869 return MatchOperand_ParseFail;
2870 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002871 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2872 if (isThumb() && Val == 32) {
2873 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2874 return MatchOperand_ParseFail;
2875 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002876 if (Val == 32) Val = 0;
2877 } else {
2878 // Shift amount must be in [1,32]
2879 if (Val < 0 || Val > 31) {
2880 Error(E, "'lsr' shift amount must be in range [0,31]");
2881 return MatchOperand_ParseFail;
2882 }
2883 }
2884
2885 E = Parser.getTok().getLoc();
2886 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2887
2888 return MatchOperand_Success;
2889}
2890
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002891/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2892/// of instructions. Legal values are:
2893/// ror #n 'n' in {0, 8, 16, 24}
2894ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2895parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2896 const AsmToken &Tok = Parser.getTok();
2897 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002898 if (Tok.isNot(AsmToken::Identifier))
2899 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002900 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002901 if (ShiftName != "ror" && ShiftName != "ROR")
2902 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002903 Parser.Lex(); // Eat the operator.
2904
2905 // A '#' and a rotate amount.
2906 if (Parser.getTok().isNot(AsmToken::Hash)) {
2907 Error(Parser.getTok().getLoc(), "'#' expected");
2908 return MatchOperand_ParseFail;
2909 }
2910 Parser.Lex(); // Eat hash token.
2911
2912 const MCExpr *ShiftAmount;
2913 SMLoc E = Parser.getTok().getLoc();
2914 if (getParser().ParseExpression(ShiftAmount)) {
2915 Error(E, "malformed rotate expression");
2916 return MatchOperand_ParseFail;
2917 }
2918 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2919 if (!CE) {
2920 Error(E, "rotate amount must be an immediate");
2921 return MatchOperand_ParseFail;
2922 }
2923
2924 int64_t Val = CE->getValue();
2925 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2926 // normally, zero is represented in asm by omitting the rotate operand
2927 // entirely.
2928 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2929 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2930 return MatchOperand_ParseFail;
2931 }
2932
2933 E = Parser.getTok().getLoc();
2934 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2935
2936 return MatchOperand_Success;
2937}
2938
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002939ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2940parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2941 SMLoc S = Parser.getTok().getLoc();
2942 // The bitfield descriptor is really two operands, the LSB and the width.
2943 if (Parser.getTok().isNot(AsmToken::Hash)) {
2944 Error(Parser.getTok().getLoc(), "'#' expected");
2945 return MatchOperand_ParseFail;
2946 }
2947 Parser.Lex(); // Eat hash token.
2948
2949 const MCExpr *LSBExpr;
2950 SMLoc E = Parser.getTok().getLoc();
2951 if (getParser().ParseExpression(LSBExpr)) {
2952 Error(E, "malformed immediate expression");
2953 return MatchOperand_ParseFail;
2954 }
2955 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2956 if (!CE) {
2957 Error(E, "'lsb' operand must be an immediate");
2958 return MatchOperand_ParseFail;
2959 }
2960
2961 int64_t LSB = CE->getValue();
2962 // The LSB must be in the range [0,31]
2963 if (LSB < 0 || LSB > 31) {
2964 Error(E, "'lsb' operand must be in the range [0,31]");
2965 return MatchOperand_ParseFail;
2966 }
2967 E = Parser.getTok().getLoc();
2968
2969 // Expect another immediate operand.
2970 if (Parser.getTok().isNot(AsmToken::Comma)) {
2971 Error(Parser.getTok().getLoc(), "too few operands");
2972 return MatchOperand_ParseFail;
2973 }
2974 Parser.Lex(); // Eat hash token.
2975 if (Parser.getTok().isNot(AsmToken::Hash)) {
2976 Error(Parser.getTok().getLoc(), "'#' expected");
2977 return MatchOperand_ParseFail;
2978 }
2979 Parser.Lex(); // Eat hash token.
2980
2981 const MCExpr *WidthExpr;
2982 if (getParser().ParseExpression(WidthExpr)) {
2983 Error(E, "malformed immediate expression");
2984 return MatchOperand_ParseFail;
2985 }
2986 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2987 if (!CE) {
2988 Error(E, "'width' operand must be an immediate");
2989 return MatchOperand_ParseFail;
2990 }
2991
2992 int64_t Width = CE->getValue();
2993 // The LSB must be in the range [1,32-lsb]
2994 if (Width < 1 || Width > 32 - LSB) {
2995 Error(E, "'width' operand must be in the range [1,32-lsb]");
2996 return MatchOperand_ParseFail;
2997 }
2998 E = Parser.getTok().getLoc();
2999
3000 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3001
3002 return MatchOperand_Success;
3003}
3004
Jim Grosbach7ce05792011-08-03 23:50:40 +00003005ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3006parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3007 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003008 // postidx_reg := '+' register {, shift}
3009 // | '-' register {, shift}
3010 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003011
3012 // This method must return MatchOperand_NoMatch without consuming any tokens
3013 // in the case where there is no match, as other alternatives take other
3014 // parse methods.
3015 AsmToken Tok = Parser.getTok();
3016 SMLoc S = Tok.getLoc();
3017 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003018 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003019 int Reg = -1;
3020 if (Tok.is(AsmToken::Plus)) {
3021 Parser.Lex(); // Eat the '+' token.
3022 haveEaten = true;
3023 } else if (Tok.is(AsmToken::Minus)) {
3024 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003025 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003026 haveEaten = true;
3027 }
3028 if (Parser.getTok().is(AsmToken::Identifier))
3029 Reg = tryParseRegister();
3030 if (Reg == -1) {
3031 if (!haveEaten)
3032 return MatchOperand_NoMatch;
3033 Error(Parser.getTok().getLoc(), "register expected");
3034 return MatchOperand_ParseFail;
3035 }
3036 SMLoc E = Parser.getTok().getLoc();
3037
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003038 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3039 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003040 if (Parser.getTok().is(AsmToken::Comma)) {
3041 Parser.Lex(); // Eat the ','.
3042 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3043 return MatchOperand_ParseFail;
3044 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003045
3046 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3047 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003048
3049 return MatchOperand_Success;
3050}
3051
Jim Grosbach251bf252011-08-10 21:56:18 +00003052ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3053parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3054 // Check for a post-index addressing register operand. Specifically:
3055 // am3offset := '+' register
3056 // | '-' register
3057 // | register
3058 // | # imm
3059 // | # + imm
3060 // | # - imm
3061
3062 // This method must return MatchOperand_NoMatch without consuming any tokens
3063 // in the case where there is no match, as other alternatives take other
3064 // parse methods.
3065 AsmToken Tok = Parser.getTok();
3066 SMLoc S = Tok.getLoc();
3067
3068 // Do immediates first, as we always parse those if we have a '#'.
3069 if (Parser.getTok().is(AsmToken::Hash)) {
3070 Parser.Lex(); // Eat the '#'.
3071 // Explicitly look for a '-', as we need to encode negative zero
3072 // differently.
3073 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3074 const MCExpr *Offset;
3075 if (getParser().ParseExpression(Offset))
3076 return MatchOperand_ParseFail;
3077 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3078 if (!CE) {
3079 Error(S, "constant expression expected");
3080 return MatchOperand_ParseFail;
3081 }
3082 SMLoc E = Tok.getLoc();
3083 // Negative zero is encoded as the flag value INT32_MIN.
3084 int32_t Val = CE->getValue();
3085 if (isNegative && Val == 0)
3086 Val = INT32_MIN;
3087
3088 Operands.push_back(
3089 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3090
3091 return MatchOperand_Success;
3092 }
3093
3094
3095 bool haveEaten = false;
3096 bool isAdd = true;
3097 int Reg = -1;
3098 if (Tok.is(AsmToken::Plus)) {
3099 Parser.Lex(); // Eat the '+' token.
3100 haveEaten = true;
3101 } else if (Tok.is(AsmToken::Minus)) {
3102 Parser.Lex(); // Eat the '-' token.
3103 isAdd = false;
3104 haveEaten = true;
3105 }
3106 if (Parser.getTok().is(AsmToken::Identifier))
3107 Reg = tryParseRegister();
3108 if (Reg == -1) {
3109 if (!haveEaten)
3110 return MatchOperand_NoMatch;
3111 Error(Parser.getTok().getLoc(), "register expected");
3112 return MatchOperand_ParseFail;
3113 }
3114 SMLoc E = Parser.getTok().getLoc();
3115
3116 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3117 0, S, E));
3118
3119 return MatchOperand_Success;
3120}
3121
Jim Grosbacha77295d2011-09-08 22:07:06 +00003122/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3123/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3124/// when they refer multiple MIOperands inside a single one.
3125bool ARMAsmParser::
3126cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3127 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3128 // Rt, Rt2
3129 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3130 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3131 // Create a writeback register dummy placeholder.
3132 Inst.addOperand(MCOperand::CreateReg(0));
3133 // addr
3134 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3135 // pred
3136 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3137 return true;
3138}
3139
3140/// cvtT2StrdPre - Convert parsed operands to MCInst.
3141/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3142/// when they refer multiple MIOperands inside a single one.
3143bool ARMAsmParser::
3144cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3145 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3146 // Create a writeback register dummy placeholder.
3147 Inst.addOperand(MCOperand::CreateReg(0));
3148 // Rt, Rt2
3149 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3150 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3151 // addr
3152 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3153 // pred
3154 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3155 return true;
3156}
3157
Jim Grosbacheeec0252011-09-08 00:39:19 +00003158/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3159/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3160/// when they refer multiple MIOperands inside a single one.
3161bool ARMAsmParser::
3162cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3163 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3164 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3165
3166 // Create a writeback register dummy placeholder.
3167 Inst.addOperand(MCOperand::CreateImm(0));
3168
3169 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3170 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3171 return true;
3172}
3173
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003174/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3175/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3176/// when they refer multiple MIOperands inside a single one.
3177bool ARMAsmParser::
3178cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3179 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3180 // Create a writeback register dummy placeholder.
3181 Inst.addOperand(MCOperand::CreateImm(0));
3182 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3183 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3184 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3185 return true;
3186}
3187
Jim Grosbach1355cf12011-07-26 17:10:22 +00003188/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003189/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3190/// when they refer multiple MIOperands inside a single one.
3191bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003192cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003193 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3194 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3195
3196 // Create a writeback register dummy placeholder.
3197 Inst.addOperand(MCOperand::CreateImm(0));
3198
Jim Grosbach7ce05792011-08-03 23:50:40 +00003199 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003200 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3201 return true;
3202}
3203
Owen Anderson9ab0f252011-08-26 20:43:14 +00003204/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3205/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3206/// when they refer multiple MIOperands inside a single one.
3207bool ARMAsmParser::
3208cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3209 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3210 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3211
3212 // Create a writeback register dummy placeholder.
3213 Inst.addOperand(MCOperand::CreateImm(0));
3214
3215 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3216 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3217 return true;
3218}
3219
3220
Jim Grosbach548340c2011-08-11 19:22:40 +00003221/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3222/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3223/// when they refer multiple MIOperands inside a single one.
3224bool ARMAsmParser::
3225cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3226 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3227 // Create a writeback register dummy placeholder.
3228 Inst.addOperand(MCOperand::CreateImm(0));
3229 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3230 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3231 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3232 return true;
3233}
3234
Jim Grosbach1355cf12011-07-26 17:10:22 +00003235/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003236/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3237/// when they refer multiple MIOperands inside a single one.
3238bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003239cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003240 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3241 // Create a writeback register dummy placeholder.
3242 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003243 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3244 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3245 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003246 return true;
3247}
3248
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003249/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3250/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3251/// when they refer multiple MIOperands inside a single one.
3252bool ARMAsmParser::
3253cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3254 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3255 // Create a writeback register dummy placeholder.
3256 Inst.addOperand(MCOperand::CreateImm(0));
3257 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3258 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3259 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3260 return true;
3261}
3262
Jim Grosbach7ce05792011-08-03 23:50:40 +00003263/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3264/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3265/// when they refer multiple MIOperands inside a single one.
3266bool ARMAsmParser::
3267cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3268 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3269 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003270 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003271 // Create a writeback register dummy placeholder.
3272 Inst.addOperand(MCOperand::CreateImm(0));
3273 // addr
3274 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3275 // offset
3276 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3277 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003278 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3279 return true;
3280}
3281
Jim Grosbach7ce05792011-08-03 23:50:40 +00003282/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003283/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3284/// when they refer multiple MIOperands inside a single one.
3285bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003286cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3287 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3288 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003289 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003290 // Create a writeback register dummy placeholder.
3291 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003292 // addr
3293 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3294 // offset
3295 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3296 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003297 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3298 return true;
3299}
3300
Jim Grosbach7ce05792011-08-03 23:50:40 +00003301/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003302/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3303/// when they refer multiple MIOperands inside a single one.
3304bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003305cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3306 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003307 // Create a writeback register dummy placeholder.
3308 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003309 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003310 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003311 // addr
3312 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3313 // offset
3314 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3315 // pred
3316 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3317 return true;
3318}
3319
3320/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3321/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3322/// when they refer multiple MIOperands inside a single one.
3323bool ARMAsmParser::
3324cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3325 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3326 // Create a writeback register dummy placeholder.
3327 Inst.addOperand(MCOperand::CreateImm(0));
3328 // Rt
3329 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3330 // addr
3331 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3332 // offset
3333 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3334 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003335 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3336 return true;
3337}
3338
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003339/// cvtLdrdPre - Convert parsed operands to MCInst.
3340/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3341/// when they refer multiple MIOperands inside a single one.
3342bool ARMAsmParser::
3343cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3344 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3345 // Rt, Rt2
3346 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3347 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3348 // Create a writeback register dummy placeholder.
3349 Inst.addOperand(MCOperand::CreateImm(0));
3350 // addr
3351 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3352 // pred
3353 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3354 return true;
3355}
3356
Jim Grosbach14605d12011-08-11 20:28:23 +00003357/// cvtStrdPre - Convert parsed operands to MCInst.
3358/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3359/// when they refer multiple MIOperands inside a single one.
3360bool ARMAsmParser::
3361cvtStrdPre(MCInst &Inst, unsigned Opcode,
3362 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3363 // Create a writeback register dummy placeholder.
3364 Inst.addOperand(MCOperand::CreateImm(0));
3365 // Rt, Rt2
3366 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3367 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3368 // addr
3369 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3370 // pred
3371 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3372 return true;
3373}
3374
Jim Grosbach623a4542011-08-10 22:42:16 +00003375/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3376/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3377/// when they refer multiple MIOperands inside a single one.
3378bool ARMAsmParser::
3379cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3380 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3381 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3382 // Create a writeback register dummy placeholder.
3383 Inst.addOperand(MCOperand::CreateImm(0));
3384 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3385 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3386 return true;
3387}
3388
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003389/// cvtThumbMultiple- Convert parsed operands to MCInst.
3390/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3391/// when they refer multiple MIOperands inside a single one.
3392bool ARMAsmParser::
3393cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3394 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3395 // The second source operand must be the same register as the destination
3396 // operand.
3397 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003398 (((ARMOperand*)Operands[3])->getReg() !=
3399 ((ARMOperand*)Operands[5])->getReg()) &&
3400 (((ARMOperand*)Operands[3])->getReg() !=
3401 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003402 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003403 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003404 return false;
3405 }
3406 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3407 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3408 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003409 // If we have a three-operand form, use that, else the second source operand
3410 // is just the destination operand again.
3411 if (Operands.size() == 6)
3412 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3413 else
3414 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003415 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3416
3417 return true;
3418}
Jim Grosbach623a4542011-08-10 22:42:16 +00003419
Jim Grosbach12431322011-10-24 22:16:58 +00003420bool ARMAsmParser::
3421cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3422 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3423 // Vd
3424 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3425 // Create a writeback register dummy placeholder.
3426 Inst.addOperand(MCOperand::CreateImm(0));
3427 // Vn
3428 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3429 // pred
3430 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3431 return true;
3432}
3433
3434bool ARMAsmParser::
3435cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3436 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3437 // Vd
3438 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3439 // Create a writeback register dummy placeholder.
3440 Inst.addOperand(MCOperand::CreateImm(0));
3441 // Vn
3442 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3443 // Vm
3444 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3445 // pred
3446 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3447 return true;
3448}
3449
Jim Grosbach4334e032011-10-31 21:50:31 +00003450bool ARMAsmParser::
3451cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3452 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3453 // Create a writeback register dummy placeholder.
3454 Inst.addOperand(MCOperand::CreateImm(0));
3455 // Vn
3456 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3457 // Vt
3458 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3459 // pred
3460 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3461 return true;
3462}
3463
3464bool ARMAsmParser::
3465cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3466 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3467 // Create a writeback register dummy placeholder.
3468 Inst.addOperand(MCOperand::CreateImm(0));
3469 // Vn
3470 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3471 // Vm
3472 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3473 // Vt
3474 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3475 // pred
3476 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3477 return true;
3478}
3479
Bill Wendlinge7176102010-11-06 22:36:58 +00003480/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003481/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003482bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003483parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003484 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003485 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003486 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003487 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003488 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003489
Sean Callanan18b83232010-01-19 21:44:56 +00003490 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003491 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003492 if (BaseRegNum == -1)
3493 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003494
Daniel Dunbar05710932011-01-18 05:34:17 +00003495 // The next token must either be a comma or a closing bracket.
3496 const AsmToken &Tok = Parser.getTok();
3497 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003498 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003499
Jim Grosbach7ce05792011-08-03 23:50:40 +00003500 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003501 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003502 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003503
Jim Grosbach7ce05792011-08-03 23:50:40 +00003504 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003505 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003506
Jim Grosbachfb12f352011-09-19 18:42:21 +00003507 // If there's a pre-indexing writeback marker, '!', just add it as a token
3508 // operand. It's rather odd, but syntactically valid.
3509 if (Parser.getTok().is(AsmToken::Exclaim)) {
3510 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3511 Parser.Lex(); // Eat the '!'.
3512 }
3513
Jim Grosbach7ce05792011-08-03 23:50:40 +00003514 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003515 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003516
Jim Grosbach7ce05792011-08-03 23:50:40 +00003517 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3518 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003519
Jim Grosbach57dcb852011-10-11 17:29:55 +00003520 // If we have a ':', it's an alignment specifier.
3521 if (Parser.getTok().is(AsmToken::Colon)) {
3522 Parser.Lex(); // Eat the ':'.
3523 E = Parser.getTok().getLoc();
3524
3525 const MCExpr *Expr;
3526 if (getParser().ParseExpression(Expr))
3527 return true;
3528
3529 // The expression has to be a constant. Memory references with relocations
3530 // don't come through here, as they use the <label> forms of the relevant
3531 // instructions.
3532 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3533 if (!CE)
3534 return Error (E, "constant expression expected");
3535
3536 unsigned Align = 0;
3537 switch (CE->getValue()) {
3538 default:
3539 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3540 case 64: Align = 8; break;
3541 case 128: Align = 16; break;
3542 case 256: Align = 32; break;
3543 }
3544
3545 // Now we should have the closing ']'
3546 E = Parser.getTok().getLoc();
3547 if (Parser.getTok().isNot(AsmToken::RBrac))
3548 return Error(E, "']' expected");
3549 Parser.Lex(); // Eat right bracket token.
3550
3551 // Don't worry about range checking the value here. That's handled by
3552 // the is*() predicates.
3553 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3554 ARM_AM::no_shift, 0, Align,
3555 false, S, E));
3556
3557 // If there's a pre-indexing writeback marker, '!', just add it as a token
3558 // operand.
3559 if (Parser.getTok().is(AsmToken::Exclaim)) {
3560 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3561 Parser.Lex(); // Eat the '!'.
3562 }
3563
3564 return false;
3565 }
3566
3567 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003568 // offset.
3569 if (Parser.getTok().is(AsmToken::Hash)) {
3570 Parser.Lex(); // Eat the '#'.
3571 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003572
Owen Anderson0da10cf2011-08-29 19:36:44 +00003573 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003574 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003575 if (getParser().ParseExpression(Offset))
3576 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003577
3578 // The expression has to be a constant. Memory references with relocations
3579 // don't come through here, as they use the <label> forms of the relevant
3580 // instructions.
3581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3582 if (!CE)
3583 return Error (E, "constant expression expected");
3584
Owen Anderson0da10cf2011-08-29 19:36:44 +00003585 // If the constant was #-0, represent it as INT32_MIN.
3586 int32_t Val = CE->getValue();
3587 if (isNegative && Val == 0)
3588 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3589
Jim Grosbach7ce05792011-08-03 23:50:40 +00003590 // Now we should have the closing ']'
3591 E = Parser.getTok().getLoc();
3592 if (Parser.getTok().isNot(AsmToken::RBrac))
3593 return Error(E, "']' expected");
3594 Parser.Lex(); // Eat right bracket token.
3595
3596 // Don't worry about range checking the value here. That's handled by
3597 // the is*() predicates.
3598 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003599 ARM_AM::no_shift, 0, 0,
3600 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003601
3602 // If there's a pre-indexing writeback marker, '!', just add it as a token
3603 // operand.
3604 if (Parser.getTok().is(AsmToken::Exclaim)) {
3605 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3606 Parser.Lex(); // Eat the '!'.
3607 }
3608
3609 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003610 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003611
3612 // The register offset is optionally preceded by a '+' or '-'
3613 bool isNegative = false;
3614 if (Parser.getTok().is(AsmToken::Minus)) {
3615 isNegative = true;
3616 Parser.Lex(); // Eat the '-'.
3617 } else if (Parser.getTok().is(AsmToken::Plus)) {
3618 // Nothing to do.
3619 Parser.Lex(); // Eat the '+'.
3620 }
3621
3622 E = Parser.getTok().getLoc();
3623 int OffsetRegNum = tryParseRegister();
3624 if (OffsetRegNum == -1)
3625 return Error(E, "register expected");
3626
3627 // If there's a shift operator, handle it.
3628 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003629 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003630 if (Parser.getTok().is(AsmToken::Comma)) {
3631 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003632 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003633 return true;
3634 }
3635
3636 // Now we should have the closing ']'
3637 E = Parser.getTok().getLoc();
3638 if (Parser.getTok().isNot(AsmToken::RBrac))
3639 return Error(E, "']' expected");
3640 Parser.Lex(); // Eat right bracket token.
3641
3642 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003643 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003644 S, E));
3645
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003646 // If there's a pre-indexing writeback marker, '!', just add it as a token
3647 // operand.
3648 if (Parser.getTok().is(AsmToken::Exclaim)) {
3649 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3650 Parser.Lex(); // Eat the '!'.
3651 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003652
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003653 return false;
3654}
3655
Jim Grosbach7ce05792011-08-03 23:50:40 +00003656/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003657/// ( lsl | lsr | asr | ror ) , # shift_amount
3658/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003659/// return true if it parses a shift otherwise it returns false.
3660bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3661 unsigned &Amount) {
3662 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003663 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003664 if (Tok.isNot(AsmToken::Identifier))
3665 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003666 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003667 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003668 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003669 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003670 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003671 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003672 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003673 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003674 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003675 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003676 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003677 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003678 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003679 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003680
Jim Grosbach7ce05792011-08-03 23:50:40 +00003681 // rrx stands alone.
3682 Amount = 0;
3683 if (St != ARM_AM::rrx) {
3684 Loc = Parser.getTok().getLoc();
3685 // A '#' and a shift amount.
3686 const AsmToken &HashTok = Parser.getTok();
3687 if (HashTok.isNot(AsmToken::Hash))
3688 return Error(HashTok.getLoc(), "'#' expected");
3689 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003690
Jim Grosbach7ce05792011-08-03 23:50:40 +00003691 const MCExpr *Expr;
3692 if (getParser().ParseExpression(Expr))
3693 return true;
3694 // Range check the immediate.
3695 // lsl, ror: 0 <= imm <= 31
3696 // lsr, asr: 0 <= imm <= 32
3697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3698 if (!CE)
3699 return Error(Loc, "shift amount must be an immediate");
3700 int64_t Imm = CE->getValue();
3701 if (Imm < 0 ||
3702 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3703 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3704 return Error(Loc, "immediate shift value out of range");
3705 Amount = Imm;
3706 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003707
3708 return false;
3709}
3710
Jim Grosbach9d390362011-10-03 23:38:36 +00003711/// parseFPImm - A floating point immediate expression operand.
3712ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3713parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3714 SMLoc S = Parser.getTok().getLoc();
3715
3716 if (Parser.getTok().isNot(AsmToken::Hash))
3717 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003718
3719 // Disambiguate the VMOV forms that can accept an FP immediate.
3720 // vmov.f32 <sreg>, #imm
3721 // vmov.f64 <dreg>, #imm
3722 // vmov.f32 <dreg>, #imm @ vector f32x2
3723 // vmov.f32 <qreg>, #imm @ vector f32x4
3724 //
3725 // There are also the NEON VMOV instructions which expect an
3726 // integer constant. Make sure we don't try to parse an FPImm
3727 // for these:
3728 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3729 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3730 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3731 TyOp->getToken() != ".f64"))
3732 return MatchOperand_NoMatch;
3733
Jim Grosbach9d390362011-10-03 23:38:36 +00003734 Parser.Lex(); // Eat the '#'.
3735
3736 // Handle negation, as that still comes through as a separate token.
3737 bool isNegative = false;
3738 if (Parser.getTok().is(AsmToken::Minus)) {
3739 isNegative = true;
3740 Parser.Lex();
3741 }
3742 const AsmToken &Tok = Parser.getTok();
3743 if (Tok.is(AsmToken::Real)) {
3744 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3745 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3746 // If we had a '-' in front, toggle the sign bit.
3747 IntVal ^= (uint64_t)isNegative << 63;
3748 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3749 Parser.Lex(); // Eat the token.
3750 if (Val == -1) {
3751 TokError("floating point value out of range");
3752 return MatchOperand_ParseFail;
3753 }
3754 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3755 return MatchOperand_Success;
3756 }
3757 if (Tok.is(AsmToken::Integer)) {
3758 int64_t Val = Tok.getIntVal();
3759 Parser.Lex(); // Eat the token.
3760 if (Val > 255 || Val < 0) {
3761 TokError("encoded floating point value out of range");
3762 return MatchOperand_ParseFail;
3763 }
3764 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3765 return MatchOperand_Success;
3766 }
3767
3768 TokError("invalid floating point immediate");
3769 return MatchOperand_ParseFail;
3770}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003771/// Parse a arm instruction operand. For now this parses the operand regardless
3772/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003773bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003774 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003775 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003776
3777 // Check if the current operand has a custom associated parser, if so, try to
3778 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003779 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3780 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003781 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003782 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3783 // there was a match, but an error occurred, in which case, just return that
3784 // the operand parsing failed.
3785 if (ResTy == MatchOperand_ParseFail)
3786 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003787
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003788 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003789 default:
3790 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003791 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003792 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003793 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003794 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003795 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003796 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003797 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003798 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003799 else if (Res == -1) // irrecoverable error
3800 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003801 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3802 S = Parser.getTok().getLoc();
3803 Parser.Lex();
3804 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3805 return false;
3806 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003807
3808 // Fall though for the Identifier case that is not a register or a
3809 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003810 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003811 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003812 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003813 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003814 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003815 // This was not a register so parse other operands that start with an
3816 // identifier (like labels) as expressions and create them as immediates.
3817 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003818 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003819 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003820 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003821 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003822 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3823 return false;
3824 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003825 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003826 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003827 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003828 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003829 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003830 // #42 -> immediate.
3831 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003832 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003833 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003834 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003835 const MCExpr *ImmVal;
3836 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003837 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003838 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003839 if (CE) {
3840 int32_t Val = CE->getValue();
3841 if (isNegative && Val == 0)
3842 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003843 }
Sean Callanan76264762010-04-02 22:27:05 +00003844 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003845 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3846 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003847 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003848 case AsmToken::Colon: {
3849 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003850 // FIXME: Check it's an expression prefix,
3851 // e.g. (FOO - :lower16:BAR) isn't legal.
3852 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003853 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003854 return true;
3855
Evan Cheng75972122011-01-13 07:58:56 +00003856 const MCExpr *SubExprVal;
3857 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003858 return true;
3859
Evan Cheng75972122011-01-13 07:58:56 +00003860 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3861 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003862 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003863 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003864 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003865 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003866 }
3867}
3868
Jim Grosbach1355cf12011-07-26 17:10:22 +00003869// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003870// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003871bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003872 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003873
3874 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003875 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003876 Parser.Lex(); // Eat ':'
3877
3878 if (getLexer().isNot(AsmToken::Identifier)) {
3879 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3880 return true;
3881 }
3882
3883 StringRef IDVal = Parser.getTok().getIdentifier();
3884 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003885 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003886 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003887 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003888 } else {
3889 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3890 return true;
3891 }
3892 Parser.Lex();
3893
3894 if (getLexer().isNot(AsmToken::Colon)) {
3895 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3896 return true;
3897 }
3898 Parser.Lex(); // Eat the last ':'
3899 return false;
3900}
3901
Daniel Dunbar352e1482011-01-11 15:59:50 +00003902/// \brief Given a mnemonic, split out possible predication code and carry
3903/// setting letters to form a canonical mnemonic and flags.
3904//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003905// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003906// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003907StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003908 unsigned &PredicationCode,
3909 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003910 unsigned &ProcessorIMod,
3911 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003912 PredicationCode = ARMCC::AL;
3913 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003914 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003915
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003916 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003917 //
3918 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003919 if ((Mnemonic == "movs" && isThumb()) ||
3920 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3921 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3922 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3923 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3924 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3925 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3926 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003927 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003928
Jim Grosbach3f00e312011-07-11 17:09:57 +00003929 // First, split out any predication code. Ignore mnemonics we know aren't
3930 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003931 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003932 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003933 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003934 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003935 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3936 .Case("eq", ARMCC::EQ)
3937 .Case("ne", ARMCC::NE)
3938 .Case("hs", ARMCC::HS)
3939 .Case("cs", ARMCC::HS)
3940 .Case("lo", ARMCC::LO)
3941 .Case("cc", ARMCC::LO)
3942 .Case("mi", ARMCC::MI)
3943 .Case("pl", ARMCC::PL)
3944 .Case("vs", ARMCC::VS)
3945 .Case("vc", ARMCC::VC)
3946 .Case("hi", ARMCC::HI)
3947 .Case("ls", ARMCC::LS)
3948 .Case("ge", ARMCC::GE)
3949 .Case("lt", ARMCC::LT)
3950 .Case("gt", ARMCC::GT)
3951 .Case("le", ARMCC::LE)
3952 .Case("al", ARMCC::AL)
3953 .Default(~0U);
3954 if (CC != ~0U) {
3955 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3956 PredicationCode = CC;
3957 }
Bill Wendling52925b62010-10-29 23:50:21 +00003958 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003959
Daniel Dunbar352e1482011-01-11 15:59:50 +00003960 // Next, determine if we have a carry setting bit. We explicitly ignore all
3961 // the instructions we know end in 's'.
3962 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003963 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003964 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3965 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3966 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003967 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3968 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003969 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3970 CarrySetting = true;
3971 }
3972
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003973 // The "cps" instruction can have a interrupt mode operand which is glued into
3974 // the mnemonic. Check if this is the case, split it and parse the imod op
3975 if (Mnemonic.startswith("cps")) {
3976 // Split out any imod code.
3977 unsigned IMod =
3978 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3979 .Case("ie", ARM_PROC::IE)
3980 .Case("id", ARM_PROC::ID)
3981 .Default(~0U);
3982 if (IMod != ~0U) {
3983 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3984 ProcessorIMod = IMod;
3985 }
3986 }
3987
Jim Grosbach89df9962011-08-26 21:43:41 +00003988 // The "it" instruction has the condition mask on the end of the mnemonic.
3989 if (Mnemonic.startswith("it")) {
3990 ITMask = Mnemonic.slice(2, Mnemonic.size());
3991 Mnemonic = Mnemonic.slice(0, 2);
3992 }
3993
Daniel Dunbar352e1482011-01-11 15:59:50 +00003994 return Mnemonic;
3995}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003996
3997/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3998/// inclusion of carry set or predication code operands.
3999//
4000// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004001void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004002getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004003 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004004 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4005 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004006 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004007 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004008 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004009 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004010 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004011 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004012 Mnemonic == "mla" || Mnemonic == "smlal" ||
4013 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004014 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004015 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004016 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004017
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004018 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4019 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4020 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4021 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004022 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4023 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004024 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004025 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4026 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4027 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004028 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4029 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004030 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004031 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004032 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004033 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004034
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004035 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004036 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004037 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004038 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004039 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004040}
4041
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004042bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4043 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004044 // FIXME: This is all horribly hacky. We really need a better way to deal
4045 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004046
4047 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4048 // another does not. Specifically, the MOVW instruction does not. So we
4049 // special case it here and remove the defaulted (non-setting) cc_out
4050 // operand if that's the instruction we're trying to match.
4051 //
4052 // We do this as post-processing of the explicit operands rather than just
4053 // conditionally adding the cc_out in the first place because we need
4054 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004055 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004056 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4057 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4058 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4059 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004060
4061 // Register-register 'add' for thumb does not have a cc_out operand
4062 // when there are only two register operands.
4063 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4064 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4065 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4066 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4067 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004068 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004069 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4070 // have to check the immediate range here since Thumb2 has a variant
4071 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004072 if (((isThumb() && Mnemonic == "add") ||
4073 (isThumbTwo() && Mnemonic == "sub")) &&
4074 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004075 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4076 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4077 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004078 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4079 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4080 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004081 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004082 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4083 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004084 // selecting via the generic "add" mnemonic, so to know that we
4085 // should remove the cc_out operand, we have to explicitly check that
4086 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004087 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4088 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004089 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4090 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4091 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4092 // Nest conditions rather than one big 'if' statement for readability.
4093 //
4094 // If either register is a high reg, it's either one of the SP
4095 // variants (handled above) or a 32-bit encoding, so we just
4096 // check against T3.
4097 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4098 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4099 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4100 return false;
4101 // If both registers are low, we're in an IT block, and the immediate is
4102 // in range, we should use encoding T1 instead, which has a cc_out.
4103 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004104 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004105 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4106 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4107 return false;
4108
4109 // Otherwise, we use encoding T4, which does not have a cc_out
4110 // operand.
4111 return true;
4112 }
4113
Jim Grosbach64944f42011-09-14 21:00:40 +00004114 // The thumb2 multiply instruction doesn't have a CCOut register, so
4115 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4116 // use the 16-bit encoding or not.
4117 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4118 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4119 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4120 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4121 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4122 // If the registers aren't low regs, the destination reg isn't the
4123 // same as one of the source regs, or the cc_out operand is zero
4124 // outside of an IT block, we have to use the 32-bit encoding, so
4125 // remove the cc_out operand.
4126 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4127 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4128 !inITBlock() ||
4129 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4130 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4131 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4132 static_cast<ARMOperand*>(Operands[4])->getReg())))
4133 return true;
4134
4135
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004136
Jim Grosbachf69c8042011-08-24 21:42:27 +00004137 // Register-register 'add/sub' for thumb does not have a cc_out operand
4138 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4139 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4140 // right, this will result in better diagnostics (which operand is off)
4141 // anyway.
4142 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4143 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004144 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4145 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4146 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4147 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004148
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004149 return false;
4150}
4151
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004152/// Parse an arm instruction mnemonic followed by its operands.
4153bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4154 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4155 // Create the leading tokens for the mnemonic, split by '.' characters.
4156 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004157 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004158
Daniel Dunbar352e1482011-01-11 15:59:50 +00004159 // Split out the predication code and carry setting flag from the mnemonic.
4160 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004161 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004162 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004163 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004164 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004165 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004166
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004167 // In Thumb1, only the branch (B) instruction can be predicated.
4168 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4169 Parser.EatToEndOfStatement();
4170 return Error(NameLoc, "conditional execution not supported in Thumb1");
4171 }
4172
Jim Grosbachffa32252011-07-19 19:13:28 +00004173 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4174
Jim Grosbach89df9962011-08-26 21:43:41 +00004175 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4176 // is the mask as it will be for the IT encoding if the conditional
4177 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4178 // where the conditional bit0 is zero, the instruction post-processing
4179 // will adjust the mask accordingly.
4180 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004181 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4182 if (ITMask.size() > 3) {
4183 Parser.EatToEndOfStatement();
4184 return Error(Loc, "too many conditions on IT instruction");
4185 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004186 unsigned Mask = 8;
4187 for (unsigned i = ITMask.size(); i != 0; --i) {
4188 char pos = ITMask[i - 1];
4189 if (pos != 't' && pos != 'e') {
4190 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004191 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004192 }
4193 Mask >>= 1;
4194 if (ITMask[i - 1] == 't')
4195 Mask |= 8;
4196 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004197 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004198 }
4199
Jim Grosbachffa32252011-07-19 19:13:28 +00004200 // FIXME: This is all a pretty gross hack. We should automatically handle
4201 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004202
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004203 // Next, add the CCOut and ConditionCode operands, if needed.
4204 //
4205 // For mnemonics which can ever incorporate a carry setting bit or predication
4206 // code, our matching model involves us always generating CCOut and
4207 // ConditionCode operands to match the mnemonic "as written" and then we let
4208 // the matcher deal with finding the right instruction or generating an
4209 // appropriate error.
4210 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004211 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004212
Jim Grosbach33c16a22011-07-14 22:04:21 +00004213 // If we had a carry-set on an instruction that can't do that, issue an
4214 // error.
4215 if (!CanAcceptCarrySet && CarrySetting) {
4216 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004217 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004218 "' can not set flags, but 's' suffix specified");
4219 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004220 // If we had a predication code on an instruction that can't do that, issue an
4221 // error.
4222 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4223 Parser.EatToEndOfStatement();
4224 return Error(NameLoc, "instruction '" + Mnemonic +
4225 "' is not predicable, but condition code specified");
4226 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004227
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004228 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004229 if (CanAcceptCarrySet) {
4230 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004231 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004232 Loc));
4233 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004234
4235 // Add the predication code operand, if necessary.
4236 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004237 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4238 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004239 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004240 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004241 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004242
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004243 // Add the processor imod operand, if necessary.
4244 if (ProcessorIMod) {
4245 Operands.push_back(ARMOperand::CreateImm(
4246 MCConstantExpr::Create(ProcessorIMod, getContext()),
4247 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004248 }
4249
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004250 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004251 while (Next != StringRef::npos) {
4252 Start = Next;
4253 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004254 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004255
Jim Grosbach4d23e992011-08-24 22:19:48 +00004256 // For now, we're only parsing Thumb1 (for the most part), so
4257 // just ignore ".n" qualifiers. We'll use them to restrict
4258 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004259 if (ExtraToken != ".n") {
4260 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4261 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4262 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004263 }
4264
4265 // Read the remaining operands.
4266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004267 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004268 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004269 Parser.EatToEndOfStatement();
4270 return true;
4271 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004272
4273 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004274 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004275
4276 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004277 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004278 Parser.EatToEndOfStatement();
4279 return true;
4280 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004281 }
4282 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004283
Chris Lattnercbf8a982010-09-11 16:18:25 +00004284 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004285 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004286 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004287 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004288 }
Bill Wendling146018f2010-11-06 21:42:12 +00004289
Chris Lattner34e53142010-09-08 05:10:46 +00004290 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004291
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004292 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4293 // do and don't have a cc_out optional-def operand. With some spot-checks
4294 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004295 // parse and adjust accordingly before actually matching. We shouldn't ever
4296 // try to remove a cc_out operand that was explicitly set on the the
4297 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4298 // table driven matcher doesn't fit well with the ARM instruction set.
4299 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004300 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4301 Operands.erase(Operands.begin() + 1);
4302 delete Op;
4303 }
4304
Jim Grosbachcf121c32011-07-28 21:57:55 +00004305 // ARM mode 'blx' need special handling, as the register operand version
4306 // is predicable, but the label operand version is not. So, we can't rely
4307 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004308 // a k_CondCode operand in the list. If we're trying to match the label
4309 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004310 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4311 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4312 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4313 Operands.erase(Operands.begin() + 1);
4314 delete Op;
4315 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004316
4317 // The vector-compare-to-zero instructions have a literal token "#0" at
4318 // the end that comes to here as an immediate operand. Convert it to a
4319 // token to play nicely with the matcher.
4320 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4321 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4322 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4323 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4324 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4325 if (CE && CE->getValue() == 0) {
4326 Operands.erase(Operands.begin() + 5);
4327 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4328 delete Op;
4329 }
4330 }
Jim Grosbach68259142011-10-03 22:30:24 +00004331 // VCMP{E} does the same thing, but with a different operand count.
4332 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4333 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4334 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4335 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4336 if (CE && CE->getValue() == 0) {
4337 Operands.erase(Operands.begin() + 4);
4338 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4339 delete Op;
4340 }
4341 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004342 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4343 // end. Convert it to a token here.
4344 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4345 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4346 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4347 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4348 if (CE && CE->getValue() == 0) {
4349 Operands.erase(Operands.begin() + 5);
4350 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4351 delete Op;
4352 }
4353 }
4354
Chris Lattner98986712010-01-14 22:21:20 +00004355 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004356}
4357
Jim Grosbach189610f2011-07-26 18:25:39 +00004358// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004359
4360// return 'true' if register list contains non-low GPR registers,
4361// 'false' otherwise. If Reg is in the register list or is HiReg, set
4362// 'containsReg' to true.
4363static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4364 unsigned HiReg, bool &containsReg) {
4365 containsReg = false;
4366 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4367 unsigned OpReg = Inst.getOperand(i).getReg();
4368 if (OpReg == Reg)
4369 containsReg = true;
4370 // Anything other than a low register isn't legal here.
4371 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4372 return true;
4373 }
4374 return false;
4375}
4376
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004377// Check if the specified regisgter is in the register list of the inst,
4378// starting at the indicated operand number.
4379static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4380 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4381 unsigned OpReg = Inst.getOperand(i).getReg();
4382 if (OpReg == Reg)
4383 return true;
4384 }
4385 return false;
4386}
4387
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004388// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4389// the ARMInsts array) instead. Getting that here requires awkward
4390// API changes, though. Better way?
4391namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004392extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004393}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004394static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004395 return ARMInsts[Opcode];
4396}
4397
Jim Grosbach189610f2011-07-26 18:25:39 +00004398// FIXME: We would really like to be able to tablegen'erate this.
4399bool ARMAsmParser::
4400validateInstruction(MCInst &Inst,
4401 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004402 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004403 SMLoc Loc = Operands[0]->getStartLoc();
4404 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004405 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4406 // being allowed in IT blocks, but not being predicable. It just always
4407 // executes.
4408 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004409 unsigned bit = 1;
4410 if (ITState.FirstCond)
4411 ITState.FirstCond = false;
4412 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004413 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004414 // The instruction must be predicable.
4415 if (!MCID.isPredicable())
4416 return Error(Loc, "instructions in IT block must be predicable");
4417 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4418 unsigned ITCond = bit ? ITState.Cond :
4419 ARMCC::getOppositeCondition(ITState.Cond);
4420 if (Cond != ITCond) {
4421 // Find the condition code Operand to get its SMLoc information.
4422 SMLoc CondLoc;
4423 for (unsigned i = 1; i < Operands.size(); ++i)
4424 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4425 CondLoc = Operands[i]->getStartLoc();
4426 return Error(CondLoc, "incorrect condition in IT block; got '" +
4427 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4428 "', but expected '" +
4429 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4430 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004431 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004432 } else if (isThumbTwo() && MCID.isPredicable() &&
4433 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004434 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4435 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004436 return Error(Loc, "predicated instructions must be in IT block");
4437
Jim Grosbach189610f2011-07-26 18:25:39 +00004438 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004439 case ARM::LDRD:
4440 case ARM::LDRD_PRE:
4441 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004442 case ARM::LDREXD: {
4443 // Rt2 must be Rt + 1.
4444 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4445 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4446 if (Rt2 != Rt + 1)
4447 return Error(Operands[3]->getStartLoc(),
4448 "destination operands must be sequential");
4449 return false;
4450 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004451 case ARM::STRD: {
4452 // Rt2 must be Rt + 1.
4453 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4454 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4455 if (Rt2 != Rt + 1)
4456 return Error(Operands[3]->getStartLoc(),
4457 "source operands must be sequential");
4458 return false;
4459 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004460 case ARM::STRD_PRE:
4461 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004462 case ARM::STREXD: {
4463 // Rt2 must be Rt + 1.
4464 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4465 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4466 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004467 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004468 "source operands must be sequential");
4469 return false;
4470 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004471 case ARM::SBFX:
4472 case ARM::UBFX: {
4473 // width must be in range [1, 32-lsb]
4474 unsigned lsb = Inst.getOperand(2).getImm();
4475 unsigned widthm1 = Inst.getOperand(3).getImm();
4476 if (widthm1 >= 32 - lsb)
4477 return Error(Operands[5]->getStartLoc(),
4478 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004479 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004480 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004481 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004482 // If we're parsing Thumb2, the .w variant is available and handles
4483 // most cases that are normally illegal for a Thumb1 LDM
4484 // instruction. We'll make the transformation in processInstruction()
4485 // if necessary.
4486 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004487 // Thumb LDM instructions are writeback iff the base register is not
4488 // in the register list.
4489 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004490 bool hasWritebackToken =
4491 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4492 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004493 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004494 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004495 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4496 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004497 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004498 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004499 return Error(Operands[2]->getStartLoc(),
4500 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004501 // If we should not have writeback, there must not be a '!'. This is
4502 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004503 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004504 return Error(Operands[3]->getStartLoc(),
4505 "writeback operator '!' not allowed when base register "
4506 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004507
4508 break;
4509 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004510 case ARM::t2LDMIA_UPD: {
4511 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4512 return Error(Operands[4]->getStartLoc(),
4513 "writeback operator '!' not allowed when base register "
4514 "in register list");
4515 break;
4516 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004517 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004518 bool listContainsBase;
4519 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4520 return Error(Operands[2]->getStartLoc(),
4521 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004522 break;
4523 }
4524 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004525 bool listContainsBase;
4526 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4527 return Error(Operands[2]->getStartLoc(),
4528 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004529 break;
4530 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004531 case ARM::tSTMIA_UPD: {
4532 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004533 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004534 return Error(Operands[4]->getStartLoc(),
4535 "registers must be in range r0-r7");
4536 break;
4537 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004538 }
4539
4540 return false;
4541}
4542
Jim Grosbachf8fce712011-08-11 17:35:48 +00004543void ARMAsmParser::
4544processInstruction(MCInst &Inst,
4545 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4546 switch (Inst.getOpcode()) {
4547 case ARM::LDMIA_UPD:
4548 // If this is a load of a single register via a 'pop', then we should use
4549 // a post-indexed LDR instruction instead, per the ARM ARM.
4550 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4551 Inst.getNumOperands() == 5) {
4552 MCInst TmpInst;
4553 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4554 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4555 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4556 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4557 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4558 TmpInst.addOperand(MCOperand::CreateImm(4));
4559 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4560 TmpInst.addOperand(Inst.getOperand(3));
4561 Inst = TmpInst;
4562 }
4563 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004564 case ARM::STMDB_UPD:
4565 // If this is a store of a single register via a 'push', then we should use
4566 // a pre-indexed STR instruction instead, per the ARM ARM.
4567 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4568 Inst.getNumOperands() == 5) {
4569 MCInst TmpInst;
4570 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4571 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4572 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4573 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4574 TmpInst.addOperand(MCOperand::CreateImm(-4));
4575 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4576 TmpInst.addOperand(Inst.getOperand(3));
4577 Inst = TmpInst;
4578 }
4579 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004580 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004581 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4582 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4583 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4584 // to encoding T1 if <Rd> is omitted."
4585 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004586 Inst.setOpcode(ARM::tADDi3);
4587 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004588 case ARM::tSUBi8:
4589 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4590 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4591 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4592 // to encoding T1 if <Rd> is omitted."
4593 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4594 Inst.setOpcode(ARM::tSUBi3);
4595 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004596 case ARM::tB:
4597 // A Thumb conditional branch outside of an IT block is a tBcc.
4598 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4599 Inst.setOpcode(ARM::tBcc);
4600 break;
4601 case ARM::t2B:
4602 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4603 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4604 Inst.setOpcode(ARM::t2Bcc);
4605 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004606 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004607 // If the conditional is AL or we're in an IT block, we really want t2B.
4608 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004609 Inst.setOpcode(ARM::t2B);
4610 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004611 case ARM::tBcc:
4612 // If the conditional is AL, we really want tB.
4613 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4614 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004615 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004616 case ARM::tLDMIA: {
4617 // If the register list contains any high registers, or if the writeback
4618 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4619 // instead if we're in Thumb2. Otherwise, this should have generated
4620 // an error in validateInstruction().
4621 unsigned Rn = Inst.getOperand(0).getReg();
4622 bool hasWritebackToken =
4623 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4624 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4625 bool listContainsBase;
4626 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4627 (!listContainsBase && !hasWritebackToken) ||
4628 (listContainsBase && hasWritebackToken)) {
4629 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4630 assert (isThumbTwo());
4631 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4632 // If we're switching to the updating version, we need to insert
4633 // the writeback tied operand.
4634 if (hasWritebackToken)
4635 Inst.insert(Inst.begin(),
4636 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4637 }
4638 break;
4639 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004640 case ARM::tSTMIA_UPD: {
4641 // If the register list contains any high registers, we need to use
4642 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4643 // should have generated an error in validateInstruction().
4644 unsigned Rn = Inst.getOperand(0).getReg();
4645 bool listContainsBase;
4646 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4647 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4648 assert (isThumbTwo());
4649 Inst.setOpcode(ARM::t2STMIA_UPD);
4650 }
4651 break;
4652 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004653 case ARM::t2MOVi: {
4654 // If we can use the 16-bit encoding and the user didn't explicitly
4655 // request the 32-bit variant, transform it here.
4656 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4657 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004658 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4659 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4660 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004661 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4662 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4663 // The operands aren't in the same order for tMOVi8...
4664 MCInst TmpInst;
4665 TmpInst.setOpcode(ARM::tMOVi8);
4666 TmpInst.addOperand(Inst.getOperand(0));
4667 TmpInst.addOperand(Inst.getOperand(4));
4668 TmpInst.addOperand(Inst.getOperand(1));
4669 TmpInst.addOperand(Inst.getOperand(2));
4670 TmpInst.addOperand(Inst.getOperand(3));
4671 Inst = TmpInst;
4672 }
4673 break;
4674 }
4675 case ARM::t2MOVr: {
4676 // If we can use the 16-bit encoding and the user didn't explicitly
4677 // request the 32-bit variant, transform it here.
4678 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4679 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4680 Inst.getOperand(2).getImm() == ARMCC::AL &&
4681 Inst.getOperand(4).getReg() == ARM::CPSR &&
4682 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4683 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4684 // The operands aren't the same for tMOV[S]r... (no cc_out)
4685 MCInst TmpInst;
4686 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4687 TmpInst.addOperand(Inst.getOperand(0));
4688 TmpInst.addOperand(Inst.getOperand(1));
4689 TmpInst.addOperand(Inst.getOperand(2));
4690 TmpInst.addOperand(Inst.getOperand(3));
4691 Inst = TmpInst;
4692 }
4693 break;
4694 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004695 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004696 case ARM::t2SXTB:
4697 case ARM::t2UXTH:
4698 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004699 // If we can use the 16-bit encoding and the user didn't explicitly
4700 // request the 32-bit variant, transform it here.
4701 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4702 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4703 Inst.getOperand(2).getImm() == 0 &&
4704 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4705 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004706 unsigned NewOpc;
4707 switch (Inst.getOpcode()) {
4708 default: llvm_unreachable("Illegal opcode!");
4709 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4710 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4711 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4712 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4713 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004714 // The operands aren't the same for thumb1 (no rotate operand).
4715 MCInst TmpInst;
4716 TmpInst.setOpcode(NewOpc);
4717 TmpInst.addOperand(Inst.getOperand(0));
4718 TmpInst.addOperand(Inst.getOperand(1));
4719 TmpInst.addOperand(Inst.getOperand(3));
4720 TmpInst.addOperand(Inst.getOperand(4));
4721 Inst = TmpInst;
4722 }
4723 break;
4724 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004725 case ARM::t2IT: {
4726 // The mask bits for all but the first condition are represented as
4727 // the low bit of the condition code value implies 't'. We currently
4728 // always have 1 implies 't', so XOR toggle the bits if the low bit
4729 // of the condition code is zero. The encoding also expects the low
4730 // bit of the condition to be encoded as bit 4 of the mask operand,
4731 // so mask that in if needed
4732 MCOperand &MO = Inst.getOperand(1);
4733 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004734 unsigned OrigMask = Mask;
4735 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004736 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004737 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4738 for (unsigned i = 3; i != TZ; --i)
4739 Mask ^= 1 << i;
4740 } else
4741 Mask |= 0x10;
4742 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004743
4744 // Set up the IT block state according to the IT instruction we just
4745 // matched.
4746 assert(!inITBlock() && "nested IT blocks?!");
4747 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4748 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4749 ITState.CurPosition = 0;
4750 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004751 break;
4752 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004753 }
4754}
4755
Jim Grosbach47a0d522011-08-16 20:45:50 +00004756unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4757 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4758 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004759 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004760 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004761 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4762 assert(MCID.hasOptionalDef() &&
4763 "optionally flag setting instruction missing optional def operand");
4764 assert(MCID.NumOperands == Inst.getNumOperands() &&
4765 "operand count mismatch!");
4766 // Find the optional-def operand (cc_out).
4767 unsigned OpNo;
4768 for (OpNo = 0;
4769 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4770 ++OpNo)
4771 ;
4772 // If we're parsing Thumb1, reject it completely.
4773 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4774 return Match_MnemonicFail;
4775 // If we're parsing Thumb2, which form is legal depends on whether we're
4776 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004777 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4778 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004779 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004780 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4781 inITBlock())
4782 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004783 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004784 // Some high-register supporting Thumb1 encodings only allow both registers
4785 // to be from r0-r7 when in Thumb2.
4786 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4787 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4788 isARMLowRegister(Inst.getOperand(2).getReg()))
4789 return Match_RequiresThumb2;
4790 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004791 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004792 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4793 isARMLowRegister(Inst.getOperand(1).getReg()))
4794 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004795 return Match_Success;
4796}
4797
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004798bool ARMAsmParser::
4799MatchAndEmitInstruction(SMLoc IDLoc,
4800 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4801 MCStreamer &Out) {
4802 MCInst Inst;
4803 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004804 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004805 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004806 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004807 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004808 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004809 // Context sensitive operand constraints aren't handled by the matcher,
4810 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004811 if (validateInstruction(Inst, Operands)) {
4812 // Still progress the IT block, otherwise one wrong condition causes
4813 // nasty cascading errors.
4814 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004815 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004816 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004817
Jim Grosbachf8fce712011-08-11 17:35:48 +00004818 // Some instructions need post-processing to, for example, tweak which
4819 // encoding is selected.
4820 processInstruction(Inst, Operands);
4821
Jim Grosbacha1109882011-09-02 23:22:08 +00004822 // Only move forward at the very end so that everything in validate
4823 // and process gets a consistent answer about whether we're in an IT
4824 // block.
4825 forwardITPosition();
4826
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004827 Out.EmitInstruction(Inst);
4828 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004829 case Match_MissingFeature:
4830 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4831 return true;
4832 case Match_InvalidOperand: {
4833 SMLoc ErrorLoc = IDLoc;
4834 if (ErrorInfo != ~0U) {
4835 if (ErrorInfo >= Operands.size())
4836 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004837
Chris Lattnere73d4f82010-10-28 21:41:58 +00004838 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4839 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4840 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004841
Chris Lattnere73d4f82010-10-28 21:41:58 +00004842 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004843 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004844 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004845 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004846 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004847 // The converter function will have already emited a diagnostic.
4848 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004849 case Match_RequiresNotITBlock:
4850 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004851 case Match_RequiresITBlock:
4852 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004853 case Match_RequiresV6:
4854 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4855 case Match_RequiresThumb2:
4856 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004857 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004858
Eric Christopherc223e2b2010-10-29 09:26:59 +00004859 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004860 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004861}
4862
Jim Grosbach1355cf12011-07-26 17:10:22 +00004863/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004864bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4865 StringRef IDVal = DirectiveID.getIdentifier();
4866 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004867 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004868 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004869 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004870 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004871 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004872 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004873 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004874 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004875 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004876 return true;
4877}
4878
Jim Grosbach1355cf12011-07-26 17:10:22 +00004879/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004880/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004881bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004882 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4883 for (;;) {
4884 const MCExpr *Value;
4885 if (getParser().ParseExpression(Value))
4886 return true;
4887
Chris Lattneraaec2052010-01-19 19:46:13 +00004888 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004889
4890 if (getLexer().is(AsmToken::EndOfStatement))
4891 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004892
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004893 // FIXME: Improve diagnostic.
4894 if (getLexer().isNot(AsmToken::Comma))
4895 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004896 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004897 }
4898 }
4899
Sean Callananb9a25b72010-01-19 20:27:46 +00004900 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004901 return false;
4902}
4903
Jim Grosbach1355cf12011-07-26 17:10:22 +00004904/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004905/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004906bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004907 if (getLexer().isNot(AsmToken::EndOfStatement))
4908 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004909 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004910
4911 // TODO: set thumb mode
4912 // TODO: tell the MC streamer the mode
4913 // getParser().getStreamer().Emit???();
4914 return false;
4915}
4916
Jim Grosbach1355cf12011-07-26 17:10:22 +00004917/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004918/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004919bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004920 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4921 bool isMachO = MAI.hasSubsectionsViaSymbols();
4922 StringRef Name;
4923
4924 // Darwin asm has function name after .thumb_func direction
4925 // ELF doesn't
4926 if (isMachO) {
4927 const AsmToken &Tok = Parser.getTok();
4928 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4929 return Error(L, "unexpected token in .thumb_func directive");
4930 Name = Tok.getString();
4931 Parser.Lex(); // Consume the identifier token.
4932 }
4933
Kevin Enderby515d5092009-10-15 20:48:48 +00004934 if (getLexer().isNot(AsmToken::EndOfStatement))
4935 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004936 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004937
Rafael Espindola64695402011-05-16 16:17:21 +00004938 // FIXME: assuming function name will be the line following .thumb_func
4939 if (!isMachO) {
4940 Name = Parser.getTok().getString();
4941 }
4942
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004943 // Mark symbol as a thumb symbol.
4944 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4945 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004946 return false;
4947}
4948
Jim Grosbach1355cf12011-07-26 17:10:22 +00004949/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004950/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004951bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004952 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004953 if (Tok.isNot(AsmToken::Identifier))
4954 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004955 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004956 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004957 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004958 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004959 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004960 else
4961 return Error(L, "unrecognized syntax mode in .syntax directive");
4962
4963 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004964 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004965 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004966
4967 // TODO tell the MC streamer the mode
4968 // getParser().getStreamer().Emit???();
4969 return false;
4970}
4971
Jim Grosbach1355cf12011-07-26 17:10:22 +00004972/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004973/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004974bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004975 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004976 if (Tok.isNot(AsmToken::Integer))
4977 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004978 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004979 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004980 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004981 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004982 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004983 else
4984 return Error(L, "invalid operand to .code directive");
4985
4986 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004987 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004988 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004989
Evan Cheng32869202011-07-08 22:36:29 +00004990 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004991 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004992 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004993 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004994 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004995 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004996 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004997 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004998 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004999
Kevin Enderby515d5092009-10-15 20:48:48 +00005000 return false;
5001}
5002
Sean Callanan90b70972010-04-07 20:29:34 +00005003extern "C" void LLVMInitializeARMAsmLexer();
5004
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005005/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005006extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005007 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5008 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005009 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005010}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005011
Chris Lattner0692ee62010-09-06 19:11:01 +00005012#define GET_REGISTER_MATCHER
5013#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005014#include "ARMGenAsmMatcher.inc"