blob: 81a67868049bb7d5fbb1716038b636755c203c07 [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 Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000143 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000147 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
148 StringRef Op, int Low, int High);
149 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
150 return parsePKHImm(O, "lsl", 0, 31);
151 }
152 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "asr", 1, 32);
154 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000155 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000156 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000157 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000158 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000159 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000160 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000161
162 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000163 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
164 const SmallVectorImpl<MCParsedAsmOperand*> &);
165 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
166 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000167 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
168 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000169 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000171 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000173 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000175 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000177 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000179 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000181 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
183 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
185 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
187 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000189 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000191 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000193 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000195 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000197
198 bool validateInstruction(MCInst &Inst,
199 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000200 void processInstruction(MCInst &Inst,
201 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000202 bool shouldOmitCCOutOperand(StringRef Mnemonic,
203 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000204
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000205public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000206 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000207 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000208 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000209 Match_RequiresV6,
210 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000211 };
212
Evan Chengffc0e732011-07-09 05:47:46 +0000213 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000214 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000215 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000216
Evan Chengebdeeab2011-07-08 01:53:10 +0000217 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000218 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000219
220 // Not in an ITBlock to start with.
221 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000222 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000223
Jim Grosbach1355cf12011-07-26 17:10:22 +0000224 // Implementation of the MCTargetAsmParser interface:
225 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
226 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000227 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000228 bool ParseDirective(AsmToken DirectiveID);
229
Jim Grosbach47a0d522011-08-16 20:45:50 +0000230 unsigned checkTargetMatchPredicate(MCInst &Inst);
231
Jim Grosbach1355cf12011-07-26 17:10:22 +0000232 bool MatchAndEmitInstruction(SMLoc IDLoc,
233 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
234 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000235};
Jim Grosbach16c74252010-10-29 14:46:02 +0000236} // end anonymous namespace
237
Chris Lattner3a697562010-10-28 17:20:03 +0000238namespace {
239
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000240/// ARMOperand - Instances of this class represent a parsed ARM machine
241/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000242class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000243 enum KindTy {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000244 CondCode,
Jim Grosbachd67641b2010-12-06 18:21:12 +0000245 CCOut,
Jim Grosbach89df9962011-08-26 21:43:41 +0000246 ITCondMask,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000247 CoprocNum,
248 CoprocReg,
Kevin Enderbycfe07242009-10-13 22:19:02 +0000249 Immediate,
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000250 MemBarrierOpt,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000251 Memory,
Jim Grosbach7ce05792011-08-03 23:50:40 +0000252 PostIndexRegister,
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000253 MSRMask,
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000254 ProcIFlags,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000255 Register,
Bill Wendling8d5acb72010-11-06 19:56:04 +0000256 RegisterList,
Bill Wendling0f630752010-11-17 04:32:08 +0000257 DPRRegisterList,
258 SPRRegisterList,
Jim Grosbache8606dc2011-07-13 17:50:29 +0000259 ShiftedRegister,
Owen Anderson92a20222011-07-21 18:54:16 +0000260 ShiftedImmediate,
Jim Grosbach580f4a92011-07-25 22:20:28 +0000261 ShifterImmediate,
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000262 RotateImmediate,
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000263 BitfieldDescriptor,
Daniel Dunbar8462b302010-08-11 06:36:53 +0000264 Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000265 } Kind;
266
Sean Callanan76264762010-04-02 22:27:05 +0000267 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000268 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000269
270 union {
271 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000272 ARMCC::CondCodes Val;
273 } CC;
274
275 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000276 unsigned Val;
277 } Cop;
278
279 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000280 unsigned Mask:4;
281 } ITMask;
282
283 struct {
284 ARM_MB::MemBOpt Val;
285 } MBOpt;
286
287 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000288 ARM_PROC::IFlags Val;
289 } IFlags;
290
291 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000292 unsigned Val;
293 } MMask;
294
295 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000296 const char *Data;
297 unsigned Length;
298 } Tok;
299
300 struct {
301 unsigned RegNum;
302 } Reg;
303
Bill Wendling8155e5b2010-11-06 22:19:43 +0000304 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000305 const MCExpr *Val;
306 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000307
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000308 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000309 struct {
310 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000311 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
312 // was specified.
313 const MCConstantExpr *OffsetImm; // Offset immediate value
314 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
315 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach0d6fac32011-08-05 22:03:36 +0000316 unsigned ShiftImm; // shift for OffsetReg.
Jim Grosbach7ce05792011-08-03 23:50:40 +0000317 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000318 } Mem;
Owen Anderson00828302011-03-18 22:50:18 +0000319
320 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000321 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000322 bool isAdd;
323 ARM_AM::ShiftOpc ShiftTy;
324 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000325 } PostIdxReg;
326
327 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000328 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000329 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000330 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000331 struct {
332 ARM_AM::ShiftOpc ShiftTy;
333 unsigned SrcReg;
334 unsigned ShiftReg;
335 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000336 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000337 struct {
338 ARM_AM::ShiftOpc ShiftTy;
339 unsigned SrcReg;
340 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000341 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000342 struct {
343 unsigned Imm;
344 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000345 struct {
346 unsigned LSB;
347 unsigned Width;
348 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000349 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000350
Bill Wendling146018f2010-11-06 21:42:12 +0000351 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
352public:
Sean Callanan76264762010-04-02 22:27:05 +0000353 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
354 Kind = o.Kind;
355 StartLoc = o.StartLoc;
356 EndLoc = o.EndLoc;
357 switch (Kind) {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000358 case CondCode:
359 CC = o.CC;
360 break;
Jim Grosbach89df9962011-08-26 21:43:41 +0000361 case ITCondMask:
362 ITMask = o.ITMask;
363 break;
Sean Callanan76264762010-04-02 22:27:05 +0000364 case Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000365 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000366 break;
Jim Grosbachd67641b2010-12-06 18:21:12 +0000367 case CCOut:
Sean Callanan76264762010-04-02 22:27:05 +0000368 case Register:
369 Reg = o.Reg;
370 break;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000371 case RegisterList:
Bill Wendling0f630752010-11-17 04:32:08 +0000372 case DPRRegisterList:
373 case SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000374 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000375 break;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000376 case CoprocNum:
377 case CoprocReg:
378 Cop = o.Cop;
379 break;
Sean Callanan76264762010-04-02 22:27:05 +0000380 case Immediate:
381 Imm = o.Imm;
382 break;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000383 case MemBarrierOpt:
384 MBOpt = o.MBOpt;
385 break;
Sean Callanan76264762010-04-02 22:27:05 +0000386 case Memory:
387 Mem = o.Mem;
388 break;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000389 case PostIndexRegister:
390 PostIdxReg = o.PostIdxReg;
391 break;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000392 case MSRMask:
393 MMask = o.MMask;
394 break;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000395 case ProcIFlags:
396 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000397 break;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000398 case ShifterImmediate:
399 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000400 break;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000401 case ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000402 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000403 break;
Owen Anderson92a20222011-07-21 18:54:16 +0000404 case ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000405 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000406 break;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000407 case RotateImmediate:
408 RotImm = o.RotImm;
409 break;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000410 case BitfieldDescriptor:
411 Bitfield = o.Bitfield;
412 break;
Sean Callanan76264762010-04-02 22:27:05 +0000413 }
414 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000415
Sean Callanan76264762010-04-02 22:27:05 +0000416 /// getStartLoc - Get the location of the first token of this operand.
417 SMLoc getStartLoc() const { return StartLoc; }
418 /// getEndLoc - Get the location of the last token of this operand.
419 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000420
Daniel Dunbar8462b302010-08-11 06:36:53 +0000421 ARMCC::CondCodes getCondCode() const {
422 assert(Kind == CondCode && "Invalid access!");
423 return CC.Val;
424 }
425
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000426 unsigned getCoproc() const {
427 assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!");
428 return Cop.Val;
429 }
430
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000431 StringRef getToken() const {
432 assert(Kind == Token && "Invalid access!");
433 return StringRef(Tok.Data, Tok.Length);
434 }
435
436 unsigned getReg() const {
Benjamin Kramer6aa49432010-12-07 15:50:35 +0000437 assert((Kind == Register || Kind == CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000438 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000439 }
440
Bill Wendling5fa22a12010-11-09 23:28:44 +0000441 const SmallVectorImpl<unsigned> &getRegList() const {
Bill Wendling0f630752010-11-17 04:32:08 +0000442 assert((Kind == RegisterList || Kind == DPRRegisterList ||
443 Kind == SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000444 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000445 }
446
Kevin Enderbycfe07242009-10-13 22:19:02 +0000447 const MCExpr *getImm() const {
448 assert(Kind == Immediate && "Invalid access!");
449 return Imm.Val;
450 }
451
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000452 ARM_MB::MemBOpt getMemBarrierOpt() const {
453 assert(Kind == MemBarrierOpt && "Invalid access!");
454 return MBOpt.Val;
455 }
456
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 ARM_PROC::IFlags getProcIFlags() const {
458 assert(Kind == ProcIFlags && "Invalid access!");
459 return IFlags.Val;
460 }
461
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000462 unsigned getMSRMask() const {
463 assert(Kind == MSRMask && "Invalid access!");
464 return MMask.Val;
465 }
466
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000467 bool isCoprocNum() const { return Kind == CoprocNum; }
468 bool isCoprocReg() const { return Kind == CoprocReg; }
Daniel Dunbar8462b302010-08-11 06:36:53 +0000469 bool isCondCode() const { return Kind == CondCode; }
Jim Grosbachd67641b2010-12-06 18:21:12 +0000470 bool isCCOut() const { return Kind == CCOut; }
Jim Grosbach89df9962011-08-26 21:43:41 +0000471 bool isITMask() const { return Kind == ITCondMask; }
472 bool isITCondCode() const { return Kind == CondCode; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000473 bool isImm() const { return Kind == Immediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000474 bool isImm8s4() const {
475 if (Kind != Immediate)
476 return false;
477 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
478 if (!CE) return false;
479 int64_t Value = CE->getValue();
480 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
481 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000482 bool isImm0_1020s4() const {
483 if (Kind != Immediate)
484 return false;
485 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
486 if (!CE) return false;
487 int64_t Value = CE->getValue();
488 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
489 }
490 bool isImm0_508s4() const {
491 if (Kind != Immediate)
492 return false;
493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
494 if (!CE) return false;
495 int64_t Value = CE->getValue();
496 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
497 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000498 bool isImm0_255() const {
499 if (Kind != Immediate)
500 return false;
501 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
502 if (!CE) return false;
503 int64_t Value = CE->getValue();
504 return Value >= 0 && Value < 256;
505 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000506 bool isImm0_7() const {
507 if (Kind != Immediate)
508 return false;
509 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
510 if (!CE) return false;
511 int64_t Value = CE->getValue();
512 return Value >= 0 && Value < 8;
513 }
514 bool isImm0_15() const {
515 if (Kind != Immediate)
516 return false;
517 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
518 if (!CE) return false;
519 int64_t Value = CE->getValue();
520 return Value >= 0 && Value < 16;
521 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000522 bool isImm0_31() const {
523 if (Kind != Immediate)
524 return false;
525 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
526 if (!CE) return false;
527 int64_t Value = CE->getValue();
528 return Value >= 0 && Value < 32;
529 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000530 bool isImm1_16() const {
531 if (Kind != Immediate)
532 return false;
533 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
534 if (!CE) return false;
535 int64_t Value = CE->getValue();
536 return Value > 0 && Value < 17;
537 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000538 bool isImm1_32() const {
539 if (Kind != Immediate)
540 return false;
541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
542 if (!CE) return false;
543 int64_t Value = CE->getValue();
544 return Value > 0 && Value < 33;
545 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000546 bool isImm0_65535() const {
547 if (Kind != Immediate)
548 return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return Value >= 0 && Value < 65536;
553 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000554 bool isImm0_65535Expr() const {
555 if (Kind != Immediate)
556 return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 // If it's not a constant expression, it'll generate a fixup and be
559 // handled later.
560 if (!CE) return true;
561 int64_t Value = CE->getValue();
562 return Value >= 0 && Value < 65536;
563 }
Jim Grosbached838482011-07-26 16:24:27 +0000564 bool isImm24bit() const {
565 if (Kind != Immediate)
566 return false;
567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
568 if (!CE) return false;
569 int64_t Value = CE->getValue();
570 return Value >= 0 && Value <= 0xffffff;
571 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000572 bool isImmThumbSR() const {
573 if (Kind != Immediate)
574 return false;
575 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
576 if (!CE) return false;
577 int64_t Value = CE->getValue();
578 return Value > 0 && Value < 33;
579 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000580 bool isPKHLSLImm() const {
581 if (Kind != Immediate)
582 return false;
583 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
584 if (!CE) return false;
585 int64_t Value = CE->getValue();
586 return Value >= 0 && Value < 32;
587 }
588 bool isPKHASRImm() const {
589 if (Kind != Immediate)
590 return false;
591 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
592 if (!CE) return false;
593 int64_t Value = CE->getValue();
594 return Value > 0 && Value <= 32;
595 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000596 bool isARMSOImm() const {
597 if (Kind != Immediate)
598 return false;
599 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
600 if (!CE) return false;
601 int64_t Value = CE->getValue();
602 return ARM_AM::getSOImmVal(Value) != -1;
603 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000604 bool isT2SOImm() const {
605 if (Kind != Immediate)
606 return false;
607 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
608 if (!CE) return false;
609 int64_t Value = CE->getValue();
610 return ARM_AM::getT2SOImmVal(Value) != -1;
611 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000612 bool isSetEndImm() const {
613 if (Kind != Immediate)
614 return false;
615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616 if (!CE) return false;
617 int64_t Value = CE->getValue();
618 return Value == 1 || Value == 0;
619 }
Bill Wendlingb32e7842010-11-08 00:32:40 +0000620 bool isReg() const { return Kind == Register; }
Bill Wendling8d5acb72010-11-06 19:56:04 +0000621 bool isRegList() const { return Kind == RegisterList; }
Bill Wendling0f630752010-11-17 04:32:08 +0000622 bool isDPRRegList() const { return Kind == DPRRegisterList; }
623 bool isSPRRegList() const { return Kind == SPRRegisterList; }
Chris Lattner14b93852010-10-29 00:27:31 +0000624 bool isToken() const { return Kind == Token; }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000625 bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
Chris Lattner14b93852010-10-29 00:27:31 +0000626 bool isMemory() const { return Kind == Memory; }
Jim Grosbach580f4a92011-07-25 22:20:28 +0000627 bool isShifterImm() const { return Kind == ShifterImmediate; }
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000628 bool isRegShiftedReg() const { return Kind == ShiftedRegister; }
629 bool isRegShiftedImm() const { return Kind == ShiftedImmediate; }
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000630 bool isRotImm() const { return Kind == RotateImmediate; }
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000631 bool isBitfield() const { return Kind == BitfieldDescriptor; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000632 bool isPostIdxRegShifted() const { return Kind == PostIndexRegister; }
633 bool isPostIdxReg() const {
634 return Kind == PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
635 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000636 bool isMemNoOffset() const {
637 if (Kind != Memory)
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000638 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000639 // No offset of any kind.
640 return Mem.OffsetRegNum == 0 && Mem.OffsetImm == 0;
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000641 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000642 bool isAddrMode2() const {
643 if (Kind != Memory)
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000644 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000645 // Check for register offset.
646 if (Mem.OffsetRegNum) return true;
647 // Immediate offset in range [-4095, 4095].
648 if (!Mem.OffsetImm) return true;
649 int64_t Val = Mem.OffsetImm->getValue();
650 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000651 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000652 bool isAM2OffsetImm() const {
653 if (Kind != Immediate)
654 return false;
655 // Immediate offset in range [-4095, 4095].
656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
657 if (!CE) return false;
658 int64_t Val = CE->getValue();
659 return Val > -4096 && Val < 4096;
660 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000661 bool isAddrMode3() const {
662 if (Kind != Memory)
663 return false;
664 // No shifts are legal for AM3.
665 if (Mem.ShiftType != ARM_AM::no_shift) return false;
666 // Check for register offset.
667 if (Mem.OffsetRegNum) return true;
668 // Immediate offset in range [-255, 255].
669 if (!Mem.OffsetImm) return true;
670 int64_t Val = Mem.OffsetImm->getValue();
671 return Val > -256 && Val < 256;
672 }
673 bool isAM3Offset() const {
674 if (Kind != Immediate && Kind != PostIndexRegister)
675 return false;
676 if (Kind == PostIndexRegister)
677 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
678 // Immediate offset in range [-255, 255].
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000682 // Special case, #-0 is INT32_MIN.
683 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000684 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000685 bool isAddrMode5() const {
686 if (Kind != Memory)
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000687 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000688 // Check for register offset.
689 if (Mem.OffsetRegNum) return false;
690 // Immediate offset in range [-1020, 1020] and a multiple of 4.
691 if (!Mem.OffsetImm) return true;
692 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000693 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
694 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000695 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000696 bool isMemTBB() const {
697 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
698 Mem.ShiftType != ARM_AM::no_shift)
699 return false;
700 return true;
701 }
702 bool isMemTBH() const {
703 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
704 Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm != 1)
705 return false;
706 return true;
707 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000708 bool isMemRegOffset() const {
709 if (Kind != Memory || !Mem.OffsetRegNum)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000710 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000711 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000712 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000713 bool isT2MemRegOffset() const {
714 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative)
715 return false;
716 // Only lsl #{0, 1, 2, 3} allowed.
717 if (Mem.ShiftType == ARM_AM::no_shift)
718 return true;
719 if (Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm > 3)
720 return false;
721 return true;
722 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000723 bool isMemThumbRR() const {
724 // Thumb reg+reg addressing is simple. Just two registers, a base and
725 // an offset. No shifts, negations or any other complicating factors.
726 if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative ||
727 Mem.ShiftType != ARM_AM::no_shift)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000728 return false;
Jim Grosbach60f91a32011-08-19 17:55:24 +0000729 return isARMLowRegister(Mem.BaseRegNum) &&
730 (!Mem.OffsetRegNum || isARMLowRegister(Mem.OffsetRegNum));
731 }
732 bool isMemThumbRIs4() const {
733 if (Kind != Memory || Mem.OffsetRegNum != 0 ||
734 !isARMLowRegister(Mem.BaseRegNum))
735 return false;
736 // Immediate offset, multiple of 4 in range [0, 124].
737 if (!Mem.OffsetImm) return true;
738 int64_t Val = Mem.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000739 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
740 }
Jim Grosbach38466302011-08-19 18:55:51 +0000741 bool isMemThumbRIs2() const {
742 if (Kind != Memory || Mem.OffsetRegNum != 0 ||
743 !isARMLowRegister(Mem.BaseRegNum))
744 return false;
745 // Immediate offset, multiple of 4 in range [0, 62].
746 if (!Mem.OffsetImm) return true;
747 int64_t Val = Mem.OffsetImm->getValue();
748 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
749 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000750 bool isMemThumbRIs1() const {
751 if (Kind != Memory || Mem.OffsetRegNum != 0 ||
752 !isARMLowRegister(Mem.BaseRegNum))
753 return false;
754 // Immediate offset in range [0, 31].
755 if (!Mem.OffsetImm) return true;
756 int64_t Val = Mem.OffsetImm->getValue();
757 return Val >= 0 && Val <= 31;
758 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000759 bool isMemThumbSPI() const {
760 if (Kind != Memory || Mem.OffsetRegNum != 0 || Mem.BaseRegNum != ARM::SP)
761 return false;
762 // Immediate offset, multiple of 4 in range [0, 1020].
763 if (!Mem.OffsetImm) return true;
764 int64_t Val = Mem.OffsetImm->getValue();
765 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000766 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000767 bool isMemImm8s4Offset() const {
768 if (Kind != Memory || Mem.OffsetRegNum != 0)
769 return false;
770 // Immediate offset a multiple of 4 in range [-1020, 1020].
771 if (!Mem.OffsetImm) return true;
772 int64_t Val = Mem.OffsetImm->getValue();
773 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
774 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000775 bool isMemImm0_1020s4Offset() const {
776 if (Kind != Memory || Mem.OffsetRegNum != 0)
777 return false;
778 // Immediate offset a multiple of 4 in range [0, 1020].
779 if (!Mem.OffsetImm) return true;
780 int64_t Val = Mem.OffsetImm->getValue();
781 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
782 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000783 bool isMemImm8Offset() const {
784 if (Kind != Memory || Mem.OffsetRegNum != 0)
785 return false;
786 // Immediate offset in range [-255, 255].
787 if (!Mem.OffsetImm) return true;
788 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000789 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000790 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000791 bool isMemPosImm8Offset() const {
792 if (Kind != Memory || Mem.OffsetRegNum != 0)
793 return false;
794 // Immediate offset in range [0, 255].
795 if (!Mem.OffsetImm) return true;
796 int64_t Val = Mem.OffsetImm->getValue();
797 return Val >= 0 && Val < 256;
798 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000799 bool isMemNegImm8Offset() const {
800 if (Kind != Memory || Mem.OffsetRegNum != 0)
801 return false;
802 // Immediate offset in range [-255, -1].
803 if (!Mem.OffsetImm) return true;
804 int64_t Val = Mem.OffsetImm->getValue();
805 return Val > -256 && Val < 0;
806 }
807 bool isMemUImm12Offset() const {
808 // If we have an immediate that's not a constant, treat it as a label
809 // reference needing a fixup. If it is a constant, it's something else
810 // and we reject it.
811 if (Kind == Immediate && !isa<MCConstantExpr>(getImm()))
812 return true;
813
814 if (Kind != Memory || Mem.OffsetRegNum != 0)
815 return false;
816 // Immediate offset in range [0, 4095].
817 if (!Mem.OffsetImm) return true;
818 int64_t Val = Mem.OffsetImm->getValue();
819 return (Val >= 0 && Val < 4096);
820 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000821 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000822 // If we have an immediate that's not a constant, treat it as a label
823 // reference needing a fixup. If it is a constant, it's something else
824 // and we reject it.
825 if (Kind == Immediate && !isa<MCConstantExpr>(getImm()))
826 return true;
827
Jim Grosbach7ce05792011-08-03 23:50:40 +0000828 if (Kind != Memory || Mem.OffsetRegNum != 0)
829 return false;
830 // Immediate offset in range [-4095, 4095].
831 if (!Mem.OffsetImm) return true;
832 int64_t Val = Mem.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000833 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000834 }
835 bool isPostIdxImm8() const {
836 if (Kind != Immediate)
837 return false;
838 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
839 if (!CE) return false;
840 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000841 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000842 }
843
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000844 bool isMSRMask() const { return Kind == MSRMask; }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000845 bool isProcIFlags() const { return Kind == ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000846
847 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +0000848 // Add as immediates when possible. Null MCExpr = 0.
849 if (Expr == 0)
850 Inst.addOperand(MCOperand::CreateImm(0));
851 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000852 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
853 else
854 Inst.addOperand(MCOperand::CreateExpr(Expr));
855 }
856
Daniel Dunbar8462b302010-08-11 06:36:53 +0000857 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +0000858 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000859 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +0000860 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
861 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +0000862 }
863
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000864 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
865 assert(N == 1 && "Invalid number of operands!");
866 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
867 }
868
Jim Grosbach89df9962011-08-26 21:43:41 +0000869 void addITMaskOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 1 && "Invalid number of operands!");
871 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
872 }
873
874 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
876 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
877 }
878
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000879 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
881 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
882 }
883
Jim Grosbachd67641b2010-12-06 18:21:12 +0000884 void addCCOutOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
886 Inst.addOperand(MCOperand::CreateReg(getReg()));
887 }
888
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000889 void addRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
891 Inst.addOperand(MCOperand::CreateReg(getReg()));
892 }
893
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000894 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +0000895 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000896 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
897 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
898 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000899 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000900 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +0000901 }
902
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000903 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +0000904 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000905 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
906 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +0000907 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000908 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +0000909 }
910
Jim Grosbach580f4a92011-07-25 22:20:28 +0000911 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +0000912 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +0000913 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
914 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +0000915 }
916
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000917 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +0000918 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +0000919 const SmallVectorImpl<unsigned> &RegList = getRegList();
920 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +0000921 I = RegList.begin(), E = RegList.end(); I != E; ++I)
922 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000923 }
924
Bill Wendling0f630752010-11-17 04:32:08 +0000925 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
926 addRegListOperands(Inst, N);
927 }
928
929 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
930 addRegListOperands(Inst, N);
931 }
932
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000933 void addRotImmOperands(MCInst &Inst, unsigned N) const {
934 assert(N == 1 && "Invalid number of operands!");
935 // Encoded as val>>3. The printer handles display as 8, 16, 24.
936 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
937 }
938
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000939 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
940 assert(N == 1 && "Invalid number of operands!");
941 // Munge the lsb/width into a bitfield mask.
942 unsigned lsb = Bitfield.LSB;
943 unsigned width = Bitfield.Width;
944 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
945 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
946 (32 - (lsb + width)));
947 Inst.addOperand(MCOperand::CreateImm(Mask));
948 }
949
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000950 void addImmOperands(MCInst &Inst, unsigned N) const {
951 assert(N == 1 && "Invalid number of operands!");
952 addExpr(Inst, getImm());
953 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000954
Jim Grosbacha77295d2011-09-08 22:07:06 +0000955 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
956 assert(N == 1 && "Invalid number of operands!");
957 // FIXME: We really want to scale the value here, but the LDRD/STRD
958 // instruction don't encode operands that way yet.
959 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
960 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
961 }
962
Jim Grosbach72f39f82011-08-24 21:22:15 +0000963 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
964 assert(N == 1 && "Invalid number of operands!");
965 // The immediate is scaled by four in the encoding and is stored
966 // in the MCInst as such. Lop off the low two bits here.
967 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
968 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
969 }
970
971 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
972 assert(N == 1 && "Invalid number of operands!");
973 // The immediate is scaled by four in the encoding and is stored
974 // in the MCInst as such. Lop off the low two bits here.
975 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
976 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
977 }
978
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000979 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
980 assert(N == 1 && "Invalid number of operands!");
981 addExpr(Inst, getImm());
982 }
983
Jim Grosbach83ab0702011-07-13 22:01:08 +0000984 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
985 assert(N == 1 && "Invalid number of operands!");
986 addExpr(Inst, getImm());
987 }
988
989 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
990 assert(N == 1 && "Invalid number of operands!");
991 addExpr(Inst, getImm());
992 }
993
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000994 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
995 assert(N == 1 && "Invalid number of operands!");
996 addExpr(Inst, getImm());
997 }
998
Jim Grosbachf4943352011-07-25 23:09:14 +0000999 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1000 assert(N == 1 && "Invalid number of operands!");
1001 // The constant encodes as the immediate-1, and we store in the instruction
1002 // the bits as encoded, so subtract off one here.
1003 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1004 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1005 }
1006
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001007 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1008 assert(N == 1 && "Invalid number of operands!");
1009 // The constant encodes as the immediate-1, and we store in the instruction
1010 // the bits as encoded, so subtract off one here.
1011 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1012 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1013 }
1014
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001015 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1016 assert(N == 1 && "Invalid number of operands!");
1017 addExpr(Inst, getImm());
1018 }
1019
Jim Grosbachffa32252011-07-19 19:13:28 +00001020 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1021 assert(N == 1 && "Invalid number of operands!");
1022 addExpr(Inst, getImm());
1023 }
1024
Jim Grosbached838482011-07-26 16:24:27 +00001025 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1026 assert(N == 1 && "Invalid number of operands!");
1027 addExpr(Inst, getImm());
1028 }
1029
Jim Grosbach70939ee2011-08-17 21:51:27 +00001030 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1031 assert(N == 1 && "Invalid number of operands!");
1032 // The constant encodes as the immediate, except for 32, which encodes as
1033 // zero.
1034 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1035 unsigned Imm = CE->getValue();
1036 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1037 }
1038
Jim Grosbachf6c05252011-07-21 17:23:04 +00001039 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1040 assert(N == 1 && "Invalid number of operands!");
1041 addExpr(Inst, getImm());
1042 }
1043
1044 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1045 assert(N == 1 && "Invalid number of operands!");
1046 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1047 // the instruction as well.
1048 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1049 int Val = CE->getValue();
1050 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1051 }
1052
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001053 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1054 assert(N == 1 && "Invalid number of operands!");
1055 addExpr(Inst, getImm());
1056 }
1057
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001058 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1059 assert(N == 1 && "Invalid number of operands!");
1060 addExpr(Inst, getImm());
1061 }
1062
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001063 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1064 assert(N == 1 && "Invalid number of operands!");
1065 addExpr(Inst, getImm());
1066 }
1067
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001068 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1069 assert(N == 1 && "Invalid number of operands!");
1070 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1071 }
1072
Jim Grosbach7ce05792011-08-03 23:50:40 +00001073 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1074 assert(N == 1 && "Invalid number of operands!");
1075 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001076 }
1077
Jim Grosbach7ce05792011-08-03 23:50:40 +00001078 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1079 assert(N == 3 && "Invalid number of operands!");
1080 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1081 if (!Mem.OffsetRegNum) {
1082 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1083 // Special case for #-0
1084 if (Val == INT32_MIN) Val = 0;
1085 if (Val < 0) Val = -Val;
1086 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1087 } else {
1088 // For register offset, we encode the shift type and negation flag
1089 // here.
1090 Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
Jim Grosbachdd32ba32011-08-11 22:05:09 +00001091 Mem.ShiftImm, Mem.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001092 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001093 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1094 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1095 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001096 }
1097
Jim Grosbach039c2e12011-08-04 23:01:30 +00001098 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1099 assert(N == 2 && "Invalid number of operands!");
1100 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1101 assert(CE && "non-constant AM2OffsetImm operand!");
1102 int32_t Val = CE->getValue();
1103 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1104 // Special case for #-0
1105 if (Val == INT32_MIN) Val = 0;
1106 if (Val < 0) Val = -Val;
1107 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1108 Inst.addOperand(MCOperand::CreateReg(0));
1109 Inst.addOperand(MCOperand::CreateImm(Val));
1110 }
1111
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001112 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1113 assert(N == 3 && "Invalid number of operands!");
1114 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1115 if (!Mem.OffsetRegNum) {
1116 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1117 // Special case for #-0
1118 if (Val == INT32_MIN) Val = 0;
1119 if (Val < 0) Val = -Val;
1120 Val = ARM_AM::getAM3Opc(AddSub, Val);
1121 } else {
1122 // For register offset, we encode the shift type and negation flag
1123 // here.
1124 Val = ARM_AM::getAM3Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
1125 }
1126 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1127 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1128 Inst.addOperand(MCOperand::CreateImm(Val));
1129 }
1130
1131 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1132 assert(N == 2 && "Invalid number of operands!");
1133 if (Kind == PostIndexRegister) {
1134 int32_t Val =
1135 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1136 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1137 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001138 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001139 }
1140
1141 // Constant offset.
1142 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1143 int32_t Val = CE->getValue();
1144 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1145 // Special case for #-0
1146 if (Val == INT32_MIN) Val = 0;
1147 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001148 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001149 Inst.addOperand(MCOperand::CreateReg(0));
1150 Inst.addOperand(MCOperand::CreateImm(Val));
1151 }
1152
Jim Grosbach7ce05792011-08-03 23:50:40 +00001153 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1154 assert(N == 2 && "Invalid number of operands!");
1155 // The lower two bits are always zero and as such are not encoded.
1156 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0;
1157 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1158 // Special case for #-0
1159 if (Val == INT32_MIN) Val = 0;
1160 if (Val < 0) Val = -Val;
1161 Val = ARM_AM::getAM5Opc(AddSub, Val);
1162 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1163 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001164 }
1165
Jim Grosbacha77295d2011-09-08 22:07:06 +00001166 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1167 assert(N == 2 && "Invalid number of operands!");
1168 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1169 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1170 Inst.addOperand(MCOperand::CreateImm(Val));
1171 }
1172
Jim Grosbachb6aed502011-09-09 18:37:27 +00001173 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1174 assert(N == 2 && "Invalid number of operands!");
1175 // The lower two bits are always zero and as such are not encoded.
1176 int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() / 4 : 0;
1177 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1178 Inst.addOperand(MCOperand::CreateImm(Val));
1179 }
1180
Jim Grosbach7ce05792011-08-03 23:50:40 +00001181 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1182 assert(N == 2 && "Invalid number of operands!");
1183 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1184 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1185 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001186 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001187
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001188 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1189 addMemImm8OffsetOperands(Inst, N);
1190 }
1191
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001192 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001193 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001194 }
1195
1196 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 2 && "Invalid number of operands!");
1198 // If this is an immediate, it's a label reference.
1199 if (Kind == Immediate) {
1200 addExpr(Inst, getImm());
1201 Inst.addOperand(MCOperand::CreateImm(0));
1202 return;
1203 }
1204
1205 // Otherwise, it's a normal memory reg+offset.
1206 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1207 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1208 Inst.addOperand(MCOperand::CreateImm(Val));
1209 }
1210
Jim Grosbach7ce05792011-08-03 23:50:40 +00001211 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1212 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001213 // If this is an immediate, it's a label reference.
1214 if (Kind == Immediate) {
1215 addExpr(Inst, getImm());
1216 Inst.addOperand(MCOperand::CreateImm(0));
1217 return;
1218 }
1219
1220 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach7ce05792011-08-03 23:50:40 +00001221 int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
1222 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1223 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001224 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001225
Jim Grosbach7f739be2011-09-19 22:21:13 +00001226 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 2 && "Invalid number of operands!");
1228 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1229 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1230 }
1231
1232 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1233 assert(N == 2 && "Invalid number of operands!");
1234 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1235 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1236 }
1237
Jim Grosbach7ce05792011-08-03 23:50:40 +00001238 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 3 && "Invalid number of operands!");
1240 unsigned Val = ARM_AM::getAM2Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001241 Mem.ShiftImm, Mem.ShiftType);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001242 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1243 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1244 Inst.addOperand(MCOperand::CreateImm(Val));
1245 }
1246
Jim Grosbachab899c12011-09-07 23:10:15 +00001247 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 3 && "Invalid number of operands!");
1249 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1250 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1251 Inst.addOperand(MCOperand::CreateImm(Mem.ShiftImm));
1252 }
1253
Jim Grosbach7ce05792011-08-03 23:50:40 +00001254 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 2 && "Invalid number of operands!");
1256 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1257 Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
1258 }
1259
Jim Grosbach60f91a32011-08-19 17:55:24 +00001260 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 2 && "Invalid number of operands!");
1262 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0;
1263 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1264 Inst.addOperand(MCOperand::CreateImm(Val));
1265 }
1266
Jim Grosbach38466302011-08-19 18:55:51 +00001267 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 2 && "Invalid number of operands!");
1269 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 2) : 0;
1270 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1271 Inst.addOperand(MCOperand::CreateImm(Val));
1272 }
1273
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001274 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1275 assert(N == 2 && "Invalid number of operands!");
1276 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue()) : 0;
1277 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1278 Inst.addOperand(MCOperand::CreateImm(Val));
1279 }
1280
Jim Grosbachecd85892011-08-19 18:13:48 +00001281 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1282 assert(N == 2 && "Invalid number of operands!");
1283 int64_t Val = Mem.OffsetImm ? (Mem.OffsetImm->getValue() / 4) : 0;
1284 Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
1285 Inst.addOperand(MCOperand::CreateImm(Val));
1286 }
1287
Jim Grosbach7ce05792011-08-03 23:50:40 +00001288 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1289 assert(N == 1 && "Invalid number of operands!");
1290 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1291 assert(CE && "non-constant post-idx-imm8 operand!");
1292 int Imm = CE->getValue();
1293 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001294 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001295 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1296 Inst.addOperand(MCOperand::CreateImm(Imm));
1297 }
1298
1299 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1300 assert(N == 2 && "Invalid number of operands!");
1301 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001302 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1303 }
1304
1305 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1306 assert(N == 2 && "Invalid number of operands!");
1307 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1308 // The sign, shift type, and shift amount are encoded in a single operand
1309 // using the AM2 encoding helpers.
1310 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1311 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1312 PostIdxReg.ShiftTy);
1313 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001314 }
1315
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001316 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
1318 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1319 }
1320
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001321 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1322 assert(N == 1 && "Invalid number of operands!");
1323 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1324 }
1325
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001326 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001327
Jim Grosbach89df9962011-08-26 21:43:41 +00001328 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
1329 ARMOperand *Op = new ARMOperand(ITCondMask);
1330 Op->ITMask.Mask = Mask;
1331 Op->StartLoc = S;
1332 Op->EndLoc = S;
1333 return Op;
1334 }
1335
Chris Lattner3a697562010-10-28 17:20:03 +00001336 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
1337 ARMOperand *Op = new ARMOperand(CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001338 Op->CC.Val = CC;
1339 Op->StartLoc = S;
1340 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001341 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001342 }
1343
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001344 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
1345 ARMOperand *Op = new ARMOperand(CoprocNum);
1346 Op->Cop.Val = CopVal;
1347 Op->StartLoc = S;
1348 Op->EndLoc = S;
1349 return Op;
1350 }
1351
1352 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
1353 ARMOperand *Op = new ARMOperand(CoprocReg);
1354 Op->Cop.Val = CopVal;
1355 Op->StartLoc = S;
1356 Op->EndLoc = S;
1357 return Op;
1358 }
1359
Jim Grosbachd67641b2010-12-06 18:21:12 +00001360 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
1361 ARMOperand *Op = new ARMOperand(CCOut);
1362 Op->Reg.RegNum = RegNum;
1363 Op->StartLoc = S;
1364 Op->EndLoc = S;
1365 return Op;
1366 }
1367
Chris Lattner3a697562010-10-28 17:20:03 +00001368 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
1369 ARMOperand *Op = new ARMOperand(Token);
Sean Callanan76264762010-04-02 22:27:05 +00001370 Op->Tok.Data = Str.data();
1371 Op->Tok.Length = Str.size();
1372 Op->StartLoc = S;
1373 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001374 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001375 }
1376
Bill Wendling50d0f582010-11-18 23:43:05 +00001377 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Chris Lattner3a697562010-10-28 17:20:03 +00001378 ARMOperand *Op = new ARMOperand(Register);
Sean Callanan76264762010-04-02 22:27:05 +00001379 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001380 Op->StartLoc = S;
1381 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001382 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001383 }
1384
Jim Grosbache8606dc2011-07-13 17:50:29 +00001385 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1386 unsigned SrcReg,
1387 unsigned ShiftReg,
1388 unsigned ShiftImm,
1389 SMLoc S, SMLoc E) {
1390 ARMOperand *Op = new ARMOperand(ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001391 Op->RegShiftedReg.ShiftTy = ShTy;
1392 Op->RegShiftedReg.SrcReg = SrcReg;
1393 Op->RegShiftedReg.ShiftReg = ShiftReg;
1394 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001395 Op->StartLoc = S;
1396 Op->EndLoc = E;
1397 return Op;
1398 }
1399
Owen Anderson92a20222011-07-21 18:54:16 +00001400 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1401 unsigned SrcReg,
1402 unsigned ShiftImm,
1403 SMLoc S, SMLoc E) {
1404 ARMOperand *Op = new ARMOperand(ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001405 Op->RegShiftedImm.ShiftTy = ShTy;
1406 Op->RegShiftedImm.SrcReg = SrcReg;
1407 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001408 Op->StartLoc = S;
1409 Op->EndLoc = E;
1410 return Op;
1411 }
1412
Jim Grosbach580f4a92011-07-25 22:20:28 +00001413 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001414 SMLoc S, SMLoc E) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00001415 ARMOperand *Op = new ARMOperand(ShifterImmediate);
1416 Op->ShifterImm.isASR = isASR;
1417 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001418 Op->StartLoc = S;
1419 Op->EndLoc = E;
1420 return Op;
1421 }
1422
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001423 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
1424 ARMOperand *Op = new ARMOperand(RotateImmediate);
1425 Op->RotImm.Imm = Imm;
1426 Op->StartLoc = S;
1427 Op->EndLoc = E;
1428 return Op;
1429 }
1430
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001431 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1432 SMLoc S, SMLoc E) {
1433 ARMOperand *Op = new ARMOperand(BitfieldDescriptor);
1434 Op->Bitfield.LSB = LSB;
1435 Op->Bitfield.Width = Width;
1436 Op->StartLoc = S;
1437 Op->EndLoc = E;
1438 return Op;
1439 }
1440
Bill Wendling7729e062010-11-09 22:44:22 +00001441 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001442 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001443 SMLoc StartLoc, SMLoc EndLoc) {
Bill Wendling0f630752010-11-17 04:32:08 +00001444 KindTy Kind = RegisterList;
1445
Jim Grosbachd300b942011-09-13 22:56:44 +00001446 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Bill Wendling0f630752010-11-17 04:32:08 +00001447 Kind = DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001448 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001449 contains(Regs.front().first))
Bill Wendling0f630752010-11-17 04:32:08 +00001450 Kind = SPRRegisterList;
1451
1452 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001453 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001454 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001455 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001456 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001457 Op->StartLoc = StartLoc;
1458 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001459 return Op;
1460 }
1461
Chris Lattner3a697562010-10-28 17:20:03 +00001462 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
1463 ARMOperand *Op = new ARMOperand(Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001464 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001465 Op->StartLoc = S;
1466 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001467 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001468 }
1469
Jim Grosbach7ce05792011-08-03 23:50:40 +00001470 static ARMOperand *CreateMem(unsigned BaseRegNum,
1471 const MCConstantExpr *OffsetImm,
1472 unsigned OffsetRegNum,
1473 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001474 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001475 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001476 SMLoc S, SMLoc E) {
1477 ARMOperand *Op = new ARMOperand(Memory);
Sean Callanan76264762010-04-02 22:27:05 +00001478 Op->Mem.BaseRegNum = BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001479 Op->Mem.OffsetImm = OffsetImm;
1480 Op->Mem.OffsetRegNum = OffsetRegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001481 Op->Mem.ShiftType = ShiftType;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001482 Op->Mem.ShiftImm = ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001483 Op->Mem.isNegative = isNegative;
1484 Op->StartLoc = S;
1485 Op->EndLoc = E;
1486 return Op;
1487 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001488
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001489 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1490 ARM_AM::ShiftOpc ShiftTy,
1491 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001492 SMLoc S, SMLoc E) {
1493 ARMOperand *Op = new ARMOperand(PostIndexRegister);
1494 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001495 Op->PostIdxReg.isAdd = isAdd;
1496 Op->PostIdxReg.ShiftTy = ShiftTy;
1497 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001498 Op->StartLoc = S;
1499 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001500 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001501 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001502
1503 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
1504 ARMOperand *Op = new ARMOperand(MemBarrierOpt);
1505 Op->MBOpt.Val = Opt;
1506 Op->StartLoc = S;
1507 Op->EndLoc = S;
1508 return Op;
1509 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001510
1511 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
1512 ARMOperand *Op = new ARMOperand(ProcIFlags);
1513 Op->IFlags.Val = IFlags;
1514 Op->StartLoc = S;
1515 Op->EndLoc = S;
1516 return Op;
1517 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001518
1519 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
1520 ARMOperand *Op = new ARMOperand(MSRMask);
1521 Op->MMask.Val = MMask;
1522 Op->StartLoc = S;
1523 Op->EndLoc = S;
1524 return Op;
1525 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001526};
1527
1528} // end anonymous namespace.
1529
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001530void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001531 switch (Kind) {
1532 case CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001533 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001534 break;
Jim Grosbachd67641b2010-12-06 18:21:12 +00001535 case CCOut:
1536 OS << "<ccout " << getReg() << ">";
1537 break;
Jim Grosbach89df9962011-08-26 21:43:41 +00001538 case ITCondMask: {
1539 static char MaskStr[][6] = { "()", "(t)", "(e)", "(tt)", "(et)", "(te)",
1540 "(ee)", "(ttt)", "(ett)", "(tet)", "(eet)", "(tte)", "(ete)",
1541 "(tee)", "(eee)" };
1542 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1543 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1544 break;
1545 }
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001546 case CoprocNum:
1547 OS << "<coprocessor number: " << getCoproc() << ">";
1548 break;
1549 case CoprocReg:
1550 OS << "<coprocessor register: " << getCoproc() << ">";
1551 break;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001552 case MSRMask:
1553 OS << "<mask: " << getMSRMask() << ">";
1554 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001555 case Immediate:
1556 getImm()->print(OS);
1557 break;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001558 case MemBarrierOpt:
1559 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1560 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001561 case Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001562 OS << "<memory "
Jim Grosbach7ce05792011-08-03 23:50:40 +00001563 << " base:" << Mem.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001564 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001565 break;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001566 case PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001567 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1568 << PostIdxReg.RegNum;
1569 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1570 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1571 << PostIdxReg.ShiftImm;
1572 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001573 break;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001574 case ProcIFlags: {
1575 OS << "<ARM_PROC::";
1576 unsigned IFlags = getProcIFlags();
1577 for (int i=2; i >= 0; --i)
1578 if (IFlags & (1 << i))
1579 OS << ARM_PROC::IFlagsToString(1 << i);
1580 OS << ">";
1581 break;
1582 }
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001583 case Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001584 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001585 break;
Jim Grosbach580f4a92011-07-25 22:20:28 +00001586 case ShifterImmediate:
1587 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1588 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001589 break;
1590 case ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001591 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001592 << RegShiftedReg.SrcReg
1593 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1594 << ", " << RegShiftedReg.ShiftReg << ", "
1595 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001596 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001597 break;
Owen Anderson92a20222011-07-21 18:54:16 +00001598 case ShiftedImmediate:
1599 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001600 << RegShiftedImm.SrcReg
1601 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
1602 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00001603 << ">";
1604 break;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001605 case RotateImmediate:
1606 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1607 break;
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001608 case BitfieldDescriptor:
1609 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1610 << ", width: " << Bitfield.Width << ">";
1611 break;
Bill Wendling0f630752010-11-17 04:32:08 +00001612 case RegisterList:
1613 case DPRRegisterList:
1614 case SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001615 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001616
Bill Wendling5fa22a12010-11-09 23:28:44 +00001617 const SmallVectorImpl<unsigned> &RegList = getRegList();
1618 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001619 I = RegList.begin(), E = RegList.end(); I != E; ) {
1620 OS << *I;
1621 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001622 }
1623
1624 OS << ">";
1625 break;
1626 }
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001627 case Token:
1628 OS << "'" << getToken() << "'";
1629 break;
1630 }
1631}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001632
1633/// @name Auto-generated Match Functions
1634/// {
1635
1636static unsigned MatchRegisterName(StringRef Name);
1637
1638/// }
1639
Bob Wilson69df7232011-02-03 21:46:10 +00001640bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1641 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001642 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001643
1644 return (RegNo == (unsigned)-1);
1645}
1646
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001647/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001648/// and if it is a register name the token is eaten and the register number is
1649/// returned. Otherwise return -1.
1650///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001651int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001652 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001653 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001654
Chris Lattnere5658fa2010-10-30 04:09:10 +00001655 // FIXME: Validate register for the current architecture; we have to do
1656 // validation later, so maybe there is no need for this here.
Owen Anderson0c9f2502011-01-13 22:50:36 +00001657 std::string upperCase = Tok.getString().str();
1658 std::string lowerCase = LowercaseString(upperCase);
1659 unsigned RegNum = MatchRegisterName(lowerCase);
1660 if (!RegNum) {
1661 RegNum = StringSwitch<unsigned>(lowerCase)
1662 .Case("r13", ARM::SP)
1663 .Case("r14", ARM::LR)
1664 .Case("r15", ARM::PC)
1665 .Case("ip", ARM::R12)
1666 .Default(0);
1667 }
1668 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00001669
Chris Lattnere5658fa2010-10-30 04:09:10 +00001670 Parser.Lex(); // Eat identifier token.
1671 return RegNum;
1672}
Jim Grosbachd4462a52010-11-01 16:44:21 +00001673
Jim Grosbach19906722011-07-13 18:49:30 +00001674// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
1675// If a recoverable error occurs, return 1. If an irrecoverable error
1676// occurs, return -1. An irrecoverable error is one where tokens have been
1677// consumed in the process of trying to parse the shifter (i.e., when it is
1678// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00001679int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00001680 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1681 SMLoc S = Parser.getTok().getLoc();
1682 const AsmToken &Tok = Parser.getTok();
1683 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1684
1685 std::string upperCase = Tok.getString().str();
1686 std::string lowerCase = LowercaseString(upperCase);
1687 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
1688 .Case("lsl", ARM_AM::lsl)
1689 .Case("lsr", ARM_AM::lsr)
1690 .Case("asr", ARM_AM::asr)
1691 .Case("ror", ARM_AM::ror)
1692 .Case("rrx", ARM_AM::rrx)
1693 .Default(ARM_AM::no_shift);
1694
1695 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00001696 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00001697
Jim Grosbache8606dc2011-07-13 17:50:29 +00001698 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00001699
Jim Grosbache8606dc2011-07-13 17:50:29 +00001700 // The source register for the shift has already been added to the
1701 // operand list, so we need to pop it off and combine it into the shifted
1702 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00001703 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00001704 if (!PrevOp->isReg())
1705 return Error(PrevOp->getStartLoc(), "shift must be of a register");
1706 int SrcReg = PrevOp->getReg();
1707 int64_t Imm = 0;
1708 int ShiftReg = 0;
1709 if (ShiftTy == ARM_AM::rrx) {
1710 // RRX Doesn't have an explicit shift amount. The encoder expects
1711 // the shift register to be the same as the source register. Seems odd,
1712 // but OK.
1713 ShiftReg = SrcReg;
1714 } else {
1715 // Figure out if this is shifted by a constant or a register (for non-RRX).
1716 if (Parser.getTok().is(AsmToken::Hash)) {
1717 Parser.Lex(); // Eat hash.
1718 SMLoc ImmLoc = Parser.getTok().getLoc();
1719 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00001720 if (getParser().ParseExpression(ShiftExpr)) {
1721 Error(ImmLoc, "invalid immediate shift value");
1722 return -1;
1723 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001724 // The expression must be evaluatable as an immediate.
1725 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00001726 if (!CE) {
1727 Error(ImmLoc, "invalid immediate shift value");
1728 return -1;
1729 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001730 // Range check the immediate.
1731 // lsl, ror: 0 <= imm <= 31
1732 // lsr, asr: 0 <= imm <= 32
1733 Imm = CE->getValue();
1734 if (Imm < 0 ||
1735 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
1736 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00001737 Error(ImmLoc, "immediate shift value out of range");
1738 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001739 }
1740 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001741 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00001742 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00001743 if (ShiftReg == -1) {
1744 Error (L, "expected immediate or register in shift operand");
1745 return -1;
1746 }
1747 } else {
1748 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00001749 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00001750 return -1;
1751 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00001752 }
1753
Owen Anderson92a20222011-07-21 18:54:16 +00001754 if (ShiftReg && ShiftTy != ARM_AM::rrx)
1755 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001756 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001757 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00001758 else
1759 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
1760 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00001761
Jim Grosbach19906722011-07-13 18:49:30 +00001762 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00001763}
1764
1765
Bill Wendling50d0f582010-11-18 23:43:05 +00001766/// Try to parse a register name. The token must be an Identifier when called.
1767/// If it's a register, an AsmOperand is created. Another AsmOperand is created
1768/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00001769///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001770/// TODO this is likely to change to allow different register types and or to
1771/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00001772bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001773tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001774 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00001775 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00001776 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00001777 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001778
Bill Wendling50d0f582010-11-18 23:43:05 +00001779 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001780
Chris Lattnere5658fa2010-10-30 04:09:10 +00001781 const AsmToken &ExclaimTok = Parser.getTok();
1782 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00001783 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
1784 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00001785 Parser.Lex(); // Eat exclaim token
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00001786 }
1787
Bill Wendling50d0f582010-11-18 23:43:05 +00001788 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001789}
1790
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001791/// MatchCoprocessorOperandName - Try to parse an coprocessor related
1792/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
1793/// "c5", ...
1794static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001795 // Use the same layout as the tablegen'erated register name matcher. Ugly,
1796 // but efficient.
1797 switch (Name.size()) {
1798 default: break;
1799 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001800 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001801 return -1;
1802 switch (Name[1]) {
1803 default: return -1;
1804 case '0': return 0;
1805 case '1': return 1;
1806 case '2': return 2;
1807 case '3': return 3;
1808 case '4': return 4;
1809 case '5': return 5;
1810 case '6': return 6;
1811 case '7': return 7;
1812 case '8': return 8;
1813 case '9': return 9;
1814 }
1815 break;
1816 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001817 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001818 return -1;
1819 switch (Name[2]) {
1820 default: return -1;
1821 case '0': return 10;
1822 case '1': return 11;
1823 case '2': return 12;
1824 case '3': return 13;
1825 case '4': return 14;
1826 case '5': return 15;
1827 }
1828 break;
1829 }
1830
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001831 return -1;
1832}
1833
Jim Grosbach89df9962011-08-26 21:43:41 +00001834/// parseITCondCode - Try to parse a condition code for an IT instruction.
1835ARMAsmParser::OperandMatchResultTy ARMAsmParser::
1836parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1837 SMLoc S = Parser.getTok().getLoc();
1838 const AsmToken &Tok = Parser.getTok();
1839 if (!Tok.is(AsmToken::Identifier))
1840 return MatchOperand_NoMatch;
1841 unsigned CC = StringSwitch<unsigned>(Tok.getString())
1842 .Case("eq", ARMCC::EQ)
1843 .Case("ne", ARMCC::NE)
1844 .Case("hs", ARMCC::HS)
1845 .Case("cs", ARMCC::HS)
1846 .Case("lo", ARMCC::LO)
1847 .Case("cc", ARMCC::LO)
1848 .Case("mi", ARMCC::MI)
1849 .Case("pl", ARMCC::PL)
1850 .Case("vs", ARMCC::VS)
1851 .Case("vc", ARMCC::VC)
1852 .Case("hi", ARMCC::HI)
1853 .Case("ls", ARMCC::LS)
1854 .Case("ge", ARMCC::GE)
1855 .Case("lt", ARMCC::LT)
1856 .Case("gt", ARMCC::GT)
1857 .Case("le", ARMCC::LE)
1858 .Case("al", ARMCC::AL)
1859 .Default(~0U);
1860 if (CC == ~0U)
1861 return MatchOperand_NoMatch;
1862 Parser.Lex(); // Eat the token.
1863
1864 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
1865
1866 return MatchOperand_Success;
1867}
1868
Jim Grosbach43904292011-07-25 20:14:50 +00001869/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001870/// token must be an Identifier when called, and if it is a coprocessor
1871/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00001872ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00001873parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001874 SMLoc S = Parser.getTok().getLoc();
1875 const AsmToken &Tok = Parser.getTok();
1876 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1877
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001878 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001879 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00001880 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001881
1882 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001883 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00001884 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001885}
1886
Jim Grosbach43904292011-07-25 20:14:50 +00001887/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001888/// token must be an Identifier when called, and if it is a coprocessor
1889/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00001890ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00001891parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001892 SMLoc S = Parser.getTok().getLoc();
1893 const AsmToken &Tok = Parser.getTok();
1894 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1895
1896 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
1897 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00001898 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001899
1900 Parser.Lex(); // Eat identifier token.
1901 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00001902 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00001903}
1904
Jim Grosbachd0588e22011-09-14 18:08:35 +00001905// For register list parsing, we need to map from raw GPR register numbering
1906// to the enumeration values. The enumeration values aren't sorted by
1907// register number due to our using "sp", "lr" and "pc" as canonical names.
1908static unsigned getNextRegister(unsigned Reg) {
1909 // If this is a GPR, we need to do it manually, otherwise we can rely
1910 // on the sort ordering of the enumeration since the other reg-classes
1911 // are sane.
1912 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
1913 return Reg + 1;
1914 switch(Reg) {
1915 default: assert(0 && "Invalid GPR number!");
1916 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
1917 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
1918 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
1919 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
1920 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
1921 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
1922 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
1923 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
1924 }
1925}
1926
1927/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00001928bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00001929parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00001930 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00001931 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00001932 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00001933 Parser.Lex(); // Eat '{' token.
1934 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00001935
Jim Grosbachd0588e22011-09-14 18:08:35 +00001936 // Check the first register in the list to see what register class
1937 // this is a list of.
1938 int Reg = tryParseRegister();
1939 if (Reg == -1)
1940 return Error(RegLoc, "register expected");
1941
1942 MCRegisterClass *RC;
1943 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
1944 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
1945 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
1946 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
1947 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
1948 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
1949 else
1950 return Error(RegLoc, "invalid register in register list");
1951
1952 // The reglist instructions have at most 16 registers, so reserve
1953 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00001954 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00001955 // Store the first register.
1956 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00001957
Jim Grosbachd0588e22011-09-14 18:08:35 +00001958 // This starts immediately after the first register token in the list,
1959 // so we can see either a comma or a minus (range separator) as a legal
1960 // next token.
1961 while (Parser.getTok().is(AsmToken::Comma) ||
1962 Parser.getTok().is(AsmToken::Minus)) {
1963 if (Parser.getTok().is(AsmToken::Minus)) {
1964 Parser.Lex(); // Eat the comma.
1965 SMLoc EndLoc = Parser.getTok().getLoc();
1966 int EndReg = tryParseRegister();
1967 if (EndReg == -1)
1968 return Error(EndLoc, "register expected");
1969 // If the register is the same as the start reg, there's nothing
1970 // more to do.
1971 if (Reg == EndReg)
1972 continue;
1973 // The register must be in the same register class as the first.
1974 if (!RC->contains(EndReg))
1975 return Error(EndLoc, "invalid register in register list");
1976 // Ranges must go from low to high.
1977 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
1978 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00001979
Jim Grosbachd0588e22011-09-14 18:08:35 +00001980 // Add all the registers in the range to the register list.
1981 while (Reg != EndReg) {
1982 Reg = getNextRegister(Reg);
1983 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
1984 }
1985 continue;
1986 }
1987 Parser.Lex(); // Eat the comma.
1988 RegLoc = Parser.getTok().getLoc();
1989 int OldReg = Reg;
1990 Reg = tryParseRegister();
1991 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00001992 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00001993 // The register must be in the same register class as the first.
1994 if (!RC->contains(Reg))
1995 return Error(RegLoc, "invalid register in register list");
1996 // List must be monotonically increasing.
1997 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
1998 return Error(RegLoc, "register list not in ascending order");
1999 // VFP register lists must also be contiguous.
2000 // It's OK to use the enumeration values directly here rather, as the
2001 // VFP register classes have the enum sorted properly.
2002 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2003 Reg != OldReg + 1)
2004 return Error(RegLoc, "non-contiguous register range");
2005 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002006 }
2007
Jim Grosbachd0588e22011-09-14 18:08:35 +00002008 SMLoc E = Parser.getTok().getLoc();
2009 if (Parser.getTok().isNot(AsmToken::RCurly))
2010 return Error(E, "'}' expected");
2011 Parser.Lex(); // Eat '}' token.
2012
Bill Wendling50d0f582010-11-18 23:43:05 +00002013 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2014 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002015}
2016
Jim Grosbach43904292011-07-25 20:14:50 +00002017/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002018ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002019parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002020 SMLoc S = Parser.getTok().getLoc();
2021 const AsmToken &Tok = Parser.getTok();
2022 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2023 StringRef OptStr = Tok.getString();
2024
2025 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2026 .Case("sy", ARM_MB::SY)
2027 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002028 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002029 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002030 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002031 .Case("ishst", ARM_MB::ISHST)
2032 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002033 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002034 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002035 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002036 .Case("osh", ARM_MB::OSH)
2037 .Case("oshst", ARM_MB::OSHST)
2038 .Default(~0U);
2039
2040 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002041 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002042
2043 Parser.Lex(); // Eat identifier token.
2044 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002045 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002046}
2047
Jim Grosbach43904292011-07-25 20:14:50 +00002048/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002049ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002050parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002051 SMLoc S = Parser.getTok().getLoc();
2052 const AsmToken &Tok = Parser.getTok();
2053 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2054 StringRef IFlagsStr = Tok.getString();
2055
2056 unsigned IFlags = 0;
2057 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2058 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2059 .Case("a", ARM_PROC::A)
2060 .Case("i", ARM_PROC::I)
2061 .Case("f", ARM_PROC::F)
2062 .Default(~0U);
2063
2064 // If some specific iflag is already set, it means that some letter is
2065 // present more than once, this is not acceptable.
2066 if (Flag == ~0U || (IFlags & Flag))
2067 return MatchOperand_NoMatch;
2068
2069 IFlags |= Flag;
2070 }
2071
2072 Parser.Lex(); // Eat identifier token.
2073 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2074 return MatchOperand_Success;
2075}
2076
Jim Grosbach43904292011-07-25 20:14:50 +00002077/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002078ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002079parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002080 SMLoc S = Parser.getTok().getLoc();
2081 const AsmToken &Tok = Parser.getTok();
2082 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2083 StringRef Mask = Tok.getString();
2084
James Molloyacad68d2011-09-28 14:21:38 +00002085 if (isMClass()) {
2086 // See ARMv6-M 10.1.1
2087 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2088 .Case("apsr", 0)
2089 .Case("iapsr", 1)
2090 .Case("eapsr", 2)
2091 .Case("xpsr", 3)
2092 .Case("ipsr", 5)
2093 .Case("epsr", 6)
2094 .Case("iepsr", 7)
2095 .Case("msp", 8)
2096 .Case("psp", 9)
2097 .Case("primask", 16)
2098 .Case("basepri", 17)
2099 .Case("basepri_max", 18)
2100 .Case("faultmask", 19)
2101 .Case("control", 20)
2102 .Default(~0U);
2103
2104 if (FlagsVal == ~0U)
2105 return MatchOperand_NoMatch;
2106
2107 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2108 // basepri, basepri_max and faultmask only valid for V7m.
2109 return MatchOperand_NoMatch;
2110
2111 Parser.Lex(); // Eat identifier token.
2112 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2113 return MatchOperand_Success;
2114 }
2115
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002116 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2117 size_t Start = 0, Next = Mask.find('_');
2118 StringRef Flags = "";
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002119 std::string SpecReg = LowercaseString(Mask.slice(Start, Next));
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002120 if (Next != StringRef::npos)
2121 Flags = Mask.slice(Next+1, Mask.size());
2122
2123 // FlagsVal contains the complete mask:
2124 // 3-0: Mask
2125 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2126 unsigned FlagsVal = 0;
2127
2128 if (SpecReg == "apsr") {
2129 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002130 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002131 .Case("g", 0x4) // same as CPSR_s
2132 .Case("nzcvqg", 0xc) // same as CPSR_fs
2133 .Default(~0U);
2134
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002135 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002136 if (!Flags.empty())
2137 return MatchOperand_NoMatch;
2138 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002139 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002140 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002141 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002142 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2143 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002144 for (int i = 0, e = Flags.size(); i != e; ++i) {
2145 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2146 .Case("c", 1)
2147 .Case("x", 2)
2148 .Case("s", 4)
2149 .Case("f", 8)
2150 .Default(~0U);
2151
2152 // If some specific flag is already set, it means that some letter is
2153 // present more than once, this is not acceptable.
2154 if (FlagsVal == ~0U || (FlagsVal & Flag))
2155 return MatchOperand_NoMatch;
2156 FlagsVal |= Flag;
2157 }
2158 } else // No match for special register.
2159 return MatchOperand_NoMatch;
2160
2161 // Special register without flags are equivalent to "fc" flags.
2162 if (!FlagsVal)
2163 FlagsVal = 0x9;
2164
2165 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2166 if (SpecReg == "spsr")
2167 FlagsVal |= 16;
2168
2169 Parser.Lex(); // Eat identifier token.
2170 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2171 return MatchOperand_Success;
2172}
2173
Jim Grosbachf6c05252011-07-21 17:23:04 +00002174ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2175parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2176 int Low, int High) {
2177 const AsmToken &Tok = Parser.getTok();
2178 if (Tok.isNot(AsmToken::Identifier)) {
2179 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2180 return MatchOperand_ParseFail;
2181 }
2182 StringRef ShiftName = Tok.getString();
2183 std::string LowerOp = LowercaseString(Op);
2184 std::string UpperOp = UppercaseString(Op);
2185 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2186 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2187 return MatchOperand_ParseFail;
2188 }
2189 Parser.Lex(); // Eat shift type token.
2190
2191 // There must be a '#' and a shift amount.
2192 if (Parser.getTok().isNot(AsmToken::Hash)) {
2193 Error(Parser.getTok().getLoc(), "'#' expected");
2194 return MatchOperand_ParseFail;
2195 }
2196 Parser.Lex(); // Eat hash token.
2197
2198 const MCExpr *ShiftAmount;
2199 SMLoc Loc = Parser.getTok().getLoc();
2200 if (getParser().ParseExpression(ShiftAmount)) {
2201 Error(Loc, "illegal expression");
2202 return MatchOperand_ParseFail;
2203 }
2204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2205 if (!CE) {
2206 Error(Loc, "constant expression expected");
2207 return MatchOperand_ParseFail;
2208 }
2209 int Val = CE->getValue();
2210 if (Val < Low || Val > High) {
2211 Error(Loc, "immediate value out of range");
2212 return MatchOperand_ParseFail;
2213 }
2214
2215 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2216
2217 return MatchOperand_Success;
2218}
2219
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002220ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2221parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2222 const AsmToken &Tok = Parser.getTok();
2223 SMLoc S = Tok.getLoc();
2224 if (Tok.isNot(AsmToken::Identifier)) {
2225 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2226 return MatchOperand_ParseFail;
2227 }
2228 int Val = StringSwitch<int>(Tok.getString())
2229 .Case("be", 1)
2230 .Case("le", 0)
2231 .Default(-1);
2232 Parser.Lex(); // Eat the token.
2233
2234 if (Val == -1) {
2235 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2236 return MatchOperand_ParseFail;
2237 }
2238 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2239 getContext()),
2240 S, Parser.getTok().getLoc()));
2241 return MatchOperand_Success;
2242}
2243
Jim Grosbach580f4a92011-07-25 22:20:28 +00002244/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2245/// instructions. Legal values are:
2246/// lsl #n 'n' in [0,31]
2247/// asr #n 'n' in [1,32]
2248/// n == 32 encoded as n == 0.
2249ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2250parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2251 const AsmToken &Tok = Parser.getTok();
2252 SMLoc S = Tok.getLoc();
2253 if (Tok.isNot(AsmToken::Identifier)) {
2254 Error(S, "shift operator 'asr' or 'lsl' expected");
2255 return MatchOperand_ParseFail;
2256 }
2257 StringRef ShiftName = Tok.getString();
2258 bool isASR;
2259 if (ShiftName == "lsl" || ShiftName == "LSL")
2260 isASR = false;
2261 else if (ShiftName == "asr" || ShiftName == "ASR")
2262 isASR = true;
2263 else {
2264 Error(S, "shift operator 'asr' or 'lsl' expected");
2265 return MatchOperand_ParseFail;
2266 }
2267 Parser.Lex(); // Eat the operator.
2268
2269 // A '#' and a shift amount.
2270 if (Parser.getTok().isNot(AsmToken::Hash)) {
2271 Error(Parser.getTok().getLoc(), "'#' expected");
2272 return MatchOperand_ParseFail;
2273 }
2274 Parser.Lex(); // Eat hash token.
2275
2276 const MCExpr *ShiftAmount;
2277 SMLoc E = Parser.getTok().getLoc();
2278 if (getParser().ParseExpression(ShiftAmount)) {
2279 Error(E, "malformed shift expression");
2280 return MatchOperand_ParseFail;
2281 }
2282 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2283 if (!CE) {
2284 Error(E, "shift amount must be an immediate");
2285 return MatchOperand_ParseFail;
2286 }
2287
2288 int64_t Val = CE->getValue();
2289 if (isASR) {
2290 // Shift amount must be in [1,32]
2291 if (Val < 1 || Val > 32) {
2292 Error(E, "'asr' shift amount must be in range [1,32]");
2293 return MatchOperand_ParseFail;
2294 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002295 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2296 if (isThumb() && Val == 32) {
2297 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2298 return MatchOperand_ParseFail;
2299 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002300 if (Val == 32) Val = 0;
2301 } else {
2302 // Shift amount must be in [1,32]
2303 if (Val < 0 || Val > 31) {
2304 Error(E, "'lsr' shift amount must be in range [0,31]");
2305 return MatchOperand_ParseFail;
2306 }
2307 }
2308
2309 E = Parser.getTok().getLoc();
2310 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2311
2312 return MatchOperand_Success;
2313}
2314
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002315/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2316/// of instructions. Legal values are:
2317/// ror #n 'n' in {0, 8, 16, 24}
2318ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2319parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2320 const AsmToken &Tok = Parser.getTok();
2321 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002322 if (Tok.isNot(AsmToken::Identifier))
2323 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002324 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002325 if (ShiftName != "ror" && ShiftName != "ROR")
2326 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002327 Parser.Lex(); // Eat the operator.
2328
2329 // A '#' and a rotate amount.
2330 if (Parser.getTok().isNot(AsmToken::Hash)) {
2331 Error(Parser.getTok().getLoc(), "'#' expected");
2332 return MatchOperand_ParseFail;
2333 }
2334 Parser.Lex(); // Eat hash token.
2335
2336 const MCExpr *ShiftAmount;
2337 SMLoc E = Parser.getTok().getLoc();
2338 if (getParser().ParseExpression(ShiftAmount)) {
2339 Error(E, "malformed rotate expression");
2340 return MatchOperand_ParseFail;
2341 }
2342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2343 if (!CE) {
2344 Error(E, "rotate amount must be an immediate");
2345 return MatchOperand_ParseFail;
2346 }
2347
2348 int64_t Val = CE->getValue();
2349 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2350 // normally, zero is represented in asm by omitting the rotate operand
2351 // entirely.
2352 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2353 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2354 return MatchOperand_ParseFail;
2355 }
2356
2357 E = Parser.getTok().getLoc();
2358 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2359
2360 return MatchOperand_Success;
2361}
2362
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002363ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2364parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2365 SMLoc S = Parser.getTok().getLoc();
2366 // The bitfield descriptor is really two operands, the LSB and the width.
2367 if (Parser.getTok().isNot(AsmToken::Hash)) {
2368 Error(Parser.getTok().getLoc(), "'#' expected");
2369 return MatchOperand_ParseFail;
2370 }
2371 Parser.Lex(); // Eat hash token.
2372
2373 const MCExpr *LSBExpr;
2374 SMLoc E = Parser.getTok().getLoc();
2375 if (getParser().ParseExpression(LSBExpr)) {
2376 Error(E, "malformed immediate expression");
2377 return MatchOperand_ParseFail;
2378 }
2379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2380 if (!CE) {
2381 Error(E, "'lsb' operand must be an immediate");
2382 return MatchOperand_ParseFail;
2383 }
2384
2385 int64_t LSB = CE->getValue();
2386 // The LSB must be in the range [0,31]
2387 if (LSB < 0 || LSB > 31) {
2388 Error(E, "'lsb' operand must be in the range [0,31]");
2389 return MatchOperand_ParseFail;
2390 }
2391 E = Parser.getTok().getLoc();
2392
2393 // Expect another immediate operand.
2394 if (Parser.getTok().isNot(AsmToken::Comma)) {
2395 Error(Parser.getTok().getLoc(), "too few operands");
2396 return MatchOperand_ParseFail;
2397 }
2398 Parser.Lex(); // Eat hash token.
2399 if (Parser.getTok().isNot(AsmToken::Hash)) {
2400 Error(Parser.getTok().getLoc(), "'#' expected");
2401 return MatchOperand_ParseFail;
2402 }
2403 Parser.Lex(); // Eat hash token.
2404
2405 const MCExpr *WidthExpr;
2406 if (getParser().ParseExpression(WidthExpr)) {
2407 Error(E, "malformed immediate expression");
2408 return MatchOperand_ParseFail;
2409 }
2410 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2411 if (!CE) {
2412 Error(E, "'width' operand must be an immediate");
2413 return MatchOperand_ParseFail;
2414 }
2415
2416 int64_t Width = CE->getValue();
2417 // The LSB must be in the range [1,32-lsb]
2418 if (Width < 1 || Width > 32 - LSB) {
2419 Error(E, "'width' operand must be in the range [1,32-lsb]");
2420 return MatchOperand_ParseFail;
2421 }
2422 E = Parser.getTok().getLoc();
2423
2424 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2425
2426 return MatchOperand_Success;
2427}
2428
Jim Grosbach7ce05792011-08-03 23:50:40 +00002429ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2430parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2431 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002432 // postidx_reg := '+' register {, shift}
2433 // | '-' register {, shift}
2434 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00002435
2436 // This method must return MatchOperand_NoMatch without consuming any tokens
2437 // in the case where there is no match, as other alternatives take other
2438 // parse methods.
2439 AsmToken Tok = Parser.getTok();
2440 SMLoc S = Tok.getLoc();
2441 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00002442 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002443 int Reg = -1;
2444 if (Tok.is(AsmToken::Plus)) {
2445 Parser.Lex(); // Eat the '+' token.
2446 haveEaten = true;
2447 } else if (Tok.is(AsmToken::Minus)) {
2448 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00002449 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002450 haveEaten = true;
2451 }
2452 if (Parser.getTok().is(AsmToken::Identifier))
2453 Reg = tryParseRegister();
2454 if (Reg == -1) {
2455 if (!haveEaten)
2456 return MatchOperand_NoMatch;
2457 Error(Parser.getTok().getLoc(), "register expected");
2458 return MatchOperand_ParseFail;
2459 }
2460 SMLoc E = Parser.getTok().getLoc();
2461
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002462 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
2463 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002464 if (Parser.getTok().is(AsmToken::Comma)) {
2465 Parser.Lex(); // Eat the ','.
2466 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
2467 return MatchOperand_ParseFail;
2468 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002469
2470 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
2471 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002472
2473 return MatchOperand_Success;
2474}
2475
Jim Grosbach251bf252011-08-10 21:56:18 +00002476ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2477parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2478 // Check for a post-index addressing register operand. Specifically:
2479 // am3offset := '+' register
2480 // | '-' register
2481 // | register
2482 // | # imm
2483 // | # + imm
2484 // | # - imm
2485
2486 // This method must return MatchOperand_NoMatch without consuming any tokens
2487 // in the case where there is no match, as other alternatives take other
2488 // parse methods.
2489 AsmToken Tok = Parser.getTok();
2490 SMLoc S = Tok.getLoc();
2491
2492 // Do immediates first, as we always parse those if we have a '#'.
2493 if (Parser.getTok().is(AsmToken::Hash)) {
2494 Parser.Lex(); // Eat the '#'.
2495 // Explicitly look for a '-', as we need to encode negative zero
2496 // differently.
2497 bool isNegative = Parser.getTok().is(AsmToken::Minus);
2498 const MCExpr *Offset;
2499 if (getParser().ParseExpression(Offset))
2500 return MatchOperand_ParseFail;
2501 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2502 if (!CE) {
2503 Error(S, "constant expression expected");
2504 return MatchOperand_ParseFail;
2505 }
2506 SMLoc E = Tok.getLoc();
2507 // Negative zero is encoded as the flag value INT32_MIN.
2508 int32_t Val = CE->getValue();
2509 if (isNegative && Val == 0)
2510 Val = INT32_MIN;
2511
2512 Operands.push_back(
2513 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
2514
2515 return MatchOperand_Success;
2516 }
2517
2518
2519 bool haveEaten = false;
2520 bool isAdd = true;
2521 int Reg = -1;
2522 if (Tok.is(AsmToken::Plus)) {
2523 Parser.Lex(); // Eat the '+' token.
2524 haveEaten = true;
2525 } else if (Tok.is(AsmToken::Minus)) {
2526 Parser.Lex(); // Eat the '-' token.
2527 isAdd = false;
2528 haveEaten = true;
2529 }
2530 if (Parser.getTok().is(AsmToken::Identifier))
2531 Reg = tryParseRegister();
2532 if (Reg == -1) {
2533 if (!haveEaten)
2534 return MatchOperand_NoMatch;
2535 Error(Parser.getTok().getLoc(), "register expected");
2536 return MatchOperand_ParseFail;
2537 }
2538 SMLoc E = Parser.getTok().getLoc();
2539
2540 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
2541 0, S, E));
2542
2543 return MatchOperand_Success;
2544}
2545
Jim Grosbacha77295d2011-09-08 22:07:06 +00002546/// cvtT2LdrdPre - Convert parsed operands to MCInst.
2547/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2548/// when they refer multiple MIOperands inside a single one.
2549bool ARMAsmParser::
2550cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
2551 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2552 // Rt, Rt2
2553 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2554 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2555 // Create a writeback register dummy placeholder.
2556 Inst.addOperand(MCOperand::CreateReg(0));
2557 // addr
2558 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2559 // pred
2560 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2561 return true;
2562}
2563
2564/// cvtT2StrdPre - Convert parsed operands to MCInst.
2565/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2566/// when they refer multiple MIOperands inside a single one.
2567bool ARMAsmParser::
2568cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
2569 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2570 // Create a writeback register dummy placeholder.
2571 Inst.addOperand(MCOperand::CreateReg(0));
2572 // Rt, Rt2
2573 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2574 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2575 // addr
2576 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
2577 // pred
2578 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2579 return true;
2580}
2581
Jim Grosbacheeec0252011-09-08 00:39:19 +00002582/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2583/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2584/// when they refer multiple MIOperands inside a single one.
2585bool ARMAsmParser::
2586cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2587 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2588 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2589
2590 // Create a writeback register dummy placeholder.
2591 Inst.addOperand(MCOperand::CreateImm(0));
2592
2593 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2594 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2595 return true;
2596}
2597
Jim Grosbachee2c2a42011-09-16 21:55:56 +00002598/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
2599/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2600/// when they refer multiple MIOperands inside a single one.
2601bool ARMAsmParser::
2602cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
2603 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2604 // Create a writeback register dummy placeholder.
2605 Inst.addOperand(MCOperand::CreateImm(0));
2606 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2607 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
2608 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2609 return true;
2610}
2611
Jim Grosbach1355cf12011-07-26 17:10:22 +00002612/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002613/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2614/// when they refer multiple MIOperands inside a single one.
2615bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002616cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002617 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2618 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2619
2620 // Create a writeback register dummy placeholder.
2621 Inst.addOperand(MCOperand::CreateImm(0));
2622
Jim Grosbach7ce05792011-08-03 23:50:40 +00002623 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002624 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2625 return true;
2626}
2627
Owen Anderson9ab0f252011-08-26 20:43:14 +00002628/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2629/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2630/// when they refer multiple MIOperands inside a single one.
2631bool ARMAsmParser::
2632cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2633 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2634 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2635
2636 // Create a writeback register dummy placeholder.
2637 Inst.addOperand(MCOperand::CreateImm(0));
2638
2639 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2640 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2641 return true;
2642}
2643
2644
Jim Grosbach548340c2011-08-11 19:22:40 +00002645/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
2646/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2647/// when they refer multiple MIOperands inside a single one.
2648bool ARMAsmParser::
2649cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
2650 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2651 // Create a writeback register dummy placeholder.
2652 Inst.addOperand(MCOperand::CreateImm(0));
2653 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2654 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
2655 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2656 return true;
2657}
2658
Jim Grosbach1355cf12011-07-26 17:10:22 +00002659/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002660/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2661/// when they refer multiple MIOperands inside a single one.
2662bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002663cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002664 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2665 // Create a writeback register dummy placeholder.
2666 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00002667 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2668 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
2669 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002670 return true;
2671}
2672
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00002673/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2674/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2675/// when they refer multiple MIOperands inside a single one.
2676bool ARMAsmParser::
2677cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2678 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2679 // Create a writeback register dummy placeholder.
2680 Inst.addOperand(MCOperand::CreateImm(0));
2681 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2682 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2683 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2684 return true;
2685}
2686
Jim Grosbach7ce05792011-08-03 23:50:40 +00002687/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
2688/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2689/// when they refer multiple MIOperands inside a single one.
2690bool ARMAsmParser::
2691cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2692 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2693 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002694 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002695 // Create a writeback register dummy placeholder.
2696 Inst.addOperand(MCOperand::CreateImm(0));
2697 // addr
2698 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2699 // offset
2700 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2701 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00002702 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2703 return true;
2704}
2705
Jim Grosbach7ce05792011-08-03 23:50:40 +00002706/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002707/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2708/// when they refer multiple MIOperands inside a single one.
2709bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002710cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2711 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2712 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00002713 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002714 // Create a writeback register dummy placeholder.
2715 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002716 // addr
2717 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2718 // offset
2719 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2720 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002721 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2722 return true;
2723}
2724
Jim Grosbach7ce05792011-08-03 23:50:40 +00002725/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002726/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2727/// when they refer multiple MIOperands inside a single one.
2728bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002729cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
2730 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002731 // Create a writeback register dummy placeholder.
2732 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00002733 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002734 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002735 // addr
2736 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2737 // offset
2738 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
2739 // pred
2740 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2741 return true;
2742}
2743
2744/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
2745/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2746/// when they refer multiple MIOperands inside a single one.
2747bool ARMAsmParser::
2748cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
2749 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2750 // Create a writeback register dummy placeholder.
2751 Inst.addOperand(MCOperand::CreateImm(0));
2752 // Rt
2753 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2754 // addr
2755 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
2756 // offset
2757 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
2758 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00002759 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2760 return true;
2761}
2762
Jim Grosbach2fd2b872011-08-10 20:29:19 +00002763/// cvtLdrdPre - Convert parsed operands to MCInst.
2764/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2765/// when they refer multiple MIOperands inside a single one.
2766bool ARMAsmParser::
2767cvtLdrdPre(MCInst &Inst, unsigned Opcode,
2768 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2769 // Rt, Rt2
2770 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2771 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2772 // Create a writeback register dummy placeholder.
2773 Inst.addOperand(MCOperand::CreateImm(0));
2774 // addr
2775 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2776 // pred
2777 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2778 return true;
2779}
2780
Jim Grosbach14605d12011-08-11 20:28:23 +00002781/// cvtStrdPre - Convert parsed operands to MCInst.
2782/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2783/// when they refer multiple MIOperands inside a single one.
2784bool ARMAsmParser::
2785cvtStrdPre(MCInst &Inst, unsigned Opcode,
2786 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2787 // Create a writeback register dummy placeholder.
2788 Inst.addOperand(MCOperand::CreateImm(0));
2789 // Rt, Rt2
2790 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2791 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2792 // addr
2793 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
2794 // pred
2795 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2796 return true;
2797}
2798
Jim Grosbach623a4542011-08-10 22:42:16 +00002799/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
2800/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2801/// when they refer multiple MIOperands inside a single one.
2802bool ARMAsmParser::
2803cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
2804 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2805 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
2806 // Create a writeback register dummy placeholder.
2807 Inst.addOperand(MCOperand::CreateImm(0));
2808 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
2809 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
2810 return true;
2811}
2812
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002813/// cvtThumbMultiple- Convert parsed operands to MCInst.
2814/// Needed here because the Asm Gen Matcher can't handle properly tied operands
2815/// when they refer multiple MIOperands inside a single one.
2816bool ARMAsmParser::
2817cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
2818 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2819 // The second source operand must be the same register as the destination
2820 // operand.
2821 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00002822 (((ARMOperand*)Operands[3])->getReg() !=
2823 ((ARMOperand*)Operands[5])->getReg()) &&
2824 (((ARMOperand*)Operands[3])->getReg() !=
2825 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002826 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00002827 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002828 return false;
2829 }
2830 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
2831 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
2832 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00002833 // If we have a three-operand form, use that, else the second source operand
2834 // is just the destination operand again.
2835 if (Operands.size() == 6)
2836 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
2837 else
2838 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00002839 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
2840
2841 return true;
2842}
Jim Grosbach623a4542011-08-10 22:42:16 +00002843
Bill Wendlinge7176102010-11-06 22:36:58 +00002844/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002845/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00002846bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00002847parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00002848 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00002849 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002850 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00002851 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00002852 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002853
Sean Callanan18b83232010-01-19 21:44:56 +00002854 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002855 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002856 if (BaseRegNum == -1)
2857 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002858
Daniel Dunbar05710932011-01-18 05:34:17 +00002859 // The next token must either be a comma or a closing bracket.
2860 const AsmToken &Tok = Parser.getTok();
2861 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00002862 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00002863
Jim Grosbach7ce05792011-08-03 23:50:40 +00002864 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00002865 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00002866 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002867
Jim Grosbach7ce05792011-08-03 23:50:40 +00002868 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
2869 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00002870
Jim Grosbachfb12f352011-09-19 18:42:21 +00002871 // If there's a pre-indexing writeback marker, '!', just add it as a token
2872 // operand. It's rather odd, but syntactically valid.
2873 if (Parser.getTok().is(AsmToken::Exclaim)) {
2874 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2875 Parser.Lex(); // Eat the '!'.
2876 }
2877
Jim Grosbach7ce05792011-08-03 23:50:40 +00002878 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002879 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00002880
Jim Grosbach7ce05792011-08-03 23:50:40 +00002881 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
2882 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00002883
Jim Grosbach7ce05792011-08-03 23:50:40 +00002884 // If we have a '#' it's an immediate offset, else assume it's a register
2885 // offset.
2886 if (Parser.getTok().is(AsmToken::Hash)) {
2887 Parser.Lex(); // Eat the '#'.
2888 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00002889
Owen Anderson0da10cf2011-08-29 19:36:44 +00002890 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002891 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002892 if (getParser().ParseExpression(Offset))
2893 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002894
2895 // The expression has to be a constant. Memory references with relocations
2896 // don't come through here, as they use the <label> forms of the relevant
2897 // instructions.
2898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
2899 if (!CE)
2900 return Error (E, "constant expression expected");
2901
Owen Anderson0da10cf2011-08-29 19:36:44 +00002902 // If the constant was #-0, represent it as INT32_MIN.
2903 int32_t Val = CE->getValue();
2904 if (isNegative && Val == 0)
2905 CE = MCConstantExpr::Create(INT32_MIN, getContext());
2906
Jim Grosbach7ce05792011-08-03 23:50:40 +00002907 // Now we should have the closing ']'
2908 E = Parser.getTok().getLoc();
2909 if (Parser.getTok().isNot(AsmToken::RBrac))
2910 return Error(E, "']' expected");
2911 Parser.Lex(); // Eat right bracket token.
2912
2913 // Don't worry about range checking the value here. That's handled by
2914 // the is*() predicates.
2915 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
2916 ARM_AM::no_shift, 0, false, S,E));
2917
2918 // If there's a pre-indexing writeback marker, '!', just add it as a token
2919 // operand.
2920 if (Parser.getTok().is(AsmToken::Exclaim)) {
2921 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2922 Parser.Lex(); // Eat the '!'.
2923 }
2924
2925 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002926 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00002927
2928 // The register offset is optionally preceded by a '+' or '-'
2929 bool isNegative = false;
2930 if (Parser.getTok().is(AsmToken::Minus)) {
2931 isNegative = true;
2932 Parser.Lex(); // Eat the '-'.
2933 } else if (Parser.getTok().is(AsmToken::Plus)) {
2934 // Nothing to do.
2935 Parser.Lex(); // Eat the '+'.
2936 }
2937
2938 E = Parser.getTok().getLoc();
2939 int OffsetRegNum = tryParseRegister();
2940 if (OffsetRegNum == -1)
2941 return Error(E, "register expected");
2942
2943 // If there's a shift operator, handle it.
2944 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002945 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002946 if (Parser.getTok().is(AsmToken::Comma)) {
2947 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002948 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00002949 return true;
2950 }
2951
2952 // Now we should have the closing ']'
2953 E = Parser.getTok().getLoc();
2954 if (Parser.getTok().isNot(AsmToken::RBrac))
2955 return Error(E, "']' expected");
2956 Parser.Lex(); // Eat right bracket token.
2957
2958 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002959 ShiftType, ShiftImm, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002960 S, E));
2961
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002962 // If there's a pre-indexing writeback marker, '!', just add it as a token
2963 // operand.
2964 if (Parser.getTok().is(AsmToken::Exclaim)) {
2965 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
2966 Parser.Lex(); // Eat the '!'.
2967 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00002968
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002969 return false;
2970}
2971
Jim Grosbach7ce05792011-08-03 23:50:40 +00002972/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002973/// ( lsl | lsr | asr | ror ) , # shift_amount
2974/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00002975/// return true if it parses a shift otherwise it returns false.
2976bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
2977 unsigned &Amount) {
2978 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00002979 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002980 if (Tok.isNot(AsmToken::Identifier))
2981 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00002982 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002983 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00002984 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002985 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00002986 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002987 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00002988 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002989 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00002990 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002991 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00002992 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002993 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00002994 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00002995 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002996
Jim Grosbach7ce05792011-08-03 23:50:40 +00002997 // rrx stands alone.
2998 Amount = 0;
2999 if (St != ARM_AM::rrx) {
3000 Loc = Parser.getTok().getLoc();
3001 // A '#' and a shift amount.
3002 const AsmToken &HashTok = Parser.getTok();
3003 if (HashTok.isNot(AsmToken::Hash))
3004 return Error(HashTok.getLoc(), "'#' expected");
3005 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003006
Jim Grosbach7ce05792011-08-03 23:50:40 +00003007 const MCExpr *Expr;
3008 if (getParser().ParseExpression(Expr))
3009 return true;
3010 // Range check the immediate.
3011 // lsl, ror: 0 <= imm <= 31
3012 // lsr, asr: 0 <= imm <= 32
3013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3014 if (!CE)
3015 return Error(Loc, "shift amount must be an immediate");
3016 int64_t Imm = CE->getValue();
3017 if (Imm < 0 ||
3018 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3019 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3020 return Error(Loc, "immediate shift value out of range");
3021 Amount = Imm;
3022 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003023
3024 return false;
3025}
3026
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003027/// Parse a arm instruction operand. For now this parses the operand regardless
3028/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003029bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003030 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003031 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003032
3033 // Check if the current operand has a custom associated parser, if so, try to
3034 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003035 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3036 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003037 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003038 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3039 // there was a match, but an error occurred, in which case, just return that
3040 // the operand parsing failed.
3041 if (ResTy == MatchOperand_ParseFail)
3042 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003043
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003044 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003045 default:
3046 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003047 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003048 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003049 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003050 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003051 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003052 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003053 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003054 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003055 else if (Res == -1) // irrecoverable error
3056 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003057 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3058 S = Parser.getTok().getLoc();
3059 Parser.Lex();
3060 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3061 return false;
3062 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003063
3064 // Fall though for the Identifier case that is not a register or a
3065 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003066 }
Kevin Enderby67b212e2011-01-13 20:32:36 +00003067 case AsmToken::Integer: // things like 1f and 2b as a branch targets
3068 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003069 // This was not a register so parse other operands that start with an
3070 // identifier (like labels) as expressions and create them as immediates.
3071 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003072 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003073 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003074 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003075 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003076 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3077 return false;
3078 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003079 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003080 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003081 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003082 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003083 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003084 // #42 -> immediate.
3085 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003086 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003087 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003088 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003089 const MCExpr *ImmVal;
3090 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003091 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003092 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
3093 if (!CE) {
3094 Error(S, "constant expression expected");
3095 return MatchOperand_ParseFail;
3096 }
3097 int32_t Val = CE->getValue();
3098 if (isNegative && Val == 0)
3099 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Sean Callanan76264762010-04-02 22:27:05 +00003100 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003101 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3102 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003103 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003104 case AsmToken::Colon: {
3105 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003106 // FIXME: Check it's an expression prefix,
3107 // e.g. (FOO - :lower16:BAR) isn't legal.
3108 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003109 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003110 return true;
3111
Evan Cheng75972122011-01-13 07:58:56 +00003112 const MCExpr *SubExprVal;
3113 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003114 return true;
3115
Evan Cheng75972122011-01-13 07:58:56 +00003116 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3117 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003118 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003119 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003120 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003121 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003122 }
3123}
3124
Jim Grosbach1355cf12011-07-26 17:10:22 +00003125// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003126// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003127bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003128 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003129
3130 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003131 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003132 Parser.Lex(); // Eat ':'
3133
3134 if (getLexer().isNot(AsmToken::Identifier)) {
3135 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3136 return true;
3137 }
3138
3139 StringRef IDVal = Parser.getTok().getIdentifier();
3140 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003141 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003142 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003143 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003144 } else {
3145 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3146 return true;
3147 }
3148 Parser.Lex();
3149
3150 if (getLexer().isNot(AsmToken::Colon)) {
3151 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3152 return true;
3153 }
3154 Parser.Lex(); // Eat the last ':'
3155 return false;
3156}
3157
Daniel Dunbar352e1482011-01-11 15:59:50 +00003158/// \brief Given a mnemonic, split out possible predication code and carry
3159/// setting letters to form a canonical mnemonic and flags.
3160//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003161// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003162// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003163StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003164 unsigned &PredicationCode,
3165 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003166 unsigned &ProcessorIMod,
3167 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003168 PredicationCode = ARMCC::AL;
3169 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003170 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003171
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003172 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003173 //
3174 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003175 if ((Mnemonic == "movs" && isThumb()) ||
3176 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3177 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3178 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3179 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3180 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3181 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3182 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003183 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003184
Jim Grosbach3f00e312011-07-11 17:09:57 +00003185 // First, split out any predication code. Ignore mnemonics we know aren't
3186 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003187 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003188 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003189 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003190 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003191 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3192 .Case("eq", ARMCC::EQ)
3193 .Case("ne", ARMCC::NE)
3194 .Case("hs", ARMCC::HS)
3195 .Case("cs", ARMCC::HS)
3196 .Case("lo", ARMCC::LO)
3197 .Case("cc", ARMCC::LO)
3198 .Case("mi", ARMCC::MI)
3199 .Case("pl", ARMCC::PL)
3200 .Case("vs", ARMCC::VS)
3201 .Case("vc", ARMCC::VC)
3202 .Case("hi", ARMCC::HI)
3203 .Case("ls", ARMCC::LS)
3204 .Case("ge", ARMCC::GE)
3205 .Case("lt", ARMCC::LT)
3206 .Case("gt", ARMCC::GT)
3207 .Case("le", ARMCC::LE)
3208 .Case("al", ARMCC::AL)
3209 .Default(~0U);
3210 if (CC != ~0U) {
3211 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3212 PredicationCode = CC;
3213 }
Bill Wendling52925b62010-10-29 23:50:21 +00003214 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003215
Daniel Dunbar352e1482011-01-11 15:59:50 +00003216 // Next, determine if we have a carry setting bit. We explicitly ignore all
3217 // the instructions we know end in 's'.
3218 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003219 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003220 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3221 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3222 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003223 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3224 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003225 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3226 CarrySetting = true;
3227 }
3228
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003229 // The "cps" instruction can have a interrupt mode operand which is glued into
3230 // the mnemonic. Check if this is the case, split it and parse the imod op
3231 if (Mnemonic.startswith("cps")) {
3232 // Split out any imod code.
3233 unsigned IMod =
3234 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3235 .Case("ie", ARM_PROC::IE)
3236 .Case("id", ARM_PROC::ID)
3237 .Default(~0U);
3238 if (IMod != ~0U) {
3239 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3240 ProcessorIMod = IMod;
3241 }
3242 }
3243
Jim Grosbach89df9962011-08-26 21:43:41 +00003244 // The "it" instruction has the condition mask on the end of the mnemonic.
3245 if (Mnemonic.startswith("it")) {
3246 ITMask = Mnemonic.slice(2, Mnemonic.size());
3247 Mnemonic = Mnemonic.slice(0, 2);
3248 }
3249
Daniel Dunbar352e1482011-01-11 15:59:50 +00003250 return Mnemonic;
3251}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003252
3253/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3254/// inclusion of carry set or predication code operands.
3255//
3256// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003257void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003258getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003259 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003260 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
3261 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003262 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003263 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003264 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003265 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003266 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00003267 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00003268 Mnemonic == "mla" || Mnemonic == "smlal" ||
3269 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003270 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003271 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003272 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003273
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00003274 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
3275 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
3276 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
3277 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00003278 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
3279 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00003280 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00003281 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
3282 !isThumb()) ||
3283 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
3284 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003285 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003286 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003287 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003288 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003289
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003290 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003291 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00003292 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00003293 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00003294 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003295}
3296
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003297bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
3298 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003299 // FIXME: This is all horribly hacky. We really need a better way to deal
3300 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003301
3302 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
3303 // another does not. Specifically, the MOVW instruction does not. So we
3304 // special case it here and remove the defaulted (non-setting) cc_out
3305 // operand if that's the instruction we're trying to match.
3306 //
3307 // We do this as post-processing of the explicit operands rather than just
3308 // conditionally adding the cc_out in the first place because we need
3309 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00003310 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003311 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
3312 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
3313 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3314 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003315
3316 // Register-register 'add' for thumb does not have a cc_out operand
3317 // when there are only two register operands.
3318 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
3319 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3320 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3321 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3322 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00003323 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003324 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
3325 // have to check the immediate range here since Thumb2 has a variant
3326 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003327 if (((isThumb() && Mnemonic == "add") ||
3328 (isThumbTwo() && Mnemonic == "sub")) &&
3329 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003330 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3331 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3332 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003333 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3334 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
3335 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00003336 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003337 // For Thumb2, add/sub immediate does not have a cc_out operand for the
3338 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003339 // selecting via the generic "add" mnemonic, so to know that we
3340 // should remove the cc_out operand, we have to explicitly check that
3341 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00003342 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
3343 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003344 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3345 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3346 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3347 // Nest conditions rather than one big 'if' statement for readability.
3348 //
3349 // If either register is a high reg, it's either one of the SP
3350 // variants (handled above) or a 32-bit encoding, so we just
3351 // check against T3.
3352 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3353 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
3354 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
3355 return false;
3356 // If both registers are low, we're in an IT block, and the immediate is
3357 // in range, we should use encoding T1 instead, which has a cc_out.
3358 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00003359 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003360 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
3361 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
3362 return false;
3363
3364 // Otherwise, we use encoding T4, which does not have a cc_out
3365 // operand.
3366 return true;
3367 }
3368
Jim Grosbach64944f42011-09-14 21:00:40 +00003369 // The thumb2 multiply instruction doesn't have a CCOut register, so
3370 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
3371 // use the 16-bit encoding or not.
3372 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
3373 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
3374 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3375 static_cast<ARMOperand*>(Operands[4])->isReg() &&
3376 static_cast<ARMOperand*>(Operands[5])->isReg() &&
3377 // If the registers aren't low regs, the destination reg isn't the
3378 // same as one of the source regs, or the cc_out operand is zero
3379 // outside of an IT block, we have to use the 32-bit encoding, so
3380 // remove the cc_out operand.
3381 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
3382 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
3383 !inITBlock() ||
3384 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
3385 static_cast<ARMOperand*>(Operands[5])->getReg() &&
3386 static_cast<ARMOperand*>(Operands[3])->getReg() !=
3387 static_cast<ARMOperand*>(Operands[4])->getReg())))
3388 return true;
3389
3390
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003391
Jim Grosbachf69c8042011-08-24 21:42:27 +00003392 // Register-register 'add/sub' for thumb does not have a cc_out operand
3393 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
3394 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
3395 // right, this will result in better diagnostics (which operand is off)
3396 // anyway.
3397 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
3398 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00003399 static_cast<ARMOperand*>(Operands[3])->isReg() &&
3400 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
3401 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
3402 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00003403
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003404 return false;
3405}
3406
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003407/// Parse an arm instruction mnemonic followed by its operands.
3408bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
3409 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3410 // Create the leading tokens for the mnemonic, split by '.' characters.
3411 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00003412 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003413
Daniel Dunbar352e1482011-01-11 15:59:50 +00003414 // Split out the predication code and carry setting flag from the mnemonic.
3415 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003416 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003417 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00003418 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003419 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003420 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003421
Jim Grosbach0c49ac02011-08-25 17:23:55 +00003422 // In Thumb1, only the branch (B) instruction can be predicated.
3423 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
3424 Parser.EatToEndOfStatement();
3425 return Error(NameLoc, "conditional execution not supported in Thumb1");
3426 }
3427
Jim Grosbachffa32252011-07-19 19:13:28 +00003428 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
3429
Jim Grosbach89df9962011-08-26 21:43:41 +00003430 // Handle the IT instruction ITMask. Convert it to a bitmask. This
3431 // is the mask as it will be for the IT encoding if the conditional
3432 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
3433 // where the conditional bit0 is zero, the instruction post-processing
3434 // will adjust the mask accordingly.
3435 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003436 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
3437 if (ITMask.size() > 3) {
3438 Parser.EatToEndOfStatement();
3439 return Error(Loc, "too many conditions on IT instruction");
3440 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003441 unsigned Mask = 8;
3442 for (unsigned i = ITMask.size(); i != 0; --i) {
3443 char pos = ITMask[i - 1];
3444 if (pos != 't' && pos != 'e') {
3445 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003446 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00003447 }
3448 Mask >>= 1;
3449 if (ITMask[i - 1] == 't')
3450 Mask |= 8;
3451 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003452 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00003453 }
3454
Jim Grosbachffa32252011-07-19 19:13:28 +00003455 // FIXME: This is all a pretty gross hack. We should automatically handle
3456 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00003457
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003458 // Next, add the CCOut and ConditionCode operands, if needed.
3459 //
3460 // For mnemonics which can ever incorporate a carry setting bit or predication
3461 // code, our matching model involves us always generating CCOut and
3462 // ConditionCode operands to match the mnemonic "as written" and then we let
3463 // the matcher deal with finding the right instruction or generating an
3464 // appropriate error.
3465 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003466 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003467
Jim Grosbach33c16a22011-07-14 22:04:21 +00003468 // If we had a carry-set on an instruction that can't do that, issue an
3469 // error.
3470 if (!CanAcceptCarrySet && CarrySetting) {
3471 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00003472 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00003473 "' can not set flags, but 's' suffix specified");
3474 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003475 // If we had a predication code on an instruction that can't do that, issue an
3476 // error.
3477 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
3478 Parser.EatToEndOfStatement();
3479 return Error(NameLoc, "instruction '" + Mnemonic +
3480 "' is not predicable, but condition code specified");
3481 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00003482
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003483 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003484 if (CanAcceptCarrySet) {
3485 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003486 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003487 Loc));
3488 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003489
3490 // Add the predication code operand, if necessary.
3491 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003492 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
3493 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003494 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003495 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003496 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003497
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003498 // Add the processor imod operand, if necessary.
3499 if (ProcessorIMod) {
3500 Operands.push_back(ARMOperand::CreateImm(
3501 MCConstantExpr::Create(ProcessorIMod, getContext()),
3502 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003503 }
3504
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003505 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00003506 while (Next != StringRef::npos) {
3507 Start = Next;
3508 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003509 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003510
Jim Grosbach4d23e992011-08-24 22:19:48 +00003511 // For now, we're only parsing Thumb1 (for the most part), so
3512 // just ignore ".n" qualifiers. We'll use them to restrict
3513 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00003514 if (ExtraToken != ".n") {
3515 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
3516 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
3517 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00003518 }
3519
3520 // Read the remaining operands.
3521 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003522 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003523 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003524 Parser.EatToEndOfStatement();
3525 return true;
3526 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003527
3528 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00003529 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003530
3531 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003532 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00003533 Parser.EatToEndOfStatement();
3534 return true;
3535 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003536 }
3537 }
Jim Grosbach16c74252010-10-29 14:46:02 +00003538
Chris Lattnercbf8a982010-09-11 16:18:25 +00003539 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3540 Parser.EatToEndOfStatement();
Chris Lattner34e53142010-09-08 05:10:46 +00003541 return TokError("unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00003542 }
Bill Wendling146018f2010-11-06 21:42:12 +00003543
Chris Lattner34e53142010-09-08 05:10:46 +00003544 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00003545
Jim Grosbachd54b4e62011-08-16 21:12:37 +00003546 // Some instructions, mostly Thumb, have forms for the same mnemonic that
3547 // do and don't have a cc_out optional-def operand. With some spot-checks
3548 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00003549 // parse and adjust accordingly before actually matching. We shouldn't ever
3550 // try to remove a cc_out operand that was explicitly set on the the
3551 // mnemonic, of course (CarrySetting == true). Reason number #317 the
3552 // table driven matcher doesn't fit well with the ARM instruction set.
3553 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00003554 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3555 Operands.erase(Operands.begin() + 1);
3556 delete Op;
3557 }
3558
Jim Grosbachcf121c32011-07-28 21:57:55 +00003559 // ARM mode 'blx' need special handling, as the register operand version
3560 // is predicable, but the label operand version is not. So, we can't rely
3561 // on the Mnemonic based checking to correctly figure out when to put
3562 // a CondCode operand in the list. If we're trying to match the label
3563 // version, remove the CondCode operand here.
3564 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
3565 static_cast<ARMOperand*>(Operands[2])->isImm()) {
3566 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
3567 Operands.erase(Operands.begin() + 1);
3568 delete Op;
3569 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00003570
3571 // The vector-compare-to-zero instructions have a literal token "#0" at
3572 // the end that comes to here as an immediate operand. Convert it to a
3573 // token to play nicely with the matcher.
3574 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
3575 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
3576 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3577 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3578 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3579 if (CE && CE->getValue() == 0) {
3580 Operands.erase(Operands.begin() + 5);
3581 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3582 delete Op;
3583 }
3584 }
Jim Grosbach68259142011-10-03 22:30:24 +00003585 // VCMP{E} does the same thing, but with a different operand count.
3586 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
3587 static_cast<ARMOperand*>(Operands[4])->isImm()) {
3588 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
3589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3590 if (CE && CE->getValue() == 0) {
3591 Operands.erase(Operands.begin() + 4);
3592 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3593 delete Op;
3594 }
3595 }
Jim Grosbach934755a2011-08-22 23:47:13 +00003596 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
3597 // end. Convert it to a token here.
3598 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
3599 static_cast<ARMOperand*>(Operands[5])->isImm()) {
3600 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
3601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
3602 if (CE && CE->getValue() == 0) {
3603 Operands.erase(Operands.begin() + 5);
3604 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
3605 delete Op;
3606 }
3607 }
3608
Chris Lattner98986712010-01-14 22:21:20 +00003609 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00003610}
3611
Jim Grosbach189610f2011-07-26 18:25:39 +00003612// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003613
3614// return 'true' if register list contains non-low GPR registers,
3615// 'false' otherwise. If Reg is in the register list or is HiReg, set
3616// 'containsReg' to true.
3617static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
3618 unsigned HiReg, bool &containsReg) {
3619 containsReg = false;
3620 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3621 unsigned OpReg = Inst.getOperand(i).getReg();
3622 if (OpReg == Reg)
3623 containsReg = true;
3624 // Anything other than a low register isn't legal here.
3625 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
3626 return true;
3627 }
3628 return false;
3629}
3630
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003631// Check if the specified regisgter is in the register list of the inst,
3632// starting at the indicated operand number.
3633static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
3634 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
3635 unsigned OpReg = Inst.getOperand(i).getReg();
3636 if (OpReg == Reg)
3637 return true;
3638 }
3639 return false;
3640}
3641
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003642// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
3643// the ARMInsts array) instead. Getting that here requires awkward
3644// API changes, though. Better way?
3645namespace llvm {
3646extern MCInstrDesc ARMInsts[];
3647}
3648static MCInstrDesc &getInstDesc(unsigned Opcode) {
3649 return ARMInsts[Opcode];
3650}
3651
Jim Grosbach189610f2011-07-26 18:25:39 +00003652// FIXME: We would really like to be able to tablegen'erate this.
3653bool ARMAsmParser::
3654validateInstruction(MCInst &Inst,
3655 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003656 MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
3657 SMLoc Loc = Operands[0]->getStartLoc();
3658 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00003659 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
3660 // being allowed in IT blocks, but not being predicable. It just always
3661 // executes.
3662 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003663 unsigned bit = 1;
3664 if (ITState.FirstCond)
3665 ITState.FirstCond = false;
3666 else
Jim Grosbacha1109882011-09-02 23:22:08 +00003667 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003668 // The instruction must be predicable.
3669 if (!MCID.isPredicable())
3670 return Error(Loc, "instructions in IT block must be predicable");
3671 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
3672 unsigned ITCond = bit ? ITState.Cond :
3673 ARMCC::getOppositeCondition(ITState.Cond);
3674 if (Cond != ITCond) {
3675 // Find the condition code Operand to get its SMLoc information.
3676 SMLoc CondLoc;
3677 for (unsigned i = 1; i < Operands.size(); ++i)
3678 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
3679 CondLoc = Operands[i]->getStartLoc();
3680 return Error(CondLoc, "incorrect condition in IT block; got '" +
3681 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
3682 "', but expected '" +
3683 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
3684 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00003685 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003686 } else if (isThumbTwo() && MCID.isPredicable() &&
3687 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00003688 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
3689 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003690 return Error(Loc, "predicated instructions must be in IT block");
3691
Jim Grosbach189610f2011-07-26 18:25:39 +00003692 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003693 case ARM::LDRD:
3694 case ARM::LDRD_PRE:
3695 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003696 case ARM::LDREXD: {
3697 // Rt2 must be Rt + 1.
3698 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3699 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3700 if (Rt2 != Rt + 1)
3701 return Error(Operands[3]->getStartLoc(),
3702 "destination operands must be sequential");
3703 return false;
3704 }
Jim Grosbach14605d12011-08-11 20:28:23 +00003705 case ARM::STRD: {
3706 // Rt2 must be Rt + 1.
3707 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
3708 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3709 if (Rt2 != Rt + 1)
3710 return Error(Operands[3]->getStartLoc(),
3711 "source operands must be sequential");
3712 return false;
3713 }
Jim Grosbach53642c52011-08-10 20:49:18 +00003714 case ARM::STRD_PRE:
3715 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00003716 case ARM::STREXD: {
3717 // Rt2 must be Rt + 1.
3718 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
3719 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
3720 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00003721 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00003722 "source operands must be sequential");
3723 return false;
3724 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00003725 case ARM::SBFX:
3726 case ARM::UBFX: {
3727 // width must be in range [1, 32-lsb]
3728 unsigned lsb = Inst.getOperand(2).getImm();
3729 unsigned widthm1 = Inst.getOperand(3).getImm();
3730 if (widthm1 >= 32 - lsb)
3731 return Error(Operands[5]->getStartLoc(),
3732 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00003733 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00003734 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003735 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003736 // If we're parsing Thumb2, the .w variant is available and handles
3737 // most cases that are normally illegal for a Thumb1 LDM
3738 // instruction. We'll make the transformation in processInstruction()
3739 // if necessary.
3740 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003741 // Thumb LDM instructions are writeback iff the base register is not
3742 // in the register list.
3743 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00003744 bool hasWritebackToken =
3745 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3746 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00003747 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003748 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00003749 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
3750 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003751 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003752 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003753 return Error(Operands[2]->getStartLoc(),
3754 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003755 // If we should not have writeback, there must not be a '!'. This is
3756 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00003757 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00003758 return Error(Operands[3]->getStartLoc(),
3759 "writeback operator '!' not allowed when base register "
3760 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00003761
3762 break;
3763 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003764 case ARM::t2LDMIA_UPD: {
3765 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
3766 return Error(Operands[4]->getStartLoc(),
3767 "writeback operator '!' not allowed when base register "
3768 "in register list");
3769 break;
3770 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00003771 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00003772 bool listContainsBase;
3773 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
3774 return Error(Operands[2]->getStartLoc(),
3775 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00003776 break;
3777 }
3778 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00003779 bool listContainsBase;
3780 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
3781 return Error(Operands[2]->getStartLoc(),
3782 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00003783 break;
3784 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00003785 case ARM::tSTMIA_UPD: {
3786 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00003787 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00003788 return Error(Operands[4]->getStartLoc(),
3789 "registers must be in range r0-r7");
3790 break;
3791 }
Jim Grosbach189610f2011-07-26 18:25:39 +00003792 }
3793
3794 return false;
3795}
3796
Jim Grosbachf8fce712011-08-11 17:35:48 +00003797void ARMAsmParser::
3798processInstruction(MCInst &Inst,
3799 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3800 switch (Inst.getOpcode()) {
3801 case ARM::LDMIA_UPD:
3802 // If this is a load of a single register via a 'pop', then we should use
3803 // a post-indexed LDR instruction instead, per the ARM ARM.
3804 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
3805 Inst.getNumOperands() == 5) {
3806 MCInst TmpInst;
3807 TmpInst.setOpcode(ARM::LDR_POST_IMM);
3808 TmpInst.addOperand(Inst.getOperand(4)); // Rt
3809 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
3810 TmpInst.addOperand(Inst.getOperand(1)); // Rn
3811 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
3812 TmpInst.addOperand(MCOperand::CreateImm(4));
3813 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
3814 TmpInst.addOperand(Inst.getOperand(3));
3815 Inst = TmpInst;
3816 }
3817 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00003818 case ARM::STMDB_UPD:
3819 // If this is a store of a single register via a 'push', then we should use
3820 // a pre-indexed STR instruction instead, per the ARM ARM.
3821 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
3822 Inst.getNumOperands() == 5) {
3823 MCInst TmpInst;
3824 TmpInst.setOpcode(ARM::STR_PRE_IMM);
3825 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
3826 TmpInst.addOperand(Inst.getOperand(4)); // Rt
3827 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
3828 TmpInst.addOperand(MCOperand::CreateImm(-4));
3829 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
3830 TmpInst.addOperand(Inst.getOperand(3));
3831 Inst = TmpInst;
3832 }
3833 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00003834 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00003835 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
3836 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
3837 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
3838 // to encoding T1 if <Rd> is omitted."
3839 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00003840 Inst.setOpcode(ARM::tADDi3);
3841 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00003842 case ARM::tSUBi8:
3843 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
3844 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
3845 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
3846 // to encoding T1 if <Rd> is omitted."
3847 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
3848 Inst.setOpcode(ARM::tSUBi3);
3849 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00003850 case ARM::tB:
3851 // A Thumb conditional branch outside of an IT block is a tBcc.
3852 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
3853 Inst.setOpcode(ARM::tBcc);
3854 break;
3855 case ARM::t2B:
3856 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
3857 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
3858 Inst.setOpcode(ARM::t2Bcc);
3859 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00003860 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00003861 // If the conditional is AL or we're in an IT block, we really want t2B.
3862 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00003863 Inst.setOpcode(ARM::t2B);
3864 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00003865 case ARM::tBcc:
3866 // If the conditional is AL, we really want tB.
3867 if (Inst.getOperand(1).getImm() == ARMCC::AL)
3868 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00003869 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00003870 case ARM::tLDMIA: {
3871 // If the register list contains any high registers, or if the writeback
3872 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
3873 // instead if we're in Thumb2. Otherwise, this should have generated
3874 // an error in validateInstruction().
3875 unsigned Rn = Inst.getOperand(0).getReg();
3876 bool hasWritebackToken =
3877 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
3878 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
3879 bool listContainsBase;
3880 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
3881 (!listContainsBase && !hasWritebackToken) ||
3882 (listContainsBase && hasWritebackToken)) {
3883 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
3884 assert (isThumbTwo());
3885 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
3886 // If we're switching to the updating version, we need to insert
3887 // the writeback tied operand.
3888 if (hasWritebackToken)
3889 Inst.insert(Inst.begin(),
3890 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
3891 }
3892 break;
3893 }
Jim Grosbach8213c962011-09-16 20:50:13 +00003894 case ARM::tSTMIA_UPD: {
3895 // If the register list contains any high registers, we need to use
3896 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
3897 // should have generated an error in validateInstruction().
3898 unsigned Rn = Inst.getOperand(0).getReg();
3899 bool listContainsBase;
3900 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
3901 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
3902 assert (isThumbTwo());
3903 Inst.setOpcode(ARM::t2STMIA_UPD);
3904 }
3905 break;
3906 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003907 case ARM::t2MOVi: {
3908 // If we can use the 16-bit encoding and the user didn't explicitly
3909 // request the 32-bit variant, transform it here.
3910 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
3911 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00003912 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
3913 Inst.getOperand(4).getReg() == ARM::CPSR) ||
3914 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00003915 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
3916 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
3917 // The operands aren't in the same order for tMOVi8...
3918 MCInst TmpInst;
3919 TmpInst.setOpcode(ARM::tMOVi8);
3920 TmpInst.addOperand(Inst.getOperand(0));
3921 TmpInst.addOperand(Inst.getOperand(4));
3922 TmpInst.addOperand(Inst.getOperand(1));
3923 TmpInst.addOperand(Inst.getOperand(2));
3924 TmpInst.addOperand(Inst.getOperand(3));
3925 Inst = TmpInst;
3926 }
3927 break;
3928 }
3929 case ARM::t2MOVr: {
3930 // If we can use the 16-bit encoding and the user didn't explicitly
3931 // request the 32-bit variant, transform it here.
3932 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
3933 isARMLowRegister(Inst.getOperand(1).getReg()) &&
3934 Inst.getOperand(2).getImm() == ARMCC::AL &&
3935 Inst.getOperand(4).getReg() == ARM::CPSR &&
3936 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
3937 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
3938 // The operands aren't the same for tMOV[S]r... (no cc_out)
3939 MCInst TmpInst;
3940 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
3941 TmpInst.addOperand(Inst.getOperand(0));
3942 TmpInst.addOperand(Inst.getOperand(1));
3943 TmpInst.addOperand(Inst.getOperand(2));
3944 TmpInst.addOperand(Inst.getOperand(3));
3945 Inst = TmpInst;
3946 }
3947 break;
3948 }
Jim Grosbach326efe52011-09-19 20:29:33 +00003949 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00003950 case ARM::t2SXTB:
3951 case ARM::t2UXTH:
3952 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00003953 // If we can use the 16-bit encoding and the user didn't explicitly
3954 // request the 32-bit variant, transform it here.
3955 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
3956 isARMLowRegister(Inst.getOperand(1).getReg()) &&
3957 Inst.getOperand(2).getImm() == 0 &&
3958 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
3959 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00003960 unsigned NewOpc;
3961 switch (Inst.getOpcode()) {
3962 default: llvm_unreachable("Illegal opcode!");
3963 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
3964 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
3965 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
3966 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
3967 }
Jim Grosbach326efe52011-09-19 20:29:33 +00003968 // The operands aren't the same for thumb1 (no rotate operand).
3969 MCInst TmpInst;
3970 TmpInst.setOpcode(NewOpc);
3971 TmpInst.addOperand(Inst.getOperand(0));
3972 TmpInst.addOperand(Inst.getOperand(1));
3973 TmpInst.addOperand(Inst.getOperand(3));
3974 TmpInst.addOperand(Inst.getOperand(4));
3975 Inst = TmpInst;
3976 }
3977 break;
3978 }
Jim Grosbach89df9962011-08-26 21:43:41 +00003979 case ARM::t2IT: {
3980 // The mask bits for all but the first condition are represented as
3981 // the low bit of the condition code value implies 't'. We currently
3982 // always have 1 implies 't', so XOR toggle the bits if the low bit
3983 // of the condition code is zero. The encoding also expects the low
3984 // bit of the condition to be encoded as bit 4 of the mask operand,
3985 // so mask that in if needed
3986 MCOperand &MO = Inst.getOperand(1);
3987 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003988 unsigned OrigMask = Mask;
3989 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00003990 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00003991 assert(Mask && TZ <= 3 && "illegal IT mask value!");
3992 for (unsigned i = 3; i != TZ; --i)
3993 Mask ^= 1 << i;
3994 } else
3995 Mask |= 0x10;
3996 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00003997
3998 // Set up the IT block state according to the IT instruction we just
3999 // matched.
4000 assert(!inITBlock() && "nested IT blocks?!");
4001 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4002 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4003 ITState.CurPosition = 0;
4004 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004005 break;
4006 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004007 }
4008}
4009
Jim Grosbach47a0d522011-08-16 20:45:50 +00004010unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4011 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4012 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004013 unsigned Opc = Inst.getOpcode();
4014 MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004015 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4016 assert(MCID.hasOptionalDef() &&
4017 "optionally flag setting instruction missing optional def operand");
4018 assert(MCID.NumOperands == Inst.getNumOperands() &&
4019 "operand count mismatch!");
4020 // Find the optional-def operand (cc_out).
4021 unsigned OpNo;
4022 for (OpNo = 0;
4023 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4024 ++OpNo)
4025 ;
4026 // If we're parsing Thumb1, reject it completely.
4027 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4028 return Match_MnemonicFail;
4029 // If we're parsing Thumb2, which form is legal depends on whether we're
4030 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004031 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4032 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004033 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004034 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4035 inITBlock())
4036 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004037 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004038 // Some high-register supporting Thumb1 encodings only allow both registers
4039 // to be from r0-r7 when in Thumb2.
4040 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4041 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4042 isARMLowRegister(Inst.getOperand(2).getReg()))
4043 return Match_RequiresThumb2;
4044 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004045 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004046 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4047 isARMLowRegister(Inst.getOperand(1).getReg()))
4048 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004049 return Match_Success;
4050}
4051
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004052bool ARMAsmParser::
4053MatchAndEmitInstruction(SMLoc IDLoc,
4054 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4055 MCStreamer &Out) {
4056 MCInst Inst;
4057 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004058 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004059 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004060 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004061 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004062 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004063 // Context sensitive operand constraints aren't handled by the matcher,
4064 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004065 if (validateInstruction(Inst, Operands)) {
4066 // Still progress the IT block, otherwise one wrong condition causes
4067 // nasty cascading errors.
4068 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004069 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004070 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004071
Jim Grosbachf8fce712011-08-11 17:35:48 +00004072 // Some instructions need post-processing to, for example, tweak which
4073 // encoding is selected.
4074 processInstruction(Inst, Operands);
4075
Jim Grosbacha1109882011-09-02 23:22:08 +00004076 // Only move forward at the very end so that everything in validate
4077 // and process gets a consistent answer about whether we're in an IT
4078 // block.
4079 forwardITPosition();
4080
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004081 Out.EmitInstruction(Inst);
4082 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004083 case Match_MissingFeature:
4084 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4085 return true;
4086 case Match_InvalidOperand: {
4087 SMLoc ErrorLoc = IDLoc;
4088 if (ErrorInfo != ~0U) {
4089 if (ErrorInfo >= Operands.size())
4090 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004091
Chris Lattnere73d4f82010-10-28 21:41:58 +00004092 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4093 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4094 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004095
Chris Lattnere73d4f82010-10-28 21:41:58 +00004096 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004097 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004098 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004099 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004100 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004101 // The converter function will have already emited a diagnostic.
4102 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004103 case Match_RequiresNotITBlock:
4104 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004105 case Match_RequiresITBlock:
4106 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004107 case Match_RequiresV6:
4108 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4109 case Match_RequiresThumb2:
4110 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004111 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004112
Eric Christopherc223e2b2010-10-29 09:26:59 +00004113 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004114 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004115}
4116
Jim Grosbach1355cf12011-07-26 17:10:22 +00004117/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004118bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4119 StringRef IDVal = DirectiveID.getIdentifier();
4120 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004121 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004122 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004123 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004124 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004125 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004126 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004127 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004128 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004129 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004130 return true;
4131}
4132
Jim Grosbach1355cf12011-07-26 17:10:22 +00004133/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004134/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004135bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004136 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4137 for (;;) {
4138 const MCExpr *Value;
4139 if (getParser().ParseExpression(Value))
4140 return true;
4141
Chris Lattneraaec2052010-01-19 19:46:13 +00004142 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004143
4144 if (getLexer().is(AsmToken::EndOfStatement))
4145 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004146
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004147 // FIXME: Improve diagnostic.
4148 if (getLexer().isNot(AsmToken::Comma))
4149 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004150 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004151 }
4152 }
4153
Sean Callananb9a25b72010-01-19 20:27:46 +00004154 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004155 return false;
4156}
4157
Jim Grosbach1355cf12011-07-26 17:10:22 +00004158/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004159/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004160bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004161 if (getLexer().isNot(AsmToken::EndOfStatement))
4162 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004163 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004164
4165 // TODO: set thumb mode
4166 // TODO: tell the MC streamer the mode
4167 // getParser().getStreamer().Emit???();
4168 return false;
4169}
4170
Jim Grosbach1355cf12011-07-26 17:10:22 +00004171/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004172/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004173bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004174 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4175 bool isMachO = MAI.hasSubsectionsViaSymbols();
4176 StringRef Name;
4177
4178 // Darwin asm has function name after .thumb_func direction
4179 // ELF doesn't
4180 if (isMachO) {
4181 const AsmToken &Tok = Parser.getTok();
4182 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4183 return Error(L, "unexpected token in .thumb_func directive");
4184 Name = Tok.getString();
4185 Parser.Lex(); // Consume the identifier token.
4186 }
4187
Kevin Enderby515d5092009-10-15 20:48:48 +00004188 if (getLexer().isNot(AsmToken::EndOfStatement))
4189 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004190 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004191
Rafael Espindola64695402011-05-16 16:17:21 +00004192 // FIXME: assuming function name will be the line following .thumb_func
4193 if (!isMachO) {
4194 Name = Parser.getTok().getString();
4195 }
4196
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004197 // Mark symbol as a thumb symbol.
4198 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4199 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004200 return false;
4201}
4202
Jim Grosbach1355cf12011-07-26 17:10:22 +00004203/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004204/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004205bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004206 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004207 if (Tok.isNot(AsmToken::Identifier))
4208 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004209 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004210 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004211 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004212 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004213 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004214 else
4215 return Error(L, "unrecognized syntax mode in .syntax directive");
4216
4217 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004218 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004219 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004220
4221 // TODO tell the MC streamer the mode
4222 // getParser().getStreamer().Emit???();
4223 return false;
4224}
4225
Jim Grosbach1355cf12011-07-26 17:10:22 +00004226/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004227/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004228bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004229 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004230 if (Tok.isNot(AsmToken::Integer))
4231 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004232 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004233 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004234 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004235 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004236 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004237 else
4238 return Error(L, "invalid operand to .code directive");
4239
4240 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004241 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004242 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004243
Evan Cheng32869202011-07-08 22:36:29 +00004244 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00004245 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004246 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004247 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00004248 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00004249 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00004250 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00004251 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00004252 }
Jim Grosbach2a301702010-11-05 22:40:53 +00004253
Kevin Enderby515d5092009-10-15 20:48:48 +00004254 return false;
4255}
4256
Sean Callanan90b70972010-04-07 20:29:34 +00004257extern "C" void LLVMInitializeARMAsmLexer();
4258
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004259/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004260extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00004261 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
4262 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00004263 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004264}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004265
Chris Lattner0692ee62010-09-06 19:11:01 +00004266#define GET_REGISTER_MATCHER
4267#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00004268#include "ARMGenAsmMatcher.inc"