blob: e68ecec301a2fdbc7129b402108f3b6fc3315a82 [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"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Evan Cheng94b95502011-07-26 00:24:13 +000042class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000043 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000044 MCAsmParser &Parser;
45
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000046 struct {
47 ARMCC::CondCodes Cond; // Condition for IT block.
48 unsigned Mask:4; // Condition mask for instructions.
49 // Starting at first 1 (from lsb).
50 // '1' condition as indicated in IT.
51 // '0' inverse of condition (else).
52 // Count of instructions in IT block is
53 // 4 - trailingzeroes(mask)
54
55 bool FirstCond; // Explicit flag for when we're parsing the
56 // First instruction in the IT block. It's
57 // implied in the mask, so needs special
58 // handling.
59
60 unsigned CurPosition; // Current position in parsing of IT
61 // block. In range [0,3]. Initialized
62 // according to count of instructions in block.
63 // ~0U if no active IT block.
64 } ITState;
65 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000066 void forwardITPosition() {
67 if (!inITBlock()) return;
68 // Move to the next instruction in the IT block, if there is one. If not,
69 // mark the block as done.
70 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
71 if (++ITState.CurPosition == 5 - TZ)
72 ITState.CurPosition = ~0U; // Done with the IT block after this.
73 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000074
75
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000076 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000077 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
78
79 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000080 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
81
Jim Grosbach1355cf12011-07-26 17:10:22 +000082 int tryParseRegister();
83 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000084 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000085 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000086 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
88 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000089 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
90 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000091 bool parseDirectiveWord(unsigned Size, SMLoc L);
92 bool parseDirectiveThumb(SMLoc L);
93 bool parseDirectiveThumbFunc(SMLoc L);
94 bool parseDirectiveCode(SMLoc L);
95 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000096
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +000098 bool &CarrySetting, unsigned &ProcessorIMod,
99 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000101 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000102
Evan Chengebdeeab2011-07-08 01:53:10 +0000103 bool isThumb() const {
104 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000105 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000106 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000107 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000108 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000110 bool isThumbTwo() const {
111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
112 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000113 bool hasV6Ops() const {
114 return STI.getFeatureBits() & ARM::HasV6Ops;
115 }
James Molloyacad68d2011-09-28 14:21:38 +0000116 bool hasV7Ops() const {
117 return STI.getFeatureBits() & ARM::HasV7Ops;
118 }
Evan Cheng32869202011-07-08 22:36:29 +0000119 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000120 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
121 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000122 }
James Molloyacad68d2011-09-28 14:21:38 +0000123 bool isMClass() const {
124 return STI.getFeatureBits() & ARM::FeatureMClass;
125 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000126
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000127 /// @name Auto-generated Match Functions
128 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000129
Chris Lattner0692ee62010-09-06 19:11:01 +0000130#define GET_ASSEMBLER_HEADER
131#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000132
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000133 /// }
134
Jim Grosbach89df9962011-08-26 21:43:41 +0000135 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000136 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000137 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000140 OperandMatchResultTy parseCoprocOptionOperand(
141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000142 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000148 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
149 StringRef Op, int Low, int High);
150 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
151 return parsePKHImm(O, "lsl", 0, 31);
152 }
153 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "asr", 1, 32);
155 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000156 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000157 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000158 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000159 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000160 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000161 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000162 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000163 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000164
165 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000166 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
167 const SmallVectorImpl<MCParsedAsmOperand*> &);
168 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
169 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000170 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000172 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000174 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000176 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000178 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000180 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000182 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000184 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
188 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000192 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000194 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000196 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000198 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000200 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
202 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000204 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000208
209 bool validateInstruction(MCInst &Inst,
210 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachf8fce712011-08-11 17:35:48 +0000211 void processInstruction(MCInst &Inst,
212 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000213 bool shouldOmitCCOutOperand(StringRef Mnemonic,
214 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000215
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000216public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000217 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000218 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000219 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000220 Match_RequiresV6,
221 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000222 };
223
Evan Chengffc0e732011-07-09 05:47:46 +0000224 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000225 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000226 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000227
Evan Chengebdeeab2011-07-08 01:53:10 +0000228 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000229 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230
231 // Not in an ITBlock to start with.
232 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000233 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000234
Jim Grosbach1355cf12011-07-26 17:10:22 +0000235 // Implementation of the MCTargetAsmParser interface:
236 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
237 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000238 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000239 bool ParseDirective(AsmToken DirectiveID);
240
Jim Grosbach47a0d522011-08-16 20:45:50 +0000241 unsigned checkTargetMatchPredicate(MCInst &Inst);
242
Jim Grosbach1355cf12011-07-26 17:10:22 +0000243 bool MatchAndEmitInstruction(SMLoc IDLoc,
244 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
245 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000246};
Jim Grosbach16c74252010-10-29 14:46:02 +0000247} // end anonymous namespace
248
Chris Lattner3a697562010-10-28 17:20:03 +0000249namespace {
250
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000251/// ARMOperand - Instances of this class represent a parsed ARM machine
252/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000253class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000254 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000255 k_CondCode,
256 k_CCOut,
257 k_ITCondMask,
258 k_CoprocNum,
259 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000260 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000261 k_Immediate,
262 k_FPImmediate,
263 k_MemBarrierOpt,
264 k_Memory,
265 k_PostIndexRegister,
266 k_MSRMask,
267 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000268 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000269 k_Register,
270 k_RegisterList,
271 k_DPRRegisterList,
272 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000273 k_VectorList,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000274 k_ShiftedRegister,
275 k_ShiftedImmediate,
276 k_ShifterImmediate,
277 k_RotateImmediate,
278 k_BitfieldDescriptor,
279 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000280 } Kind;
281
Sean Callanan76264762010-04-02 22:27:05 +0000282 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000283 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000284
285 union {
286 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000287 ARMCC::CondCodes Val;
288 } CC;
289
290 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000291 unsigned Val;
292 } Cop;
293
294 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000295 unsigned Val;
296 } CoprocOption;
297
298 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000299 unsigned Mask:4;
300 } ITMask;
301
302 struct {
303 ARM_MB::MemBOpt Val;
304 } MBOpt;
305
306 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000307 ARM_PROC::IFlags Val;
308 } IFlags;
309
310 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000311 unsigned Val;
312 } MMask;
313
314 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000315 const char *Data;
316 unsigned Length;
317 } Tok;
318
319 struct {
320 unsigned RegNum;
321 } Reg;
322
Jim Grosbach862019c2011-10-18 23:02:30 +0000323 // A vector register list is a sequential list of 1 to 4 registers.
324 struct {
325 unsigned RegNum;
326 unsigned Count;
327 } VectorList;
328
Bill Wendling8155e5b2010-11-06 22:19:43 +0000329 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000330 unsigned Val;
331 } VectorIndex;
332
333 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000334 const MCExpr *Val;
335 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000336
Jim Grosbach9d390362011-10-03 23:38:36 +0000337 struct {
338 unsigned Val; // encoded 8-bit representation
339 } FPImm;
340
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000341 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000342 struct {
343 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000344 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
345 // was specified.
346 const MCConstantExpr *OffsetImm; // Offset immediate value
347 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
348 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000349 unsigned ShiftImm; // shift for OffsetReg.
350 unsigned Alignment; // 0 = no alignment specified
351 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000352 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000353 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000354
355 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000356 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000357 bool isAdd;
358 ARM_AM::ShiftOpc ShiftTy;
359 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000360 } PostIdxReg;
361
362 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000363 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000364 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000365 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000366 struct {
367 ARM_AM::ShiftOpc ShiftTy;
368 unsigned SrcReg;
369 unsigned ShiftReg;
370 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000371 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000372 struct {
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned SrcReg;
375 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000376 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000377 struct {
378 unsigned Imm;
379 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000380 struct {
381 unsigned LSB;
382 unsigned Width;
383 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000384 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000385
Bill Wendling146018f2010-11-06 21:42:12 +0000386 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
387public:
Sean Callanan76264762010-04-02 22:27:05 +0000388 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
389 Kind = o.Kind;
390 StartLoc = o.StartLoc;
391 EndLoc = o.EndLoc;
392 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000393 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000394 CC = o.CC;
395 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000396 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000397 ITMask = o.ITMask;
398 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000399 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000400 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000401 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000402 case k_CCOut:
403 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000404 Reg = o.Reg;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_RegisterList:
407 case k_DPRRegisterList:
408 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000409 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000410 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000411 case k_VectorList:
412 VectorList = o.VectorList;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_CoprocNum:
415 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000416 Cop = o.Cop;
417 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000418 case k_CoprocOption:
419 CoprocOption = o.CoprocOption;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000422 Imm = o.Imm;
423 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000424 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000425 FPImm = o.FPImm;
426 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000427 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000428 MBOpt = o.MBOpt;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000431 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000434 PostIdxReg = o.PostIdxReg;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000437 MMask = o.MMask;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000440 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000443 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000446 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000449 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000452 RotImm = o.RotImm;
453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000455 Bitfield = o.Bitfield;
456 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000457 case k_VectorIndex:
458 VectorIndex = o.VectorIndex;
459 break;
Sean Callanan76264762010-04-02 22:27:05 +0000460 }
461 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000462
Sean Callanan76264762010-04-02 22:27:05 +0000463 /// getStartLoc - Get the location of the first token of this operand.
464 SMLoc getStartLoc() const { return StartLoc; }
465 /// getEndLoc - Get the location of the last token of this operand.
466 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000467
Daniel Dunbar8462b302010-08-11 06:36:53 +0000468 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000469 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000470 return CC.Val;
471 }
472
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000473 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000474 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000475 return Cop.Val;
476 }
477
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000478 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000479 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000480 return StringRef(Tok.Data, Tok.Length);
481 }
482
483 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000484 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000485 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000486 }
487
Bill Wendling5fa22a12010-11-09 23:28:44 +0000488 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000489 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
490 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000491 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000492 }
493
Kevin Enderbycfe07242009-10-13 22:19:02 +0000494 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000495 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000496 return Imm.Val;
497 }
498
Jim Grosbach9d390362011-10-03 23:38:36 +0000499 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000500 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000501 return FPImm.Val;
502 }
503
Jim Grosbach460a9052011-10-07 23:56:00 +0000504 unsigned getVectorIndex() const {
505 assert(Kind == k_VectorIndex && "Invalid access!");
506 return VectorIndex.Val;
507 }
508
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000509 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000510 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000511 return MBOpt.Val;
512 }
513
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000514 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000515 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000516 return IFlags.Val;
517 }
518
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000519 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000520 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000521 return MMask.Val;
522 }
523
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 bool isCoprocNum() const { return Kind == k_CoprocNum; }
525 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000526 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 bool isCondCode() const { return Kind == k_CondCode; }
528 bool isCCOut() const { return Kind == k_CCOut; }
529 bool isITMask() const { return Kind == k_ITCondMask; }
530 bool isITCondCode() const { return Kind == k_CondCode; }
531 bool isImm() const { return Kind == k_Immediate; }
532 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000533 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000534 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000535 return false;
536 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
537 if (!CE) return false;
538 int64_t Value = CE->getValue();
539 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
540 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000541 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000542 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000543 return false;
544 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
545 if (!CE) return false;
546 int64_t Value = CE->getValue();
547 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
548 }
549 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000550 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000551 return false;
552 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
553 if (!CE) return false;
554 int64_t Value = CE->getValue();
555 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
556 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000557 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000558 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000559 return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return Value >= 0 && Value < 256;
564 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000565 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000566 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000567 return false;
568 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
569 if (!CE) return false;
570 int64_t Value = CE->getValue();
571 return Value >= 0 && Value < 8;
572 }
573 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000574 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000575 return false;
576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
577 if (!CE) return false;
578 int64_t Value = CE->getValue();
579 return Value >= 0 && Value < 16;
580 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000581 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000582 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000583 return false;
584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
585 if (!CE) return false;
586 int64_t Value = CE->getValue();
587 return Value >= 0 && Value < 32;
588 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000589 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000590 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000591 return false;
592 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
593 if (!CE) return false;
594 int64_t Value = CE->getValue();
595 return Value > 0 && Value < 17;
596 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000597 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000598 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000599 return false;
600 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
601 if (!CE) return false;
602 int64_t Value = CE->getValue();
603 return Value > 0 && Value < 33;
604 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000605 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000606 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000607 return false;
608 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609 if (!CE) return false;
610 int64_t Value = CE->getValue();
611 return Value >= 0 && Value < 65536;
612 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000613 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 // If it's not a constant expression, it'll generate a fixup and be
618 // handled later.
619 if (!CE) return true;
620 int64_t Value = CE->getValue();
621 return Value >= 0 && Value < 65536;
622 }
Jim Grosbached838482011-07-26 16:24:27 +0000623 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000624 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000625 return false;
626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
627 if (!CE) return false;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value <= 0xffffff;
630 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000631 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000632 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000633 return false;
634 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
635 if (!CE) return false;
636 int64_t Value = CE->getValue();
637 return Value > 0 && Value < 33;
638 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000639 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000641 return false;
642 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
643 if (!CE) return false;
644 int64_t Value = CE->getValue();
645 return Value >= 0 && Value < 32;
646 }
647 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000648 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000649 return false;
650 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651 if (!CE) return false;
652 int64_t Value = CE->getValue();
653 return Value > 0 && Value <= 32;
654 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000655 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000656 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000657 return false;
658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
659 if (!CE) return false;
660 int64_t Value = CE->getValue();
661 return ARM_AM::getSOImmVal(Value) != -1;
662 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000663 bool isARMSOImmNot() const {
664 if (Kind != k_Immediate)
665 return false;
666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return ARM_AM::getSOImmVal(~Value) != -1;
670 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000671 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000672 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000673 return false;
674 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
675 if (!CE) return false;
676 int64_t Value = CE->getValue();
677 return ARM_AM::getT2SOImmVal(Value) != -1;
678 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000679 bool isT2SOImmNot() const {
680 if (Kind != k_Immediate)
681 return false;
682 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
683 if (!CE) return false;
684 int64_t Value = CE->getValue();
685 return ARM_AM::getT2SOImmVal(~Value) != -1;
686 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000687 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000688 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000689 return false;
690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
691 if (!CE) return false;
692 int64_t Value = CE->getValue();
693 return Value == 1 || Value == 0;
694 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000695 bool isReg() const { return Kind == k_Register; }
696 bool isRegList() const { return Kind == k_RegisterList; }
697 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
698 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
699 bool isToken() const { return Kind == k_Token; }
700 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
701 bool isMemory() const { return Kind == k_Memory; }
702 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
703 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
704 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
705 bool isRotImm() const { return Kind == k_RotateImmediate; }
706 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
707 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000708 bool isPostIdxReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000709 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000710 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000711 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000712 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000713 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000714 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000715 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
716 (alignOK || Memory.Alignment == 0);
717 }
718 bool isAlignedMemory() const {
719 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000720 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000721 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000722 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000723 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000724 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000725 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000726 if (!Memory.OffsetImm) return true;
727 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000728 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000729 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000730 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000731 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000732 return false;
733 // Immediate offset in range [-4095, 4095].
734 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
735 if (!CE) return false;
736 int64_t Val = CE->getValue();
737 return Val > -4096 && Val < 4096;
738 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000739 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000740 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000741 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000742 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000743 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000744 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000745 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000746 if (!Memory.OffsetImm) return true;
747 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000748 return Val > -256 && Val < 256;
749 }
750 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000751 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000752 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000754 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
755 // Immediate offset in range [-255, 255].
756 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
757 if (!CE) return false;
758 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000759 // Special case, #-0 is INT32_MIN.
760 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000761 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000762 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000763 // If we have an immediate that's not a constant, treat it as a label
764 // reference needing a fixup. If it is a constant, it's something else
765 // and we reject it.
766 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
767 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000768 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000769 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000770 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000771 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000772 if (!Memory.OffsetImm) return true;
773 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000774 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000775 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000776 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000777 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000778 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000779 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000780 return false;
781 return true;
782 }
783 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000784 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000785 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
786 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000787 return false;
788 return true;
789 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000790 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000791 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000792 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000793 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000794 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000795 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000796 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
797 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000798 return false;
799 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000800 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000801 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000802 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000803 return false;
804 return true;
805 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000806 bool isMemThumbRR() const {
807 // Thumb reg+reg addressing is simple. Just two registers, a base and
808 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000809 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000810 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000811 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000812 return isARMLowRegister(Memory.BaseRegNum) &&
813 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000814 }
815 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000816 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000817 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000818 return false;
819 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000820 if (!Memory.OffsetImm) return true;
821 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000822 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
823 }
Jim Grosbach38466302011-08-19 18:55:51 +0000824 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000825 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000826 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000827 return false;
828 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000829 if (!Memory.OffsetImm) return true;
830 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000831 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
832 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000833 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000834 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000835 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000836 return false;
837 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000838 if (!Memory.OffsetImm) return true;
839 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000840 return Val >= 0 && Val <= 31;
841 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000842 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000843 if (!isMemory() || Memory.OffsetRegNum != 0 ||
844 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000845 return false;
846 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (!Memory.OffsetImm) return true;
848 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000849 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000850 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000851 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000852 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000853 return false;
854 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000857 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
858 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000859 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000861 return false;
862 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000865 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
866 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000867 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000869 return false;
870 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000873 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000874 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000875 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000877 return false;
878 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000881 return Val >= 0 && Val < 256;
882 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000883 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000885 return false;
886 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000889 return Val > -256 && Val < 0;
890 }
891 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000892 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000893 return false;
894 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000895 if (!Memory.OffsetImm) return true;
896 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000897 return (Val >= 0 && Val < 4096);
898 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000899 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000900 // If we have an immediate that's not a constant, treat it as a label
901 // reference needing a fixup. If it is a constant, it's something else
902 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000903 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000904 return true;
905
Jim Grosbach57dcb852011-10-11 17:29:55 +0000906 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000907 return false;
908 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 if (!Memory.OffsetImm) return true;
910 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000911 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 }
913 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000914 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000915 return false;
916 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
917 if (!CE) return false;
918 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000919 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000920 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000921 bool isPostIdxImm8s4() const {
922 if (Kind != k_Immediate)
923 return false;
924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
925 if (!CE) return false;
926 int64_t Val = CE->getValue();
927 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
928 (Val == INT32_MIN);
929 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000930
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000931 bool isMSRMask() const { return Kind == k_MSRMask; }
932 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000933
Jim Grosbach0e387b22011-10-17 22:26:03 +0000934 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000935 bool isVecListOneD() const {
936 if (Kind != k_VectorList) return false;
937 return VectorList.Count == 1;
938 }
939
Jim Grosbach280dfad2011-10-21 18:54:25 +0000940 bool isVecListTwoD() const {
941 if (Kind != k_VectorList) return false;
942 return VectorList.Count == 2;
943 }
944
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000945 bool isVecListThreeD() const {
946 if (Kind != k_VectorList) return false;
947 return VectorList.Count == 3;
948 }
949
Jim Grosbachb6310312011-10-21 20:35:01 +0000950 bool isVecListFourD() const {
951 if (Kind != k_VectorList) return false;
952 return VectorList.Count == 4;
953 }
954
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000955 bool isVecListTwoQ() const {
956 if (Kind != k_VectorList) return false;
957 //FIXME: We haven't taught the parser to handle by-two register lists
958 // yet, so don't pretend to know one.
959 return VectorList.Count == 2 && false;
960 }
961
Jim Grosbach460a9052011-10-07 23:56:00 +0000962 bool isVectorIndex8() const {
963 if (Kind != k_VectorIndex) return false;
964 return VectorIndex.Val < 8;
965 }
966 bool isVectorIndex16() const {
967 if (Kind != k_VectorIndex) return false;
968 return VectorIndex.Val < 4;
969 }
970 bool isVectorIndex32() const {
971 if (Kind != k_VectorIndex) return false;
972 return VectorIndex.Val < 2;
973 }
974
Jim Grosbach0e387b22011-10-17 22:26:03 +0000975 bool isNEONi8splat() const {
976 if (Kind != k_Immediate)
977 return false;
978 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
979 // Must be a constant.
980 if (!CE) return false;
981 int64_t Value = CE->getValue();
982 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
983 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000984 return Value >= 0 && Value < 256;
985 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000986
Jim Grosbachea461102011-10-17 23:09:09 +0000987 bool isNEONi16splat() const {
988 if (Kind != k_Immediate)
989 return false;
990 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
991 // Must be a constant.
992 if (!CE) return false;
993 int64_t Value = CE->getValue();
994 // i16 value in the range [0,255] or [0x0100, 0xff00]
995 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
996 }
997
Jim Grosbach6248a542011-10-18 00:22:00 +0000998 bool isNEONi32splat() const {
999 if (Kind != k_Immediate)
1000 return false;
1001 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1002 // Must be a constant.
1003 if (!CE) return false;
1004 int64_t Value = CE->getValue();
1005 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1006 return (Value >= 0 && Value < 256) ||
1007 (Value >= 0x0100 && Value <= 0xff00) ||
1008 (Value >= 0x010000 && Value <= 0xff0000) ||
1009 (Value >= 0x01000000 && Value <= 0xff000000);
1010 }
1011
1012 bool isNEONi32vmov() const {
1013 if (Kind != k_Immediate)
1014 return false;
1015 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1016 // Must be a constant.
1017 if (!CE) return false;
1018 int64_t Value = CE->getValue();
1019 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1020 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1021 return (Value >= 0 && Value < 256) ||
1022 (Value >= 0x0100 && Value <= 0xff00) ||
1023 (Value >= 0x010000 && Value <= 0xff0000) ||
1024 (Value >= 0x01000000 && Value <= 0xff000000) ||
1025 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1026 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1027 }
1028
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001029 bool isNEONi64splat() const {
1030 if (Kind != k_Immediate)
1031 return false;
1032 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1033 // Must be a constant.
1034 if (!CE) return false;
1035 uint64_t Value = CE->getValue();
1036 // i64 value with each byte being either 0 or 0xff.
1037 for (unsigned i = 0; i < 8; ++i)
1038 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1039 return true;
1040 }
1041
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001042 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001043 // Add as immediates when possible. Null MCExpr = 0.
1044 if (Expr == 0)
1045 Inst.addOperand(MCOperand::CreateImm(0));
1046 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001047 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1048 else
1049 Inst.addOperand(MCOperand::CreateExpr(Expr));
1050 }
1051
Daniel Dunbar8462b302010-08-11 06:36:53 +00001052 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001053 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001054 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001055 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1056 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001057 }
1058
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001059 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1060 assert(N == 1 && "Invalid number of operands!");
1061 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1062 }
1063
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001064 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1065 assert(N == 1 && "Invalid number of operands!");
1066 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1067 }
1068
1069 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1070 assert(N == 1 && "Invalid number of operands!");
1071 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1072 }
1073
Jim Grosbach89df9962011-08-26 21:43:41 +00001074 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1075 assert(N == 1 && "Invalid number of operands!");
1076 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1077 }
1078
1079 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1080 assert(N == 1 && "Invalid number of operands!");
1081 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1082 }
1083
Jim Grosbachd67641b2010-12-06 18:21:12 +00001084 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1085 assert(N == 1 && "Invalid number of operands!");
1086 Inst.addOperand(MCOperand::CreateReg(getReg()));
1087 }
1088
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001089 void addRegOperands(MCInst &Inst, unsigned N) const {
1090 assert(N == 1 && "Invalid number of operands!");
1091 Inst.addOperand(MCOperand::CreateReg(getReg()));
1092 }
1093
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001094 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001095 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001096 assert(isRegShiftedReg() && "addRegShiftedRegOperands() on non RegShiftedReg!");
1097 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1098 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001099 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001100 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001101 }
1102
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001103 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001104 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001105 assert(isRegShiftedImm() && "addRegShiftedImmOperands() on non RegShiftedImm!");
1106 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001107 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001108 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001109 }
1110
Jim Grosbach580f4a92011-07-25 22:20:28 +00001111 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001112 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001113 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1114 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001115 }
1116
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001117 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001118 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001119 const SmallVectorImpl<unsigned> &RegList = getRegList();
1120 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001121 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1122 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001123 }
1124
Bill Wendling0f630752010-11-17 04:32:08 +00001125 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1126 addRegListOperands(Inst, N);
1127 }
1128
1129 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1130 addRegListOperands(Inst, N);
1131 }
1132
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001133 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1134 assert(N == 1 && "Invalid number of operands!");
1135 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1136 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1137 }
1138
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001139 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1140 assert(N == 1 && "Invalid number of operands!");
1141 // Munge the lsb/width into a bitfield mask.
1142 unsigned lsb = Bitfield.LSB;
1143 unsigned width = Bitfield.Width;
1144 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1145 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1146 (32 - (lsb + width)));
1147 Inst.addOperand(MCOperand::CreateImm(Mask));
1148 }
1149
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001150 void addImmOperands(MCInst &Inst, unsigned N) const {
1151 assert(N == 1 && "Invalid number of operands!");
1152 addExpr(Inst, getImm());
1153 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001154
Jim Grosbach9d390362011-10-03 23:38:36 +00001155 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1156 assert(N == 1 && "Invalid number of operands!");
1157 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1158 }
1159
Jim Grosbacha77295d2011-09-08 22:07:06 +00001160 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 // FIXME: We really want to scale the value here, but the LDRD/STRD
1163 // instruction don't encode operands that way yet.
1164 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1165 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1166 }
1167
Jim Grosbach72f39f82011-08-24 21:22:15 +00001168 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1169 assert(N == 1 && "Invalid number of operands!");
1170 // The immediate is scaled by four in the encoding and is stored
1171 // in the MCInst as such. Lop off the low two bits here.
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1174 }
1175
1176 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 // The immediate is scaled by four in the encoding and is stored
1179 // in the MCInst as such. Lop off the low two bits here.
1180 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1181 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1182 }
1183
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001184 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 addExpr(Inst, getImm());
1187 }
1188
Jim Grosbach83ab0702011-07-13 22:01:08 +00001189 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
1191 addExpr(Inst, getImm());
1192 }
1193
1194 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 addExpr(Inst, getImm());
1197 }
1198
Jim Grosbach7c6e42e2011-07-21 23:26:25 +00001199 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1200 assert(N == 1 && "Invalid number of operands!");
1201 addExpr(Inst, getImm());
1202 }
1203
Jim Grosbachf4943352011-07-25 23:09:14 +00001204 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 // The constant encodes as the immediate-1, and we store in the instruction
1207 // the bits as encoded, so subtract off one here.
1208 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1209 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1210 }
1211
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001212 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
1214 // The constant encodes as the immediate-1, and we store in the instruction
1215 // the bits as encoded, so subtract off one here.
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1218 }
1219
Jim Grosbachfff76ee2011-07-13 20:10:10 +00001220 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
1222 addExpr(Inst, getImm());
1223 }
1224
Jim Grosbachffa32252011-07-19 19:13:28 +00001225 void addImm0_65535ExprOperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
1227 addExpr(Inst, getImm());
1228 }
1229
Jim Grosbached838482011-07-26 16:24:27 +00001230 void addImm24bitOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
1232 addExpr(Inst, getImm());
1233 }
1234
Jim Grosbach70939ee2011-08-17 21:51:27 +00001235 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1236 assert(N == 1 && "Invalid number of operands!");
1237 // The constant encodes as the immediate, except for 32, which encodes as
1238 // zero.
1239 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1240 unsigned Imm = CE->getValue();
1241 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1242 }
1243
Jim Grosbachf6c05252011-07-21 17:23:04 +00001244 void addPKHLSLImmOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 addExpr(Inst, getImm());
1247 }
1248
1249 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
1251 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1252 // the instruction as well.
1253 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1254 int Val = CE->getValue();
1255 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1256 }
1257
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +00001258 void addARMSOImmOperands(MCInst &Inst, unsigned N) const {
1259 assert(N == 1 && "Invalid number of operands!");
1260 addExpr(Inst, getImm());
1261 }
1262
Jim Grosbach6b8f1e32011-06-27 23:54:06 +00001263 void addT2SOImmOperands(MCInst &Inst, unsigned N) const {
1264 assert(N == 1 && "Invalid number of operands!");
1265 addExpr(Inst, getImm());
1266 }
1267
Jim Grosbach89a63372011-10-28 22:36:30 +00001268 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1269 assert(N == 1 && "Invalid number of operands!");
1270 // The operand is actually a t2_so_imm, but we have its bitwise
1271 // negation in the assembly source, so twiddle it here.
1272 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1273 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1274 }
1275
Jim Grosbache70ec842011-10-28 22:50:54 +00001276 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1277 assert(N == 1 && "Invalid number of operands!");
1278 // The operand is actually a so_imm, but we have its bitwise
1279 // negation in the assembly source, so twiddle it here.
1280 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1281 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1282 }
1283
Jim Grosbachc27d4f92011-07-22 17:44:50 +00001284 void addSetEndImmOperands(MCInst &Inst, unsigned N) const {
1285 assert(N == 1 && "Invalid number of operands!");
1286 addExpr(Inst, getImm());
1287 }
1288
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001289 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1290 assert(N == 1 && "Invalid number of operands!");
1291 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1292 }
1293
Jim Grosbach7ce05792011-08-03 23:50:40 +00001294 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1295 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001296 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001297 }
1298
Jim Grosbach57dcb852011-10-11 17:29:55 +00001299 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1300 assert(N == 2 && "Invalid number of operands!");
1301 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1302 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1303 }
1304
Jim Grosbach7ce05792011-08-03 23:50:40 +00001305 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1306 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001307 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1308 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001309 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1310 // Special case for #-0
1311 if (Val == INT32_MIN) Val = 0;
1312 if (Val < 0) Val = -Val;
1313 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1314 } else {
1315 // For register offset, we encode the shift type and negation flag
1316 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001317 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1318 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001319 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001320 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1321 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001322 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001323 }
1324
Jim Grosbach039c2e12011-08-04 23:01:30 +00001325 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1326 assert(N == 2 && "Invalid number of operands!");
1327 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1328 assert(CE && "non-constant AM2OffsetImm operand!");
1329 int32_t Val = CE->getValue();
1330 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1331 // Special case for #-0
1332 if (Val == INT32_MIN) Val = 0;
1333 if (Val < 0) Val = -Val;
1334 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1335 Inst.addOperand(MCOperand::CreateReg(0));
1336 Inst.addOperand(MCOperand::CreateImm(Val));
1337 }
1338
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001339 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1340 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001341 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1342 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001343 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1344 // Special case for #-0
1345 if (Val == INT32_MIN) Val = 0;
1346 if (Val < 0) Val = -Val;
1347 Val = ARM_AM::getAM3Opc(AddSub, Val);
1348 } else {
1349 // For register offset, we encode the shift type and negation flag
1350 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001351 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001352 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001353 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1354 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001355 Inst.addOperand(MCOperand::CreateImm(Val));
1356 }
1357
1358 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1359 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001360 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001361 int32_t Val =
1362 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1363 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1364 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001365 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001366 }
1367
1368 // Constant offset.
1369 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1370 int32_t Val = CE->getValue();
1371 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1372 // Special case for #-0
1373 if (Val == INT32_MIN) Val = 0;
1374 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001375 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001376 Inst.addOperand(MCOperand::CreateReg(0));
1377 Inst.addOperand(MCOperand::CreateImm(Val));
1378 }
1379
Jim Grosbach7ce05792011-08-03 23:50:40 +00001380 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1381 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001382 // If we have an immediate that's not a constant, treat it as a label
1383 // reference needing a fixup. If it is a constant, it's something else
1384 // and we reject it.
1385 if (isImm()) {
1386 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1387 Inst.addOperand(MCOperand::CreateImm(0));
1388 return;
1389 }
1390
Jim Grosbach7ce05792011-08-03 23:50:40 +00001391 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001392 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001393 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1394 // Special case for #-0
1395 if (Val == INT32_MIN) Val = 0;
1396 if (Val < 0) Val = -Val;
1397 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001398 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001399 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001400 }
1401
Jim Grosbacha77295d2011-09-08 22:07:06 +00001402 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001404 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1405 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001406 Inst.addOperand(MCOperand::CreateImm(Val));
1407 }
1408
Jim Grosbachb6aed502011-09-09 18:37:27 +00001409 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 2 && "Invalid number of operands!");
1411 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001412 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1413 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001414 Inst.addOperand(MCOperand::CreateImm(Val));
1415 }
1416
Jim Grosbach7ce05792011-08-03 23:50:40 +00001417 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001419 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1420 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001421 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001422 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001423
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001424 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1425 addMemImm8OffsetOperands(Inst, N);
1426 }
1427
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001428 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001429 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001430 }
1431
1432 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1433 assert(N == 2 && "Invalid number of operands!");
1434 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001435 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001436 addExpr(Inst, getImm());
1437 Inst.addOperand(MCOperand::CreateImm(0));
1438 return;
1439 }
1440
1441 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001442 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1443 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001444 Inst.addOperand(MCOperand::CreateImm(Val));
1445 }
1446
Jim Grosbach7ce05792011-08-03 23:50:40 +00001447 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1448 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001449 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001450 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001451 addExpr(Inst, getImm());
1452 Inst.addOperand(MCOperand::CreateImm(0));
1453 return;
1454 }
1455
1456 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001457 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1458 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001459 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001460 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001461
Jim Grosbach7f739be2011-09-19 22:21:13 +00001462 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1463 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001464 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1465 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001466 }
1467
1468 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1469 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001470 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1471 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001472 }
1473
Jim Grosbach7ce05792011-08-03 23:50:40 +00001474 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1475 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001476 unsigned Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1477 Memory.ShiftImm, Memory.ShiftType);
1478 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1479 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001480 Inst.addOperand(MCOperand::CreateImm(Val));
1481 }
1482
Jim Grosbachab899c12011-09-07 23:10:15 +00001483 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001485 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1486 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1487 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001488 }
1489
Jim Grosbach7ce05792011-08-03 23:50:40 +00001490 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1491 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001492 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1493 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001494 }
1495
Jim Grosbach60f91a32011-08-19 17:55:24 +00001496 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1497 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001498 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1499 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001500 Inst.addOperand(MCOperand::CreateImm(Val));
1501 }
1502
Jim Grosbach38466302011-08-19 18:55:51 +00001503 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001505 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1506 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001507 Inst.addOperand(MCOperand::CreateImm(Val));
1508 }
1509
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001510 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001512 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1513 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001514 Inst.addOperand(MCOperand::CreateImm(Val));
1515 }
1516
Jim Grosbachecd85892011-08-19 18:13:48 +00001517 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1518 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001519 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1520 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001521 Inst.addOperand(MCOperand::CreateImm(Val));
1522 }
1523
Jim Grosbach7ce05792011-08-03 23:50:40 +00001524 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1525 assert(N == 1 && "Invalid number of operands!");
1526 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1527 assert(CE && "non-constant post-idx-imm8 operand!");
1528 int Imm = CE->getValue();
1529 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001530 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001531 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1532 Inst.addOperand(MCOperand::CreateImm(Imm));
1533 }
1534
Jim Grosbach2bd01182011-10-11 21:55:36 +00001535 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1538 assert(CE && "non-constant post-idx-imm8s4 operand!");
1539 int Imm = CE->getValue();
1540 bool isAdd = Imm >= 0;
1541 if (Imm == INT32_MIN) Imm = 0;
1542 // Immediate is scaled by 4.
1543 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1544 Inst.addOperand(MCOperand::CreateImm(Imm));
1545 }
1546
Jim Grosbach7ce05792011-08-03 23:50:40 +00001547 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1548 assert(N == 2 && "Invalid number of operands!");
1549 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001550 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1551 }
1552
1553 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1554 assert(N == 2 && "Invalid number of operands!");
1555 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1556 // The sign, shift type, and shift amount are encoded in a single operand
1557 // using the AM2 encoding helpers.
1558 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1559 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1560 PostIdxReg.ShiftTy);
1561 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001562 }
1563
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001564 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1567 }
1568
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001569 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1570 assert(N == 1 && "Invalid number of operands!");
1571 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1572 }
1573
Jim Grosbach862019c2011-10-18 23:02:30 +00001574 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1575 assert(N == 1 && "Invalid number of operands!");
1576 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1577 }
1578
Jim Grosbach280dfad2011-10-21 18:54:25 +00001579 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1580 assert(N == 1 && "Invalid number of operands!");
1581 // Only the first register actually goes on the instruction. The rest
1582 // are implied by the opcode.
1583 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1584 }
1585
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001586 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 // Only the first register actually goes on the instruction. The rest
1589 // are implied by the opcode.
1590 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1591 }
1592
Jim Grosbachb6310312011-10-21 20:35:01 +00001593 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 1 && "Invalid number of operands!");
1595 // Only the first register actually goes on the instruction. The rest
1596 // are implied by the opcode.
1597 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1598 }
1599
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001600 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1601 assert(N == 1 && "Invalid number of operands!");
1602 // Only the first register actually goes on the instruction. The rest
1603 // are implied by the opcode.
1604 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1605 }
1606
Jim Grosbach460a9052011-10-07 23:56:00 +00001607 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1608 assert(N == 1 && "Invalid number of operands!");
1609 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1610 }
1611
1612 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1615 }
1616
1617 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1618 assert(N == 1 && "Invalid number of operands!");
1619 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1620 }
1621
Jim Grosbach0e387b22011-10-17 22:26:03 +00001622 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 1 && "Invalid number of operands!");
1624 // The immediate encodes the type of constant as well as the value.
1625 // Mask in that this is an i8 splat.
1626 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1627 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1628 }
1629
Jim Grosbachea461102011-10-17 23:09:09 +00001630 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1631 assert(N == 1 && "Invalid number of operands!");
1632 // The immediate encodes the type of constant as well as the value.
1633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1634 unsigned Value = CE->getValue();
1635 if (Value >= 256)
1636 Value = (Value >> 8) | 0xa00;
1637 else
1638 Value |= 0x800;
1639 Inst.addOperand(MCOperand::CreateImm(Value));
1640 }
1641
Jim Grosbach6248a542011-10-18 00:22:00 +00001642 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1643 assert(N == 1 && "Invalid number of operands!");
1644 // The immediate encodes the type of constant as well as the value.
1645 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1646 unsigned Value = CE->getValue();
1647 if (Value >= 256 && Value <= 0xff00)
1648 Value = (Value >> 8) | 0x200;
1649 else if (Value > 0xffff && Value <= 0xff0000)
1650 Value = (Value >> 16) | 0x400;
1651 else if (Value > 0xffffff)
1652 Value = (Value >> 24) | 0x600;
1653 Inst.addOperand(MCOperand::CreateImm(Value));
1654 }
1655
1656 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1657 assert(N == 1 && "Invalid number of operands!");
1658 // The immediate encodes the type of constant as well as the value.
1659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1660 unsigned Value = CE->getValue();
1661 if (Value >= 256 && Value <= 0xffff)
1662 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1663 else if (Value > 0xffff && Value <= 0xffffff)
1664 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1665 else if (Value > 0xffffff)
1666 Value = (Value >> 24) | 0x600;
1667 Inst.addOperand(MCOperand::CreateImm(Value));
1668 }
1669
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001670 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1671 assert(N == 1 && "Invalid number of operands!");
1672 // The immediate encodes the type of constant as well as the value.
1673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1674 uint64_t Value = CE->getValue();
1675 unsigned Imm = 0;
1676 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1677 Imm |= (Value & 1) << i;
1678 }
1679 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1680 }
1681
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001682 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001683
Jim Grosbach89df9962011-08-26 21:43:41 +00001684 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001685 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001686 Op->ITMask.Mask = Mask;
1687 Op->StartLoc = S;
1688 Op->EndLoc = S;
1689 return Op;
1690 }
1691
Chris Lattner3a697562010-10-28 17:20:03 +00001692 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001693 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001694 Op->CC.Val = CC;
1695 Op->StartLoc = S;
1696 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001697 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001698 }
1699
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001700 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001701 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001702 Op->Cop.Val = CopVal;
1703 Op->StartLoc = S;
1704 Op->EndLoc = S;
1705 return Op;
1706 }
1707
1708 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001709 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001710 Op->Cop.Val = CopVal;
1711 Op->StartLoc = S;
1712 Op->EndLoc = S;
1713 return Op;
1714 }
1715
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001716 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1717 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1718 Op->Cop.Val = Val;
1719 Op->StartLoc = S;
1720 Op->EndLoc = E;
1721 return Op;
1722 }
1723
Jim Grosbachd67641b2010-12-06 18:21:12 +00001724 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001725 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001726 Op->Reg.RegNum = RegNum;
1727 Op->StartLoc = S;
1728 Op->EndLoc = S;
1729 return Op;
1730 }
1731
Chris Lattner3a697562010-10-28 17:20:03 +00001732 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001733 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001734 Op->Tok.Data = Str.data();
1735 Op->Tok.Length = Str.size();
1736 Op->StartLoc = S;
1737 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001738 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001739 }
1740
Bill Wendling50d0f582010-11-18 23:43:05 +00001741 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001742 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001743 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001744 Op->StartLoc = S;
1745 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001746 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001747 }
1748
Jim Grosbache8606dc2011-07-13 17:50:29 +00001749 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1750 unsigned SrcReg,
1751 unsigned ShiftReg,
1752 unsigned ShiftImm,
1753 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001754 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001755 Op->RegShiftedReg.ShiftTy = ShTy;
1756 Op->RegShiftedReg.SrcReg = SrcReg;
1757 Op->RegShiftedReg.ShiftReg = ShiftReg;
1758 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001759 Op->StartLoc = S;
1760 Op->EndLoc = E;
1761 return Op;
1762 }
1763
Owen Anderson92a20222011-07-21 18:54:16 +00001764 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1765 unsigned SrcReg,
1766 unsigned ShiftImm,
1767 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001768 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001769 Op->RegShiftedImm.ShiftTy = ShTy;
1770 Op->RegShiftedImm.SrcReg = SrcReg;
1771 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001772 Op->StartLoc = S;
1773 Op->EndLoc = E;
1774 return Op;
1775 }
1776
Jim Grosbach580f4a92011-07-25 22:20:28 +00001777 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001778 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001779 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001780 Op->ShifterImm.isASR = isASR;
1781 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001782 Op->StartLoc = S;
1783 Op->EndLoc = E;
1784 return Op;
1785 }
1786
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001787 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001788 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001789 Op->RotImm.Imm = Imm;
1790 Op->StartLoc = S;
1791 Op->EndLoc = E;
1792 return Op;
1793 }
1794
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001795 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1796 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001797 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001798 Op->Bitfield.LSB = LSB;
1799 Op->Bitfield.Width = Width;
1800 Op->StartLoc = S;
1801 Op->EndLoc = E;
1802 return Op;
1803 }
1804
Bill Wendling7729e062010-11-09 22:44:22 +00001805 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001806 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001807 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001808 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001809
Jim Grosbachd300b942011-09-13 22:56:44 +00001810 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001811 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001812 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001813 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001814 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001815
1816 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001817 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001818 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001819 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001820 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001821 Op->StartLoc = StartLoc;
1822 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001823 return Op;
1824 }
1825
Jim Grosbach862019c2011-10-18 23:02:30 +00001826 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1827 SMLoc S, SMLoc E) {
1828 ARMOperand *Op = new ARMOperand(k_VectorList);
1829 Op->VectorList.RegNum = RegNum;
1830 Op->VectorList.Count = Count;
1831 Op->StartLoc = S;
1832 Op->EndLoc = E;
1833 return Op;
1834 }
1835
Jim Grosbach460a9052011-10-07 23:56:00 +00001836 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1837 MCContext &Ctx) {
1838 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1839 Op->VectorIndex.Val = Idx;
1840 Op->StartLoc = S;
1841 Op->EndLoc = E;
1842 return Op;
1843 }
1844
Chris Lattner3a697562010-10-28 17:20:03 +00001845 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001846 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001847 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001848 Op->StartLoc = S;
1849 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001850 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001851 }
1852
Jim Grosbach9d390362011-10-03 23:38:36 +00001853 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001854 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001855 Op->FPImm.Val = Val;
1856 Op->StartLoc = S;
1857 Op->EndLoc = S;
1858 return Op;
1859 }
1860
Jim Grosbach7ce05792011-08-03 23:50:40 +00001861 static ARMOperand *CreateMem(unsigned BaseRegNum,
1862 const MCConstantExpr *OffsetImm,
1863 unsigned OffsetRegNum,
1864 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001865 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001866 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001867 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001868 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001869 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001870 Op->Memory.BaseRegNum = BaseRegNum;
1871 Op->Memory.OffsetImm = OffsetImm;
1872 Op->Memory.OffsetRegNum = OffsetRegNum;
1873 Op->Memory.ShiftType = ShiftType;
1874 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001875 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001876 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001877 Op->StartLoc = S;
1878 Op->EndLoc = E;
1879 return Op;
1880 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001881
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001882 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1883 ARM_AM::ShiftOpc ShiftTy,
1884 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001885 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001886 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001887 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001888 Op->PostIdxReg.isAdd = isAdd;
1889 Op->PostIdxReg.ShiftTy = ShiftTy;
1890 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001891 Op->StartLoc = S;
1892 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001893 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001894 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001895
1896 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001897 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001898 Op->MBOpt.Val = Opt;
1899 Op->StartLoc = S;
1900 Op->EndLoc = S;
1901 return Op;
1902 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001903
1904 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001905 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001906 Op->IFlags.Val = IFlags;
1907 Op->StartLoc = S;
1908 Op->EndLoc = S;
1909 return Op;
1910 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001911
1912 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001913 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001914 Op->MMask.Val = MMask;
1915 Op->StartLoc = S;
1916 Op->EndLoc = S;
1917 return Op;
1918 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001919};
1920
1921} // end anonymous namespace.
1922
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001923void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001924 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001925 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001926 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1927 << ") >";
1928 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001929 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001930 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001931 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001932 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001933 OS << "<ccout " << getReg() << ">";
1934 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001935 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001936 static const char *MaskStr[] = {
1937 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1938 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1939 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001940 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1941 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1942 break;
1943 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001945 OS << "<coprocessor number: " << getCoproc() << ">";
1946 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001947 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001948 OS << "<coprocessor register: " << getCoproc() << ">";
1949 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001950 case k_CoprocOption:
1951 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1952 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001953 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001954 OS << "<mask: " << getMSRMask() << ">";
1955 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001956 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001957 getImm()->print(OS);
1958 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001960 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1961 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001962 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001963 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001964 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001965 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001966 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001967 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001968 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1969 << PostIdxReg.RegNum;
1970 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1971 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1972 << PostIdxReg.ShiftImm;
1973 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001974 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001975 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001976 OS << "<ARM_PROC::";
1977 unsigned IFlags = getProcIFlags();
1978 for (int i=2; i >= 0; --i)
1979 if (IFlags & (1 << i))
1980 OS << ARM_PROC::IFlagsToString(1 << i);
1981 OS << ">";
1982 break;
1983 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001984 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001985 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001986 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001987 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001988 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1989 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001990 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001991 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001992 OS << "<so_reg_reg "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001993 << RegShiftedReg.SrcReg
1994 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedReg.ShiftImm))
1995 << ", " << RegShiftedReg.ShiftReg << ", "
1996 << ARM_AM::getSORegOffset(RegShiftedReg.ShiftImm)
Jim Grosbache8606dc2011-07-13 17:50:29 +00001997 << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001998 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001999 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002000 OS << "<so_reg_imm "
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002001 << RegShiftedImm.SrcReg
2002 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(RegShiftedImm.ShiftImm))
2003 << ", " << ARM_AM::getSORegOffset(RegShiftedImm.ShiftImm)
Owen Anderson92a20222011-07-21 18:54:16 +00002004 << ">";
2005 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002006 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002007 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2008 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002009 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002010 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2011 << ", width: " << Bitfield.Width << ">";
2012 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002013 case k_RegisterList:
2014 case k_DPRRegisterList:
2015 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002016 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002017
Bill Wendling5fa22a12010-11-09 23:28:44 +00002018 const SmallVectorImpl<unsigned> &RegList = getRegList();
2019 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002020 I = RegList.begin(), E = RegList.end(); I != E; ) {
2021 OS << *I;
2022 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002023 }
2024
2025 OS << ">";
2026 break;
2027 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002028 case k_VectorList:
2029 OS << "<vector_list " << VectorList.Count << " * "
2030 << VectorList.RegNum << ">";
2031 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002032 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002033 OS << "'" << getToken() << "'";
2034 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002035 case k_VectorIndex:
2036 OS << "<vectorindex " << getVectorIndex() << ">";
2037 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002038 }
2039}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002040
2041/// @name Auto-generated Match Functions
2042/// {
2043
2044static unsigned MatchRegisterName(StringRef Name);
2045
2046/// }
2047
Bob Wilson69df7232011-02-03 21:46:10 +00002048bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2049 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002050 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002051
2052 return (RegNo == (unsigned)-1);
2053}
2054
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002055/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002056/// and if it is a register name the token is eaten and the register number is
2057/// returned. Otherwise return -1.
2058///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002059int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002060 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002061 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002062
Chris Lattnere5658fa2010-10-30 04:09:10 +00002063 // FIXME: Validate register for the current architecture; we have to do
2064 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002065 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002066 unsigned RegNum = MatchRegisterName(lowerCase);
2067 if (!RegNum) {
2068 RegNum = StringSwitch<unsigned>(lowerCase)
2069 .Case("r13", ARM::SP)
2070 .Case("r14", ARM::LR)
2071 .Case("r15", ARM::PC)
2072 .Case("ip", ARM::R12)
2073 .Default(0);
2074 }
2075 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002076
Chris Lattnere5658fa2010-10-30 04:09:10 +00002077 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002078
Chris Lattnere5658fa2010-10-30 04:09:10 +00002079 return RegNum;
2080}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002081
Jim Grosbach19906722011-07-13 18:49:30 +00002082// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2083// If a recoverable error occurs, return 1. If an irrecoverable error
2084// occurs, return -1. An irrecoverable error is one where tokens have been
2085// consumed in the process of trying to parse the shifter (i.e., when it is
2086// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002087int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002088 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2089 SMLoc S = Parser.getTok().getLoc();
2090 const AsmToken &Tok = Parser.getTok();
2091 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2092
Benjamin Kramer59085362011-11-06 20:37:06 +00002093 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002094 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2095 .Case("lsl", ARM_AM::lsl)
2096 .Case("lsr", ARM_AM::lsr)
2097 .Case("asr", ARM_AM::asr)
2098 .Case("ror", ARM_AM::ror)
2099 .Case("rrx", ARM_AM::rrx)
2100 .Default(ARM_AM::no_shift);
2101
2102 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002103 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002104
Jim Grosbache8606dc2011-07-13 17:50:29 +00002105 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002106
Jim Grosbache8606dc2011-07-13 17:50:29 +00002107 // The source register for the shift has already been added to the
2108 // operand list, so we need to pop it off and combine it into the shifted
2109 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002110 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002111 if (!PrevOp->isReg())
2112 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2113 int SrcReg = PrevOp->getReg();
2114 int64_t Imm = 0;
2115 int ShiftReg = 0;
2116 if (ShiftTy == ARM_AM::rrx) {
2117 // RRX Doesn't have an explicit shift amount. The encoder expects
2118 // the shift register to be the same as the source register. Seems odd,
2119 // but OK.
2120 ShiftReg = SrcReg;
2121 } else {
2122 // Figure out if this is shifted by a constant or a register (for non-RRX).
2123 if (Parser.getTok().is(AsmToken::Hash)) {
2124 Parser.Lex(); // Eat hash.
2125 SMLoc ImmLoc = Parser.getTok().getLoc();
2126 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002127 if (getParser().ParseExpression(ShiftExpr)) {
2128 Error(ImmLoc, "invalid immediate shift value");
2129 return -1;
2130 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002131 // The expression must be evaluatable as an immediate.
2132 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002133 if (!CE) {
2134 Error(ImmLoc, "invalid immediate shift value");
2135 return -1;
2136 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002137 // Range check the immediate.
2138 // lsl, ror: 0 <= imm <= 31
2139 // lsr, asr: 0 <= imm <= 32
2140 Imm = CE->getValue();
2141 if (Imm < 0 ||
2142 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2143 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002144 Error(ImmLoc, "immediate shift value out of range");
2145 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002146 }
2147 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002148 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002149 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002150 if (ShiftReg == -1) {
2151 Error (L, "expected immediate or register in shift operand");
2152 return -1;
2153 }
2154 } else {
2155 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002156 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002157 return -1;
2158 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002159 }
2160
Owen Anderson92a20222011-07-21 18:54:16 +00002161 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2162 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002163 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002164 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002165 else
2166 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2167 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002168
Jim Grosbach19906722011-07-13 18:49:30 +00002169 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002170}
2171
2172
Bill Wendling50d0f582010-11-18 23:43:05 +00002173/// Try to parse a register name. The token must be an Identifier when called.
2174/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2175/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002176///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002177/// TODO this is likely to change to allow different register types and or to
2178/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002179bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002180tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002181 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002182 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002183 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002184 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002185
Bill Wendling50d0f582010-11-18 23:43:05 +00002186 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002187
Chris Lattnere5658fa2010-10-30 04:09:10 +00002188 const AsmToken &ExclaimTok = Parser.getTok();
2189 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002190 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2191 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002192 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002193 return false;
2194 }
2195
2196 // Also check for an index operand. This is only legal for vector registers,
2197 // but that'll get caught OK in operand matching, so we don't need to
2198 // explicitly filter everything else out here.
2199 if (Parser.getTok().is(AsmToken::LBrac)) {
2200 SMLoc SIdx = Parser.getTok().getLoc();
2201 Parser.Lex(); // Eat left bracket token.
2202
2203 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002204 if (getParser().ParseExpression(ImmVal))
2205 return MatchOperand_ParseFail;
2206 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2207 if (!MCE) {
2208 TokError("immediate value expected for vector index");
2209 return MatchOperand_ParseFail;
2210 }
2211
2212 SMLoc E = Parser.getTok().getLoc();
2213 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2214 Error(E, "']' expected");
2215 return MatchOperand_ParseFail;
2216 }
2217
2218 Parser.Lex(); // Eat right bracket token.
2219
2220 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2221 SIdx, E,
2222 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002223 }
2224
Bill Wendling50d0f582010-11-18 23:43:05 +00002225 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002226}
2227
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002228/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2229/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2230/// "c5", ...
2231static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002232 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2233 // but efficient.
2234 switch (Name.size()) {
2235 default: break;
2236 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002237 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002238 return -1;
2239 switch (Name[1]) {
2240 default: return -1;
2241 case '0': return 0;
2242 case '1': return 1;
2243 case '2': return 2;
2244 case '3': return 3;
2245 case '4': return 4;
2246 case '5': return 5;
2247 case '6': return 6;
2248 case '7': return 7;
2249 case '8': return 8;
2250 case '9': return 9;
2251 }
2252 break;
2253 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002254 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002255 return -1;
2256 switch (Name[2]) {
2257 default: return -1;
2258 case '0': return 10;
2259 case '1': return 11;
2260 case '2': return 12;
2261 case '3': return 13;
2262 case '4': return 14;
2263 case '5': return 15;
2264 }
2265 break;
2266 }
2267
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002268 return -1;
2269}
2270
Jim Grosbach89df9962011-08-26 21:43:41 +00002271/// parseITCondCode - Try to parse a condition code for an IT instruction.
2272ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2273parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2274 SMLoc S = Parser.getTok().getLoc();
2275 const AsmToken &Tok = Parser.getTok();
2276 if (!Tok.is(AsmToken::Identifier))
2277 return MatchOperand_NoMatch;
2278 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2279 .Case("eq", ARMCC::EQ)
2280 .Case("ne", ARMCC::NE)
2281 .Case("hs", ARMCC::HS)
2282 .Case("cs", ARMCC::HS)
2283 .Case("lo", ARMCC::LO)
2284 .Case("cc", ARMCC::LO)
2285 .Case("mi", ARMCC::MI)
2286 .Case("pl", ARMCC::PL)
2287 .Case("vs", ARMCC::VS)
2288 .Case("vc", ARMCC::VC)
2289 .Case("hi", ARMCC::HI)
2290 .Case("ls", ARMCC::LS)
2291 .Case("ge", ARMCC::GE)
2292 .Case("lt", ARMCC::LT)
2293 .Case("gt", ARMCC::GT)
2294 .Case("le", ARMCC::LE)
2295 .Case("al", ARMCC::AL)
2296 .Default(~0U);
2297 if (CC == ~0U)
2298 return MatchOperand_NoMatch;
2299 Parser.Lex(); // Eat the token.
2300
2301 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2302
2303 return MatchOperand_Success;
2304}
2305
Jim Grosbach43904292011-07-25 20:14:50 +00002306/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002307/// token must be an Identifier when called, and if it is a coprocessor
2308/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002309ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002310parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002311 SMLoc S = Parser.getTok().getLoc();
2312 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002313 if (Tok.isNot(AsmToken::Identifier))
2314 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002315
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002316 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002317 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002318 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002319
2320 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002321 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002322 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002323}
2324
Jim Grosbach43904292011-07-25 20:14:50 +00002325/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002326/// token must be an Identifier when called, and if it is a coprocessor
2327/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002328ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002329parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002330 SMLoc S = Parser.getTok().getLoc();
2331 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002332 if (Tok.isNot(AsmToken::Identifier))
2333 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002334
2335 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2336 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002337 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002338
2339 Parser.Lex(); // Eat identifier token.
2340 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002341 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002342}
2343
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002344/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2345/// coproc_option : '{' imm0_255 '}'
2346ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2347parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2348 SMLoc S = Parser.getTok().getLoc();
2349
2350 // If this isn't a '{', this isn't a coprocessor immediate operand.
2351 if (Parser.getTok().isNot(AsmToken::LCurly))
2352 return MatchOperand_NoMatch;
2353 Parser.Lex(); // Eat the '{'
2354
2355 const MCExpr *Expr;
2356 SMLoc Loc = Parser.getTok().getLoc();
2357 if (getParser().ParseExpression(Expr)) {
2358 Error(Loc, "illegal expression");
2359 return MatchOperand_ParseFail;
2360 }
2361 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2362 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2363 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2364 return MatchOperand_ParseFail;
2365 }
2366 int Val = CE->getValue();
2367
2368 // Check for and consume the closing '}'
2369 if (Parser.getTok().isNot(AsmToken::RCurly))
2370 return MatchOperand_ParseFail;
2371 SMLoc E = Parser.getTok().getLoc();
2372 Parser.Lex(); // Eat the '}'
2373
2374 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2375 return MatchOperand_Success;
2376}
2377
Jim Grosbachd0588e22011-09-14 18:08:35 +00002378// For register list parsing, we need to map from raw GPR register numbering
2379// to the enumeration values. The enumeration values aren't sorted by
2380// register number due to our using "sp", "lr" and "pc" as canonical names.
2381static unsigned getNextRegister(unsigned Reg) {
2382 // If this is a GPR, we need to do it manually, otherwise we can rely
2383 // on the sort ordering of the enumeration since the other reg-classes
2384 // are sane.
2385 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2386 return Reg + 1;
2387 switch(Reg) {
2388 default: assert(0 && "Invalid GPR number!");
2389 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2390 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2391 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2392 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2393 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2394 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2395 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2396 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2397 }
2398}
2399
2400/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002401bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002402parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002403 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002404 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002405 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002406 Parser.Lex(); // Eat '{' token.
2407 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002408
Jim Grosbachd0588e22011-09-14 18:08:35 +00002409 // Check the first register in the list to see what register class
2410 // this is a list of.
2411 int Reg = tryParseRegister();
2412 if (Reg == -1)
2413 return Error(RegLoc, "register expected");
2414
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002415 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002416 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2417 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2418 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2419 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2420 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2421 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2422 else
2423 return Error(RegLoc, "invalid register in register list");
2424
2425 // The reglist instructions have at most 16 registers, so reserve
2426 // space for that many.
Jim Grosbachd7a2b3b2011-09-13 20:35:57 +00002427 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002428 // Store the first register.
2429 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002430
Jim Grosbachd0588e22011-09-14 18:08:35 +00002431 // This starts immediately after the first register token in the list,
2432 // so we can see either a comma or a minus (range separator) as a legal
2433 // next token.
2434 while (Parser.getTok().is(AsmToken::Comma) ||
2435 Parser.getTok().is(AsmToken::Minus)) {
2436 if (Parser.getTok().is(AsmToken::Minus)) {
2437 Parser.Lex(); // Eat the comma.
2438 SMLoc EndLoc = Parser.getTok().getLoc();
2439 int EndReg = tryParseRegister();
2440 if (EndReg == -1)
2441 return Error(EndLoc, "register expected");
2442 // If the register is the same as the start reg, there's nothing
2443 // more to do.
2444 if (Reg == EndReg)
2445 continue;
2446 // The register must be in the same register class as the first.
2447 if (!RC->contains(EndReg))
2448 return Error(EndLoc, "invalid register in register list");
2449 // Ranges must go from low to high.
2450 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2451 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002452
Jim Grosbachd0588e22011-09-14 18:08:35 +00002453 // Add all the registers in the range to the register list.
2454 while (Reg != EndReg) {
2455 Reg = getNextRegister(Reg);
2456 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2457 }
2458 continue;
2459 }
2460 Parser.Lex(); // Eat the comma.
2461 RegLoc = Parser.getTok().getLoc();
2462 int OldReg = Reg;
2463 Reg = tryParseRegister();
2464 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002465 return Error(RegLoc, "register expected");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002466 // The register must be in the same register class as the first.
2467 if (!RC->contains(Reg))
2468 return Error(RegLoc, "invalid register in register list");
2469 // List must be monotonically increasing.
2470 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2471 return Error(RegLoc, "register list not in ascending order");
2472 // VFP register lists must also be contiguous.
2473 // It's OK to use the enumeration values directly here rather, as the
2474 // VFP register classes have the enum sorted properly.
2475 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2476 Reg != OldReg + 1)
2477 return Error(RegLoc, "non-contiguous register range");
2478 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002479 }
2480
Jim Grosbachd0588e22011-09-14 18:08:35 +00002481 SMLoc E = Parser.getTok().getLoc();
2482 if (Parser.getTok().isNot(AsmToken::RCurly))
2483 return Error(E, "'}' expected");
2484 Parser.Lex(); // Eat '}' token.
2485
Bill Wendling50d0f582010-11-18 23:43:05 +00002486 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2487 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002488}
2489
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002490// Return the low-subreg of a given Q register.
2491static unsigned getDRegFromQReg(unsigned QReg) {
2492 switch (QReg) {
2493 default: llvm_unreachable("expected a Q register!");
2494 case ARM::Q0: return ARM::D0;
2495 case ARM::Q1: return ARM::D2;
2496 case ARM::Q2: return ARM::D4;
2497 case ARM::Q3: return ARM::D6;
2498 case ARM::Q4: return ARM::D8;
2499 case ARM::Q5: return ARM::D10;
2500 case ARM::Q6: return ARM::D12;
2501 case ARM::Q7: return ARM::D14;
2502 case ARM::Q8: return ARM::D16;
2503 case ARM::Q9: return ARM::D19;
2504 case ARM::Q10: return ARM::D20;
2505 case ARM::Q11: return ARM::D22;
2506 case ARM::Q12: return ARM::D24;
2507 case ARM::Q13: return ARM::D26;
2508 case ARM::Q14: return ARM::D28;
2509 case ARM::Q15: return ARM::D30;
2510 }
2511}
2512
Jim Grosbach862019c2011-10-18 23:02:30 +00002513// parse a vector register list
2514ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2515parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2516 if(Parser.getTok().isNot(AsmToken::LCurly))
2517 return MatchOperand_NoMatch;
2518
2519 SMLoc S = Parser.getTok().getLoc();
2520 Parser.Lex(); // Eat '{' token.
2521 SMLoc RegLoc = Parser.getTok().getLoc();
2522
2523 int Reg = tryParseRegister();
2524 if (Reg == -1) {
2525 Error(RegLoc, "register expected");
2526 return MatchOperand_ParseFail;
2527 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002528 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002529 unsigned FirstReg = Reg;
2530 // The list is of D registers, but we also allow Q regs and just interpret
2531 // them as the two D sub-registers.
2532 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2533 FirstReg = Reg = getDRegFromQReg(Reg);
2534 ++Reg;
2535 ++Count;
2536 }
2537
Jim Grosbach862019c2011-10-18 23:02:30 +00002538 while (Parser.getTok().is(AsmToken::Comma)) {
2539 Parser.Lex(); // Eat the comma.
2540 RegLoc = Parser.getTok().getLoc();
2541 int OldReg = Reg;
2542 Reg = tryParseRegister();
2543 if (Reg == -1) {
2544 Error(RegLoc, "register expected");
2545 return MatchOperand_ParseFail;
2546 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002547 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002548 // It's OK to use the enumeration values directly here rather, as the
2549 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002550 //
2551 // The list is of D registers, but we also allow Q regs and just interpret
2552 // them as the two D sub-registers.
2553 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2554 Reg = getDRegFromQReg(Reg);
2555 if (Reg != OldReg + 1) {
2556 Error(RegLoc, "non-contiguous register range");
2557 return MatchOperand_ParseFail;
2558 }
2559 ++Reg;
2560 Count += 2;
2561 continue;
2562 }
2563 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002564 if (Reg != OldReg + 1) {
2565 Error(RegLoc, "non-contiguous register range");
2566 return MatchOperand_ParseFail;
2567 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002568 ++Count;
2569 }
2570
2571 SMLoc E = Parser.getTok().getLoc();
2572 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2573 Error(E, "'}' expected");
2574 return MatchOperand_ParseFail;
2575 }
2576 Parser.Lex(); // Eat '}' token.
2577
2578 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2579 return MatchOperand_Success;
2580}
2581
Jim Grosbach43904292011-07-25 20:14:50 +00002582/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002583ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002584parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002585 SMLoc S = Parser.getTok().getLoc();
2586 const AsmToken &Tok = Parser.getTok();
2587 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2588 StringRef OptStr = Tok.getString();
2589
2590 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2591 .Case("sy", ARM_MB::SY)
2592 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002593 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002594 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002595 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002596 .Case("ishst", ARM_MB::ISHST)
2597 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002598 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002599 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002600 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002601 .Case("osh", ARM_MB::OSH)
2602 .Case("oshst", ARM_MB::OSHST)
2603 .Default(~0U);
2604
2605 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002606 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002607
2608 Parser.Lex(); // Eat identifier token.
2609 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002610 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002611}
2612
Jim Grosbach43904292011-07-25 20:14:50 +00002613/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002614ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002615parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002616 SMLoc S = Parser.getTok().getLoc();
2617 const AsmToken &Tok = Parser.getTok();
2618 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2619 StringRef IFlagsStr = Tok.getString();
2620
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002621 // An iflags string of "none" is interpreted to mean that none of the AIF
2622 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002623 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002624 if (IFlagsStr != "none") {
2625 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2626 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2627 .Case("a", ARM_PROC::A)
2628 .Case("i", ARM_PROC::I)
2629 .Case("f", ARM_PROC::F)
2630 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002631
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002632 // If some specific iflag is already set, it means that some letter is
2633 // present more than once, this is not acceptable.
2634 if (Flag == ~0U || (IFlags & Flag))
2635 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002636
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002637 IFlags |= Flag;
2638 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002639 }
2640
2641 Parser.Lex(); // Eat identifier token.
2642 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2643 return MatchOperand_Success;
2644}
2645
Jim Grosbach43904292011-07-25 20:14:50 +00002646/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002647ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002648parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002649 SMLoc S = Parser.getTok().getLoc();
2650 const AsmToken &Tok = Parser.getTok();
2651 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2652 StringRef Mask = Tok.getString();
2653
James Molloyacad68d2011-09-28 14:21:38 +00002654 if (isMClass()) {
2655 // See ARMv6-M 10.1.1
2656 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2657 .Case("apsr", 0)
2658 .Case("iapsr", 1)
2659 .Case("eapsr", 2)
2660 .Case("xpsr", 3)
2661 .Case("ipsr", 5)
2662 .Case("epsr", 6)
2663 .Case("iepsr", 7)
2664 .Case("msp", 8)
2665 .Case("psp", 9)
2666 .Case("primask", 16)
2667 .Case("basepri", 17)
2668 .Case("basepri_max", 18)
2669 .Case("faultmask", 19)
2670 .Case("control", 20)
2671 .Default(~0U);
2672
2673 if (FlagsVal == ~0U)
2674 return MatchOperand_NoMatch;
2675
2676 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2677 // basepri, basepri_max and faultmask only valid for V7m.
2678 return MatchOperand_NoMatch;
2679
2680 Parser.Lex(); // Eat identifier token.
2681 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2682 return MatchOperand_Success;
2683 }
2684
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002685 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2686 size_t Start = 0, Next = Mask.find('_');
2687 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002688 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002689 if (Next != StringRef::npos)
2690 Flags = Mask.slice(Next+1, Mask.size());
2691
2692 // FlagsVal contains the complete mask:
2693 // 3-0: Mask
2694 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2695 unsigned FlagsVal = 0;
2696
2697 if (SpecReg == "apsr") {
2698 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002699 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002700 .Case("g", 0x4) // same as CPSR_s
2701 .Case("nzcvqg", 0xc) // same as CPSR_fs
2702 .Default(~0U);
2703
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002704 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002705 if (!Flags.empty())
2706 return MatchOperand_NoMatch;
2707 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002708 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002709 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002710 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002711 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2712 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002713 for (int i = 0, e = Flags.size(); i != e; ++i) {
2714 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2715 .Case("c", 1)
2716 .Case("x", 2)
2717 .Case("s", 4)
2718 .Case("f", 8)
2719 .Default(~0U);
2720
2721 // If some specific flag is already set, it means that some letter is
2722 // present more than once, this is not acceptable.
2723 if (FlagsVal == ~0U || (FlagsVal & Flag))
2724 return MatchOperand_NoMatch;
2725 FlagsVal |= Flag;
2726 }
2727 } else // No match for special register.
2728 return MatchOperand_NoMatch;
2729
Owen Anderson7784f1d2011-10-21 18:43:28 +00002730 // Special register without flags is NOT equivalent to "fc" flags.
2731 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2732 // two lines would enable gas compatibility at the expense of breaking
2733 // round-tripping.
2734 //
2735 // if (!FlagsVal)
2736 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002737
2738 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2739 if (SpecReg == "spsr")
2740 FlagsVal |= 16;
2741
2742 Parser.Lex(); // Eat identifier token.
2743 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2744 return MatchOperand_Success;
2745}
2746
Jim Grosbachf6c05252011-07-21 17:23:04 +00002747ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2748parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2749 int Low, int High) {
2750 const AsmToken &Tok = Parser.getTok();
2751 if (Tok.isNot(AsmToken::Identifier)) {
2752 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2753 return MatchOperand_ParseFail;
2754 }
2755 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002756 std::string LowerOp = Op.lower();
2757 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002758 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2759 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2760 return MatchOperand_ParseFail;
2761 }
2762 Parser.Lex(); // Eat shift type token.
2763
2764 // There must be a '#' and a shift amount.
2765 if (Parser.getTok().isNot(AsmToken::Hash)) {
2766 Error(Parser.getTok().getLoc(), "'#' expected");
2767 return MatchOperand_ParseFail;
2768 }
2769 Parser.Lex(); // Eat hash token.
2770
2771 const MCExpr *ShiftAmount;
2772 SMLoc Loc = Parser.getTok().getLoc();
2773 if (getParser().ParseExpression(ShiftAmount)) {
2774 Error(Loc, "illegal expression");
2775 return MatchOperand_ParseFail;
2776 }
2777 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2778 if (!CE) {
2779 Error(Loc, "constant expression expected");
2780 return MatchOperand_ParseFail;
2781 }
2782 int Val = CE->getValue();
2783 if (Val < Low || Val > High) {
2784 Error(Loc, "immediate value out of range");
2785 return MatchOperand_ParseFail;
2786 }
2787
2788 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2789
2790 return MatchOperand_Success;
2791}
2792
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002793ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2794parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2795 const AsmToken &Tok = Parser.getTok();
2796 SMLoc S = Tok.getLoc();
2797 if (Tok.isNot(AsmToken::Identifier)) {
2798 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2799 return MatchOperand_ParseFail;
2800 }
2801 int Val = StringSwitch<int>(Tok.getString())
2802 .Case("be", 1)
2803 .Case("le", 0)
2804 .Default(-1);
2805 Parser.Lex(); // Eat the token.
2806
2807 if (Val == -1) {
2808 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2809 return MatchOperand_ParseFail;
2810 }
2811 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2812 getContext()),
2813 S, Parser.getTok().getLoc()));
2814 return MatchOperand_Success;
2815}
2816
Jim Grosbach580f4a92011-07-25 22:20:28 +00002817/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2818/// instructions. Legal values are:
2819/// lsl #n 'n' in [0,31]
2820/// asr #n 'n' in [1,32]
2821/// n == 32 encoded as n == 0.
2822ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2823parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2824 const AsmToken &Tok = Parser.getTok();
2825 SMLoc S = Tok.getLoc();
2826 if (Tok.isNot(AsmToken::Identifier)) {
2827 Error(S, "shift operator 'asr' or 'lsl' expected");
2828 return MatchOperand_ParseFail;
2829 }
2830 StringRef ShiftName = Tok.getString();
2831 bool isASR;
2832 if (ShiftName == "lsl" || ShiftName == "LSL")
2833 isASR = false;
2834 else if (ShiftName == "asr" || ShiftName == "ASR")
2835 isASR = true;
2836 else {
2837 Error(S, "shift operator 'asr' or 'lsl' expected");
2838 return MatchOperand_ParseFail;
2839 }
2840 Parser.Lex(); // Eat the operator.
2841
2842 // A '#' and a shift amount.
2843 if (Parser.getTok().isNot(AsmToken::Hash)) {
2844 Error(Parser.getTok().getLoc(), "'#' expected");
2845 return MatchOperand_ParseFail;
2846 }
2847 Parser.Lex(); // Eat hash token.
2848
2849 const MCExpr *ShiftAmount;
2850 SMLoc E = Parser.getTok().getLoc();
2851 if (getParser().ParseExpression(ShiftAmount)) {
2852 Error(E, "malformed shift expression");
2853 return MatchOperand_ParseFail;
2854 }
2855 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2856 if (!CE) {
2857 Error(E, "shift amount must be an immediate");
2858 return MatchOperand_ParseFail;
2859 }
2860
2861 int64_t Val = CE->getValue();
2862 if (isASR) {
2863 // Shift amount must be in [1,32]
2864 if (Val < 1 || Val > 32) {
2865 Error(E, "'asr' shift amount must be in range [1,32]");
2866 return MatchOperand_ParseFail;
2867 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002868 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2869 if (isThumb() && Val == 32) {
2870 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2871 return MatchOperand_ParseFail;
2872 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002873 if (Val == 32) Val = 0;
2874 } else {
2875 // Shift amount must be in [1,32]
2876 if (Val < 0 || Val > 31) {
2877 Error(E, "'lsr' shift amount must be in range [0,31]");
2878 return MatchOperand_ParseFail;
2879 }
2880 }
2881
2882 E = Parser.getTok().getLoc();
2883 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2884
2885 return MatchOperand_Success;
2886}
2887
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002888/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2889/// of instructions. Legal values are:
2890/// ror #n 'n' in {0, 8, 16, 24}
2891ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2892parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2893 const AsmToken &Tok = Parser.getTok();
2894 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002895 if (Tok.isNot(AsmToken::Identifier))
2896 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002897 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002898 if (ShiftName != "ror" && ShiftName != "ROR")
2899 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002900 Parser.Lex(); // Eat the operator.
2901
2902 // A '#' and a rotate amount.
2903 if (Parser.getTok().isNot(AsmToken::Hash)) {
2904 Error(Parser.getTok().getLoc(), "'#' expected");
2905 return MatchOperand_ParseFail;
2906 }
2907 Parser.Lex(); // Eat hash token.
2908
2909 const MCExpr *ShiftAmount;
2910 SMLoc E = Parser.getTok().getLoc();
2911 if (getParser().ParseExpression(ShiftAmount)) {
2912 Error(E, "malformed rotate expression");
2913 return MatchOperand_ParseFail;
2914 }
2915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2916 if (!CE) {
2917 Error(E, "rotate amount must be an immediate");
2918 return MatchOperand_ParseFail;
2919 }
2920
2921 int64_t Val = CE->getValue();
2922 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2923 // normally, zero is represented in asm by omitting the rotate operand
2924 // entirely.
2925 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2926 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2927 return MatchOperand_ParseFail;
2928 }
2929
2930 E = Parser.getTok().getLoc();
2931 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2932
2933 return MatchOperand_Success;
2934}
2935
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002936ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2937parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2938 SMLoc S = Parser.getTok().getLoc();
2939 // The bitfield descriptor is really two operands, the LSB and the width.
2940 if (Parser.getTok().isNot(AsmToken::Hash)) {
2941 Error(Parser.getTok().getLoc(), "'#' expected");
2942 return MatchOperand_ParseFail;
2943 }
2944 Parser.Lex(); // Eat hash token.
2945
2946 const MCExpr *LSBExpr;
2947 SMLoc E = Parser.getTok().getLoc();
2948 if (getParser().ParseExpression(LSBExpr)) {
2949 Error(E, "malformed immediate expression");
2950 return MatchOperand_ParseFail;
2951 }
2952 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2953 if (!CE) {
2954 Error(E, "'lsb' operand must be an immediate");
2955 return MatchOperand_ParseFail;
2956 }
2957
2958 int64_t LSB = CE->getValue();
2959 // The LSB must be in the range [0,31]
2960 if (LSB < 0 || LSB > 31) {
2961 Error(E, "'lsb' operand must be in the range [0,31]");
2962 return MatchOperand_ParseFail;
2963 }
2964 E = Parser.getTok().getLoc();
2965
2966 // Expect another immediate operand.
2967 if (Parser.getTok().isNot(AsmToken::Comma)) {
2968 Error(Parser.getTok().getLoc(), "too few operands");
2969 return MatchOperand_ParseFail;
2970 }
2971 Parser.Lex(); // Eat hash token.
2972 if (Parser.getTok().isNot(AsmToken::Hash)) {
2973 Error(Parser.getTok().getLoc(), "'#' expected");
2974 return MatchOperand_ParseFail;
2975 }
2976 Parser.Lex(); // Eat hash token.
2977
2978 const MCExpr *WidthExpr;
2979 if (getParser().ParseExpression(WidthExpr)) {
2980 Error(E, "malformed immediate expression");
2981 return MatchOperand_ParseFail;
2982 }
2983 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2984 if (!CE) {
2985 Error(E, "'width' operand must be an immediate");
2986 return MatchOperand_ParseFail;
2987 }
2988
2989 int64_t Width = CE->getValue();
2990 // The LSB must be in the range [1,32-lsb]
2991 if (Width < 1 || Width > 32 - LSB) {
2992 Error(E, "'width' operand must be in the range [1,32-lsb]");
2993 return MatchOperand_ParseFail;
2994 }
2995 E = Parser.getTok().getLoc();
2996
2997 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2998
2999 return MatchOperand_Success;
3000}
3001
Jim Grosbach7ce05792011-08-03 23:50:40 +00003002ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3003parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3004 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003005 // postidx_reg := '+' register {, shift}
3006 // | '-' register {, shift}
3007 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003008
3009 // This method must return MatchOperand_NoMatch without consuming any tokens
3010 // in the case where there is no match, as other alternatives take other
3011 // parse methods.
3012 AsmToken Tok = Parser.getTok();
3013 SMLoc S = Tok.getLoc();
3014 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003015 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003016 int Reg = -1;
3017 if (Tok.is(AsmToken::Plus)) {
3018 Parser.Lex(); // Eat the '+' token.
3019 haveEaten = true;
3020 } else if (Tok.is(AsmToken::Minus)) {
3021 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003022 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003023 haveEaten = true;
3024 }
3025 if (Parser.getTok().is(AsmToken::Identifier))
3026 Reg = tryParseRegister();
3027 if (Reg == -1) {
3028 if (!haveEaten)
3029 return MatchOperand_NoMatch;
3030 Error(Parser.getTok().getLoc(), "register expected");
3031 return MatchOperand_ParseFail;
3032 }
3033 SMLoc E = Parser.getTok().getLoc();
3034
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003035 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3036 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003037 if (Parser.getTok().is(AsmToken::Comma)) {
3038 Parser.Lex(); // Eat the ','.
3039 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3040 return MatchOperand_ParseFail;
3041 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003042
3043 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3044 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003045
3046 return MatchOperand_Success;
3047}
3048
Jim Grosbach251bf252011-08-10 21:56:18 +00003049ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3050parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3051 // Check for a post-index addressing register operand. Specifically:
3052 // am3offset := '+' register
3053 // | '-' register
3054 // | register
3055 // | # imm
3056 // | # + imm
3057 // | # - imm
3058
3059 // This method must return MatchOperand_NoMatch without consuming any tokens
3060 // in the case where there is no match, as other alternatives take other
3061 // parse methods.
3062 AsmToken Tok = Parser.getTok();
3063 SMLoc S = Tok.getLoc();
3064
3065 // Do immediates first, as we always parse those if we have a '#'.
3066 if (Parser.getTok().is(AsmToken::Hash)) {
3067 Parser.Lex(); // Eat the '#'.
3068 // Explicitly look for a '-', as we need to encode negative zero
3069 // differently.
3070 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3071 const MCExpr *Offset;
3072 if (getParser().ParseExpression(Offset))
3073 return MatchOperand_ParseFail;
3074 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3075 if (!CE) {
3076 Error(S, "constant expression expected");
3077 return MatchOperand_ParseFail;
3078 }
3079 SMLoc E = Tok.getLoc();
3080 // Negative zero is encoded as the flag value INT32_MIN.
3081 int32_t Val = CE->getValue();
3082 if (isNegative && Val == 0)
3083 Val = INT32_MIN;
3084
3085 Operands.push_back(
3086 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3087
3088 return MatchOperand_Success;
3089 }
3090
3091
3092 bool haveEaten = false;
3093 bool isAdd = true;
3094 int Reg = -1;
3095 if (Tok.is(AsmToken::Plus)) {
3096 Parser.Lex(); // Eat the '+' token.
3097 haveEaten = true;
3098 } else if (Tok.is(AsmToken::Minus)) {
3099 Parser.Lex(); // Eat the '-' token.
3100 isAdd = false;
3101 haveEaten = true;
3102 }
3103 if (Parser.getTok().is(AsmToken::Identifier))
3104 Reg = tryParseRegister();
3105 if (Reg == -1) {
3106 if (!haveEaten)
3107 return MatchOperand_NoMatch;
3108 Error(Parser.getTok().getLoc(), "register expected");
3109 return MatchOperand_ParseFail;
3110 }
3111 SMLoc E = Parser.getTok().getLoc();
3112
3113 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3114 0, S, E));
3115
3116 return MatchOperand_Success;
3117}
3118
Jim Grosbacha77295d2011-09-08 22:07:06 +00003119/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3120/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3121/// when they refer multiple MIOperands inside a single one.
3122bool ARMAsmParser::
3123cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3124 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3125 // Rt, Rt2
3126 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3127 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3128 // Create a writeback register dummy placeholder.
3129 Inst.addOperand(MCOperand::CreateReg(0));
3130 // addr
3131 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3132 // pred
3133 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3134 return true;
3135}
3136
3137/// cvtT2StrdPre - Convert parsed operands to MCInst.
3138/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3139/// when they refer multiple MIOperands inside a single one.
3140bool ARMAsmParser::
3141cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3142 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3143 // Create a writeback register dummy placeholder.
3144 Inst.addOperand(MCOperand::CreateReg(0));
3145 // Rt, Rt2
3146 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3147 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3148 // addr
3149 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3150 // pred
3151 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3152 return true;
3153}
3154
Jim Grosbacheeec0252011-09-08 00:39:19 +00003155/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3156/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3157/// when they refer multiple MIOperands inside a single one.
3158bool ARMAsmParser::
3159cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3160 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3161 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3162
3163 // Create a writeback register dummy placeholder.
3164 Inst.addOperand(MCOperand::CreateImm(0));
3165
3166 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3167 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3168 return true;
3169}
3170
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003171/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3172/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3173/// when they refer multiple MIOperands inside a single one.
3174bool ARMAsmParser::
3175cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3176 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3177 // Create a writeback register dummy placeholder.
3178 Inst.addOperand(MCOperand::CreateImm(0));
3179 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3180 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3181 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3182 return true;
3183}
3184
Jim Grosbach1355cf12011-07-26 17:10:22 +00003185/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003186/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3187/// when they refer multiple MIOperands inside a single one.
3188bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003189cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003190 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3191 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3192
3193 // Create a writeback register dummy placeholder.
3194 Inst.addOperand(MCOperand::CreateImm(0));
3195
Jim Grosbach7ce05792011-08-03 23:50:40 +00003196 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003197 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3198 return true;
3199}
3200
Owen Anderson9ab0f252011-08-26 20:43:14 +00003201/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3202/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3203/// when they refer multiple MIOperands inside a single one.
3204bool ARMAsmParser::
3205cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3206 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3207 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3208
3209 // Create a writeback register dummy placeholder.
3210 Inst.addOperand(MCOperand::CreateImm(0));
3211
3212 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3213 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3214 return true;
3215}
3216
3217
Jim Grosbach548340c2011-08-11 19:22:40 +00003218/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3219/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3220/// when they refer multiple MIOperands inside a single one.
3221bool ARMAsmParser::
3222cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3223 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3224 // Create a writeback register dummy placeholder.
3225 Inst.addOperand(MCOperand::CreateImm(0));
3226 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3227 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3228 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3229 return true;
3230}
3231
Jim Grosbach1355cf12011-07-26 17:10:22 +00003232/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003233/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3234/// when they refer multiple MIOperands inside a single one.
3235bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003236cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003237 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3238 // Create a writeback register dummy placeholder.
3239 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003240 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3241 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3242 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003243 return true;
3244}
3245
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003246/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3247/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3248/// when they refer multiple MIOperands inside a single one.
3249bool ARMAsmParser::
3250cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3251 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3252 // Create a writeback register dummy placeholder.
3253 Inst.addOperand(MCOperand::CreateImm(0));
3254 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3255 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3256 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3257 return true;
3258}
3259
Jim Grosbach7ce05792011-08-03 23:50:40 +00003260/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3261/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3262/// when they refer multiple MIOperands inside a single one.
3263bool ARMAsmParser::
3264cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3265 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3266 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003267 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003268 // Create a writeback register dummy placeholder.
3269 Inst.addOperand(MCOperand::CreateImm(0));
3270 // addr
3271 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3272 // offset
3273 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3274 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003275 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3276 return true;
3277}
3278
Jim Grosbach7ce05792011-08-03 23:50:40 +00003279/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003280/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3281/// when they refer multiple MIOperands inside a single one.
3282bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003283cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3284 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3285 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003286 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003287 // Create a writeback register dummy placeholder.
3288 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003289 // addr
3290 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3291 // offset
3292 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3293 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003294 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3295 return true;
3296}
3297
Jim Grosbach7ce05792011-08-03 23:50:40 +00003298/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003299/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3300/// when they refer multiple MIOperands inside a single one.
3301bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003302cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3303 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003304 // Create a writeback register dummy placeholder.
3305 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003306 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003307 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003308 // addr
3309 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3310 // offset
3311 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3312 // pred
3313 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3314 return true;
3315}
3316
3317/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3318/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3319/// when they refer multiple MIOperands inside a single one.
3320bool ARMAsmParser::
3321cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3322 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3323 // Create a writeback register dummy placeholder.
3324 Inst.addOperand(MCOperand::CreateImm(0));
3325 // Rt
3326 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3327 // addr
3328 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3329 // offset
3330 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3331 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003332 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3333 return true;
3334}
3335
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003336/// cvtLdrdPre - Convert parsed operands to MCInst.
3337/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3338/// when they refer multiple MIOperands inside a single one.
3339bool ARMAsmParser::
3340cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3341 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3342 // Rt, Rt2
3343 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3344 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3345 // Create a writeback register dummy placeholder.
3346 Inst.addOperand(MCOperand::CreateImm(0));
3347 // addr
3348 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3349 // pred
3350 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3351 return true;
3352}
3353
Jim Grosbach14605d12011-08-11 20:28:23 +00003354/// cvtStrdPre - Convert parsed operands to MCInst.
3355/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3356/// when they refer multiple MIOperands inside a single one.
3357bool ARMAsmParser::
3358cvtStrdPre(MCInst &Inst, unsigned Opcode,
3359 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3360 // Create a writeback register dummy placeholder.
3361 Inst.addOperand(MCOperand::CreateImm(0));
3362 // Rt, Rt2
3363 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3364 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3365 // addr
3366 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3367 // pred
3368 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3369 return true;
3370}
3371
Jim Grosbach623a4542011-08-10 22:42:16 +00003372/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3373/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3374/// when they refer multiple MIOperands inside a single one.
3375bool ARMAsmParser::
3376cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3377 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3378 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3379 // Create a writeback register dummy placeholder.
3380 Inst.addOperand(MCOperand::CreateImm(0));
3381 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3382 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3383 return true;
3384}
3385
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003386/// cvtThumbMultiple- Convert parsed operands to MCInst.
3387/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3388/// when they refer multiple MIOperands inside a single one.
3389bool ARMAsmParser::
3390cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3391 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3392 // The second source operand must be the same register as the destination
3393 // operand.
3394 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003395 (((ARMOperand*)Operands[3])->getReg() !=
3396 ((ARMOperand*)Operands[5])->getReg()) &&
3397 (((ARMOperand*)Operands[3])->getReg() !=
3398 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003399 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003400 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003401 return false;
3402 }
3403 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3404 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
3405 ((ARMOperand*)Operands[4])->addRegOperands(Inst, 1);
Jim Grosbach7a010692011-08-19 22:30:46 +00003406 // If we have a three-operand form, use that, else the second source operand
3407 // is just the destination operand again.
3408 if (Operands.size() == 6)
3409 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3410 else
3411 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003412 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3413
3414 return true;
3415}
Jim Grosbach623a4542011-08-10 22:42:16 +00003416
Jim Grosbach12431322011-10-24 22:16:58 +00003417bool ARMAsmParser::
3418cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3419 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3420 // Vd
3421 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3422 // Create a writeback register dummy placeholder.
3423 Inst.addOperand(MCOperand::CreateImm(0));
3424 // Vn
3425 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3426 // pred
3427 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3428 return true;
3429}
3430
3431bool ARMAsmParser::
3432cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3433 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3434 // Vd
3435 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3436 // Create a writeback register dummy placeholder.
3437 Inst.addOperand(MCOperand::CreateImm(0));
3438 // Vn
3439 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3440 // Vm
3441 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3442 // pred
3443 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3444 return true;
3445}
3446
Jim Grosbach4334e032011-10-31 21:50:31 +00003447bool ARMAsmParser::
3448cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3449 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3450 // Create a writeback register dummy placeholder.
3451 Inst.addOperand(MCOperand::CreateImm(0));
3452 // Vn
3453 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3454 // Vt
3455 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3456 // pred
3457 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3458 return true;
3459}
3460
3461bool ARMAsmParser::
3462cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3463 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3464 // Create a writeback register dummy placeholder.
3465 Inst.addOperand(MCOperand::CreateImm(0));
3466 // Vn
3467 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3468 // Vm
3469 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3470 // Vt
3471 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3472 // pred
3473 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3474 return true;
3475}
3476
Bill Wendlinge7176102010-11-06 22:36:58 +00003477/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003478/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003479bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003480parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003481 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003482 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003483 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003484 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003485 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003486
Sean Callanan18b83232010-01-19 21:44:56 +00003487 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003488 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003489 if (BaseRegNum == -1)
3490 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003491
Daniel Dunbar05710932011-01-18 05:34:17 +00003492 // The next token must either be a comma or a closing bracket.
3493 const AsmToken &Tok = Parser.getTok();
3494 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003495 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003496
Jim Grosbach7ce05792011-08-03 23:50:40 +00003497 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003498 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003499 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003500
Jim Grosbach7ce05792011-08-03 23:50:40 +00003501 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003502 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003503
Jim Grosbachfb12f352011-09-19 18:42:21 +00003504 // If there's a pre-indexing writeback marker, '!', just add it as a token
3505 // operand. It's rather odd, but syntactically valid.
3506 if (Parser.getTok().is(AsmToken::Exclaim)) {
3507 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3508 Parser.Lex(); // Eat the '!'.
3509 }
3510
Jim Grosbach7ce05792011-08-03 23:50:40 +00003511 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003512 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003513
Jim Grosbach7ce05792011-08-03 23:50:40 +00003514 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3515 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003516
Jim Grosbach57dcb852011-10-11 17:29:55 +00003517 // If we have a ':', it's an alignment specifier.
3518 if (Parser.getTok().is(AsmToken::Colon)) {
3519 Parser.Lex(); // Eat the ':'.
3520 E = Parser.getTok().getLoc();
3521
3522 const MCExpr *Expr;
3523 if (getParser().ParseExpression(Expr))
3524 return true;
3525
3526 // The expression has to be a constant. Memory references with relocations
3527 // don't come through here, as they use the <label> forms of the relevant
3528 // instructions.
3529 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3530 if (!CE)
3531 return Error (E, "constant expression expected");
3532
3533 unsigned Align = 0;
3534 switch (CE->getValue()) {
3535 default:
3536 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3537 case 64: Align = 8; break;
3538 case 128: Align = 16; break;
3539 case 256: Align = 32; break;
3540 }
3541
3542 // Now we should have the closing ']'
3543 E = Parser.getTok().getLoc();
3544 if (Parser.getTok().isNot(AsmToken::RBrac))
3545 return Error(E, "']' expected");
3546 Parser.Lex(); // Eat right bracket token.
3547
3548 // Don't worry about range checking the value here. That's handled by
3549 // the is*() predicates.
3550 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3551 ARM_AM::no_shift, 0, Align,
3552 false, S, E));
3553
3554 // If there's a pre-indexing writeback marker, '!', just add it as a token
3555 // operand.
3556 if (Parser.getTok().is(AsmToken::Exclaim)) {
3557 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3558 Parser.Lex(); // Eat the '!'.
3559 }
3560
3561 return false;
3562 }
3563
3564 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach7ce05792011-08-03 23:50:40 +00003565 // offset.
3566 if (Parser.getTok().is(AsmToken::Hash)) {
3567 Parser.Lex(); // Eat the '#'.
3568 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003569
Owen Anderson0da10cf2011-08-29 19:36:44 +00003570 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003571 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003572 if (getParser().ParseExpression(Offset))
3573 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003574
3575 // The expression has to be a constant. Memory references with relocations
3576 // don't come through here, as they use the <label> forms of the relevant
3577 // instructions.
3578 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3579 if (!CE)
3580 return Error (E, "constant expression expected");
3581
Owen Anderson0da10cf2011-08-29 19:36:44 +00003582 // If the constant was #-0, represent it as INT32_MIN.
3583 int32_t Val = CE->getValue();
3584 if (isNegative && Val == 0)
3585 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3586
Jim Grosbach7ce05792011-08-03 23:50:40 +00003587 // Now we should have the closing ']'
3588 E = Parser.getTok().getLoc();
3589 if (Parser.getTok().isNot(AsmToken::RBrac))
3590 return Error(E, "']' expected");
3591 Parser.Lex(); // Eat right bracket token.
3592
3593 // Don't worry about range checking the value here. That's handled by
3594 // the is*() predicates.
3595 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003596 ARM_AM::no_shift, 0, 0,
3597 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003598
3599 // If there's a pre-indexing writeback marker, '!', just add it as a token
3600 // operand.
3601 if (Parser.getTok().is(AsmToken::Exclaim)) {
3602 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3603 Parser.Lex(); // Eat the '!'.
3604 }
3605
3606 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003607 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003608
3609 // The register offset is optionally preceded by a '+' or '-'
3610 bool isNegative = false;
3611 if (Parser.getTok().is(AsmToken::Minus)) {
3612 isNegative = true;
3613 Parser.Lex(); // Eat the '-'.
3614 } else if (Parser.getTok().is(AsmToken::Plus)) {
3615 // Nothing to do.
3616 Parser.Lex(); // Eat the '+'.
3617 }
3618
3619 E = Parser.getTok().getLoc();
3620 int OffsetRegNum = tryParseRegister();
3621 if (OffsetRegNum == -1)
3622 return Error(E, "register expected");
3623
3624 // If there's a shift operator, handle it.
3625 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003626 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003627 if (Parser.getTok().is(AsmToken::Comma)) {
3628 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003629 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003630 return true;
3631 }
3632
3633 // Now we should have the closing ']'
3634 E = Parser.getTok().getLoc();
3635 if (Parser.getTok().isNot(AsmToken::RBrac))
3636 return Error(E, "']' expected");
3637 Parser.Lex(); // Eat right bracket token.
3638
3639 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003640 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003641 S, E));
3642
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003643 // If there's a pre-indexing writeback marker, '!', just add it as a token
3644 // operand.
3645 if (Parser.getTok().is(AsmToken::Exclaim)) {
3646 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3647 Parser.Lex(); // Eat the '!'.
3648 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003649
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003650 return false;
3651}
3652
Jim Grosbach7ce05792011-08-03 23:50:40 +00003653/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003654/// ( lsl | lsr | asr | ror ) , # shift_amount
3655/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003656/// return true if it parses a shift otherwise it returns false.
3657bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3658 unsigned &Amount) {
3659 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003660 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003661 if (Tok.isNot(AsmToken::Identifier))
3662 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003663 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003664 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003665 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003666 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003667 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003668 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003669 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003670 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003671 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003672 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003673 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003674 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003675 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003676 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003677
Jim Grosbach7ce05792011-08-03 23:50:40 +00003678 // rrx stands alone.
3679 Amount = 0;
3680 if (St != ARM_AM::rrx) {
3681 Loc = Parser.getTok().getLoc();
3682 // A '#' and a shift amount.
3683 const AsmToken &HashTok = Parser.getTok();
3684 if (HashTok.isNot(AsmToken::Hash))
3685 return Error(HashTok.getLoc(), "'#' expected");
3686 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003687
Jim Grosbach7ce05792011-08-03 23:50:40 +00003688 const MCExpr *Expr;
3689 if (getParser().ParseExpression(Expr))
3690 return true;
3691 // Range check the immediate.
3692 // lsl, ror: 0 <= imm <= 31
3693 // lsr, asr: 0 <= imm <= 32
3694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3695 if (!CE)
3696 return Error(Loc, "shift amount must be an immediate");
3697 int64_t Imm = CE->getValue();
3698 if (Imm < 0 ||
3699 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3700 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3701 return Error(Loc, "immediate shift value out of range");
3702 Amount = Imm;
3703 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003704
3705 return false;
3706}
3707
Jim Grosbach9d390362011-10-03 23:38:36 +00003708/// parseFPImm - A floating point immediate expression operand.
3709ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3710parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3711 SMLoc S = Parser.getTok().getLoc();
3712
3713 if (Parser.getTok().isNot(AsmToken::Hash))
3714 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003715
3716 // Disambiguate the VMOV forms that can accept an FP immediate.
3717 // vmov.f32 <sreg>, #imm
3718 // vmov.f64 <dreg>, #imm
3719 // vmov.f32 <dreg>, #imm @ vector f32x2
3720 // vmov.f32 <qreg>, #imm @ vector f32x4
3721 //
3722 // There are also the NEON VMOV instructions which expect an
3723 // integer constant. Make sure we don't try to parse an FPImm
3724 // for these:
3725 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3726 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3727 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3728 TyOp->getToken() != ".f64"))
3729 return MatchOperand_NoMatch;
3730
Jim Grosbach9d390362011-10-03 23:38:36 +00003731 Parser.Lex(); // Eat the '#'.
3732
3733 // Handle negation, as that still comes through as a separate token.
3734 bool isNegative = false;
3735 if (Parser.getTok().is(AsmToken::Minus)) {
3736 isNegative = true;
3737 Parser.Lex();
3738 }
3739 const AsmToken &Tok = Parser.getTok();
3740 if (Tok.is(AsmToken::Real)) {
3741 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3742 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3743 // If we had a '-' in front, toggle the sign bit.
3744 IntVal ^= (uint64_t)isNegative << 63;
3745 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3746 Parser.Lex(); // Eat the token.
3747 if (Val == -1) {
3748 TokError("floating point value out of range");
3749 return MatchOperand_ParseFail;
3750 }
3751 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3752 return MatchOperand_Success;
3753 }
3754 if (Tok.is(AsmToken::Integer)) {
3755 int64_t Val = Tok.getIntVal();
3756 Parser.Lex(); // Eat the token.
3757 if (Val > 255 || Val < 0) {
3758 TokError("encoded floating point value out of range");
3759 return MatchOperand_ParseFail;
3760 }
3761 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3762 return MatchOperand_Success;
3763 }
3764
3765 TokError("invalid floating point immediate");
3766 return MatchOperand_ParseFail;
3767}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003768/// Parse a arm instruction operand. For now this parses the operand regardless
3769/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003770bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003771 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003772 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003773
3774 // Check if the current operand has a custom associated parser, if so, try to
3775 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003776 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3777 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003778 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003779 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3780 // there was a match, but an error occurred, in which case, just return that
3781 // the operand parsing failed.
3782 if (ResTy == MatchOperand_ParseFail)
3783 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003784
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003785 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003786 default:
3787 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003788 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003789 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003790 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003791 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003792 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003793 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003794 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003795 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003796 else if (Res == -1) // irrecoverable error
3797 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003798 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3799 S = Parser.getTok().getLoc();
3800 Parser.Lex();
3801 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3802 return false;
3803 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003804
3805 // Fall though for the Identifier case that is not a register or a
3806 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003807 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003808 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003809 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003810 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003811 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003812 // This was not a register so parse other operands that start with an
3813 // identifier (like labels) as expressions and create them as immediates.
3814 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003815 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003816 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003817 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003818 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003819 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3820 return false;
3821 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003822 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003823 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003824 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003825 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003826 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003827 // #42 -> immediate.
3828 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003829 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003830 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003831 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003832 const MCExpr *ImmVal;
3833 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003834 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003836 if (CE) {
3837 int32_t Val = CE->getValue();
3838 if (isNegative && Val == 0)
3839 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003840 }
Sean Callanan76264762010-04-02 22:27:05 +00003841 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003842 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3843 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003844 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003845 case AsmToken::Colon: {
3846 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003847 // FIXME: Check it's an expression prefix,
3848 // e.g. (FOO - :lower16:BAR) isn't legal.
3849 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003850 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003851 return true;
3852
Evan Cheng75972122011-01-13 07:58:56 +00003853 const MCExpr *SubExprVal;
3854 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003855 return true;
3856
Evan Cheng75972122011-01-13 07:58:56 +00003857 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3858 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003859 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003860 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003861 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003862 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003863 }
3864}
3865
Jim Grosbach1355cf12011-07-26 17:10:22 +00003866// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003867// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003868bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003869 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003870
3871 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003872 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003873 Parser.Lex(); // Eat ':'
3874
3875 if (getLexer().isNot(AsmToken::Identifier)) {
3876 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3877 return true;
3878 }
3879
3880 StringRef IDVal = Parser.getTok().getIdentifier();
3881 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003882 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003883 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003884 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003885 } else {
3886 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3887 return true;
3888 }
3889 Parser.Lex();
3890
3891 if (getLexer().isNot(AsmToken::Colon)) {
3892 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3893 return true;
3894 }
3895 Parser.Lex(); // Eat the last ':'
3896 return false;
3897}
3898
Daniel Dunbar352e1482011-01-11 15:59:50 +00003899/// \brief Given a mnemonic, split out possible predication code and carry
3900/// setting letters to form a canonical mnemonic and flags.
3901//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003902// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003903// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003904StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003905 unsigned &PredicationCode,
3906 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003907 unsigned &ProcessorIMod,
3908 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003909 PredicationCode = ARMCC::AL;
3910 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003911 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003912
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003913 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003914 //
3915 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003916 if ((Mnemonic == "movs" && isThumb()) ||
3917 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3918 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3919 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3920 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3921 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3922 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3923 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003924 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003925
Jim Grosbach3f00e312011-07-11 17:09:57 +00003926 // First, split out any predication code. Ignore mnemonics we know aren't
3927 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003928 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003929 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003930 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003931 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003932 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3933 .Case("eq", ARMCC::EQ)
3934 .Case("ne", ARMCC::NE)
3935 .Case("hs", ARMCC::HS)
3936 .Case("cs", ARMCC::HS)
3937 .Case("lo", ARMCC::LO)
3938 .Case("cc", ARMCC::LO)
3939 .Case("mi", ARMCC::MI)
3940 .Case("pl", ARMCC::PL)
3941 .Case("vs", ARMCC::VS)
3942 .Case("vc", ARMCC::VC)
3943 .Case("hi", ARMCC::HI)
3944 .Case("ls", ARMCC::LS)
3945 .Case("ge", ARMCC::GE)
3946 .Case("lt", ARMCC::LT)
3947 .Case("gt", ARMCC::GT)
3948 .Case("le", ARMCC::LE)
3949 .Case("al", ARMCC::AL)
3950 .Default(~0U);
3951 if (CC != ~0U) {
3952 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3953 PredicationCode = CC;
3954 }
Bill Wendling52925b62010-10-29 23:50:21 +00003955 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003956
Daniel Dunbar352e1482011-01-11 15:59:50 +00003957 // Next, determine if we have a carry setting bit. We explicitly ignore all
3958 // the instructions we know end in 's'.
3959 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003960 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003961 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3962 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3963 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003964 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3965 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003966 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3967 CarrySetting = true;
3968 }
3969
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003970 // The "cps" instruction can have a interrupt mode operand which is glued into
3971 // the mnemonic. Check if this is the case, split it and parse the imod op
3972 if (Mnemonic.startswith("cps")) {
3973 // Split out any imod code.
3974 unsigned IMod =
3975 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3976 .Case("ie", ARM_PROC::IE)
3977 .Case("id", ARM_PROC::ID)
3978 .Default(~0U);
3979 if (IMod != ~0U) {
3980 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3981 ProcessorIMod = IMod;
3982 }
3983 }
3984
Jim Grosbach89df9962011-08-26 21:43:41 +00003985 // The "it" instruction has the condition mask on the end of the mnemonic.
3986 if (Mnemonic.startswith("it")) {
3987 ITMask = Mnemonic.slice(2, Mnemonic.size());
3988 Mnemonic = Mnemonic.slice(0, 2);
3989 }
3990
Daniel Dunbar352e1482011-01-11 15:59:50 +00003991 return Mnemonic;
3992}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003993
3994/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3995/// inclusion of carry set or predication code operands.
3996//
3997// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003998void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003999getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004000 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004001 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4002 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004003 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004004 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004005 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004006 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004007 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004008 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004009 Mnemonic == "mla" || Mnemonic == "smlal" ||
4010 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004011 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004012 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004013 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004014
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004015 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4016 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4017 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4018 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004019 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4020 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004021 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004022 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4023 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4024 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004025 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4026 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004027 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004028 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004029 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004030 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004031
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004032 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004033 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004034 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004035 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004036 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004037}
4038
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004039bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4040 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004041 // FIXME: This is all horribly hacky. We really need a better way to deal
4042 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004043
4044 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4045 // another does not. Specifically, the MOVW instruction does not. So we
4046 // special case it here and remove the defaulted (non-setting) cc_out
4047 // operand if that's the instruction we're trying to match.
4048 //
4049 // We do this as post-processing of the explicit operands rather than just
4050 // conditionally adding the cc_out in the first place because we need
4051 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004052 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004053 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4054 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4055 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4056 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004057
4058 // Register-register 'add' for thumb does not have a cc_out operand
4059 // when there are only two register operands.
4060 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4061 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4062 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4063 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4064 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004065 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004066 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4067 // have to check the immediate range here since Thumb2 has a variant
4068 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004069 if (((isThumb() && Mnemonic == "add") ||
4070 (isThumbTwo() && Mnemonic == "sub")) &&
4071 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004072 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4073 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4074 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004075 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4076 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4077 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004078 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004079 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4080 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004081 // selecting via the generic "add" mnemonic, so to know that we
4082 // should remove the cc_out operand, we have to explicitly check that
4083 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004084 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4085 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004086 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4087 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4088 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4089 // Nest conditions rather than one big 'if' statement for readability.
4090 //
4091 // If either register is a high reg, it's either one of the SP
4092 // variants (handled above) or a 32-bit encoding, so we just
4093 // check against T3.
4094 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4095 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4096 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4097 return false;
4098 // If both registers are low, we're in an IT block, and the immediate is
4099 // in range, we should use encoding T1 instead, which has a cc_out.
4100 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004101 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004102 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4103 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4104 return false;
4105
4106 // Otherwise, we use encoding T4, which does not have a cc_out
4107 // operand.
4108 return true;
4109 }
4110
Jim Grosbach64944f42011-09-14 21:00:40 +00004111 // The thumb2 multiply instruction doesn't have a CCOut register, so
4112 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4113 // use the 16-bit encoding or not.
4114 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4115 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4116 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4117 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4118 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4119 // If the registers aren't low regs, the destination reg isn't the
4120 // same as one of the source regs, or the cc_out operand is zero
4121 // outside of an IT block, we have to use the 32-bit encoding, so
4122 // remove the cc_out operand.
4123 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4124 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4125 !inITBlock() ||
4126 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4127 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4128 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4129 static_cast<ARMOperand*>(Operands[4])->getReg())))
4130 return true;
4131
4132
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004133
Jim Grosbachf69c8042011-08-24 21:42:27 +00004134 // Register-register 'add/sub' for thumb does not have a cc_out operand
4135 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4136 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4137 // right, this will result in better diagnostics (which operand is off)
4138 // anyway.
4139 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4140 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004141 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4142 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4143 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4144 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004145
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004146 return false;
4147}
4148
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004149/// Parse an arm instruction mnemonic followed by its operands.
4150bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4151 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4152 // Create the leading tokens for the mnemonic, split by '.' characters.
4153 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004154 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004155
Daniel Dunbar352e1482011-01-11 15:59:50 +00004156 // Split out the predication code and carry setting flag from the mnemonic.
4157 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004158 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004159 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004160 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004161 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004162 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004163
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004164 // In Thumb1, only the branch (B) instruction can be predicated.
4165 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4166 Parser.EatToEndOfStatement();
4167 return Error(NameLoc, "conditional execution not supported in Thumb1");
4168 }
4169
Jim Grosbachffa32252011-07-19 19:13:28 +00004170 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4171
Jim Grosbach89df9962011-08-26 21:43:41 +00004172 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4173 // is the mask as it will be for the IT encoding if the conditional
4174 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4175 // where the conditional bit0 is zero, the instruction post-processing
4176 // will adjust the mask accordingly.
4177 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004178 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4179 if (ITMask.size() > 3) {
4180 Parser.EatToEndOfStatement();
4181 return Error(Loc, "too many conditions on IT instruction");
4182 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004183 unsigned Mask = 8;
4184 for (unsigned i = ITMask.size(); i != 0; --i) {
4185 char pos = ITMask[i - 1];
4186 if (pos != 't' && pos != 'e') {
4187 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004188 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004189 }
4190 Mask >>= 1;
4191 if (ITMask[i - 1] == 't')
4192 Mask |= 8;
4193 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004194 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004195 }
4196
Jim Grosbachffa32252011-07-19 19:13:28 +00004197 // FIXME: This is all a pretty gross hack. We should automatically handle
4198 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004199
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004200 // Next, add the CCOut and ConditionCode operands, if needed.
4201 //
4202 // For mnemonics which can ever incorporate a carry setting bit or predication
4203 // code, our matching model involves us always generating CCOut and
4204 // ConditionCode operands to match the mnemonic "as written" and then we let
4205 // the matcher deal with finding the right instruction or generating an
4206 // appropriate error.
4207 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004208 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004209
Jim Grosbach33c16a22011-07-14 22:04:21 +00004210 // If we had a carry-set on an instruction that can't do that, issue an
4211 // error.
4212 if (!CanAcceptCarrySet && CarrySetting) {
4213 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004214 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004215 "' can not set flags, but 's' suffix specified");
4216 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004217 // If we had a predication code on an instruction that can't do that, issue an
4218 // error.
4219 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4220 Parser.EatToEndOfStatement();
4221 return Error(NameLoc, "instruction '" + Mnemonic +
4222 "' is not predicable, but condition code specified");
4223 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004224
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004225 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004226 if (CanAcceptCarrySet) {
4227 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004228 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004229 Loc));
4230 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004231
4232 // Add the predication code operand, if necessary.
4233 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004234 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4235 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004236 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004237 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004238 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004239
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004240 // Add the processor imod operand, if necessary.
4241 if (ProcessorIMod) {
4242 Operands.push_back(ARMOperand::CreateImm(
4243 MCConstantExpr::Create(ProcessorIMod, getContext()),
4244 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004245 }
4246
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004247 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004248 while (Next != StringRef::npos) {
4249 Start = Next;
4250 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004251 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004252
Jim Grosbach4d23e992011-08-24 22:19:48 +00004253 // For now, we're only parsing Thumb1 (for the most part), so
4254 // just ignore ".n" qualifiers. We'll use them to restrict
4255 // matching when we do Thumb2.
Jim Grosbach81d2e392011-09-07 16:06:04 +00004256 if (ExtraToken != ".n") {
4257 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4258 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4259 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004260 }
4261
4262 // Read the remaining operands.
4263 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004264 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004265 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004266 Parser.EatToEndOfStatement();
4267 return true;
4268 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004269
4270 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004271 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004272
4273 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004274 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004275 Parser.EatToEndOfStatement();
4276 return true;
4277 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004278 }
4279 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004280
Chris Lattnercbf8a982010-09-11 16:18:25 +00004281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004282 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004283 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004284 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004285 }
Bill Wendling146018f2010-11-06 21:42:12 +00004286
Chris Lattner34e53142010-09-08 05:10:46 +00004287 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004288
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004289 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4290 // do and don't have a cc_out optional-def operand. With some spot-checks
4291 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004292 // parse and adjust accordingly before actually matching. We shouldn't ever
4293 // try to remove a cc_out operand that was explicitly set on the the
4294 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4295 // table driven matcher doesn't fit well with the ARM instruction set.
4296 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004297 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4298 Operands.erase(Operands.begin() + 1);
4299 delete Op;
4300 }
4301
Jim Grosbachcf121c32011-07-28 21:57:55 +00004302 // ARM mode 'blx' need special handling, as the register operand version
4303 // is predicable, but the label operand version is not. So, we can't rely
4304 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004305 // a k_CondCode operand in the list. If we're trying to match the label
4306 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004307 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4308 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4309 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4310 Operands.erase(Operands.begin() + 1);
4311 delete Op;
4312 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004313
4314 // The vector-compare-to-zero instructions have a literal token "#0" at
4315 // the end that comes to here as an immediate operand. Convert it to a
4316 // token to play nicely with the matcher.
4317 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4318 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4319 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4320 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4321 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4322 if (CE && CE->getValue() == 0) {
4323 Operands.erase(Operands.begin() + 5);
4324 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4325 delete Op;
4326 }
4327 }
Jim Grosbach68259142011-10-03 22:30:24 +00004328 // VCMP{E} does the same thing, but with a different operand count.
4329 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4330 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4331 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4332 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4333 if (CE && CE->getValue() == 0) {
4334 Operands.erase(Operands.begin() + 4);
4335 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4336 delete Op;
4337 }
4338 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004339 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4340 // end. Convert it to a token here.
4341 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4342 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4343 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4344 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4345 if (CE && CE->getValue() == 0) {
4346 Operands.erase(Operands.begin() + 5);
4347 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4348 delete Op;
4349 }
4350 }
4351
Chris Lattner98986712010-01-14 22:21:20 +00004352 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004353}
4354
Jim Grosbach189610f2011-07-26 18:25:39 +00004355// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004356
4357// return 'true' if register list contains non-low GPR registers,
4358// 'false' otherwise. If Reg is in the register list or is HiReg, set
4359// 'containsReg' to true.
4360static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4361 unsigned HiReg, bool &containsReg) {
4362 containsReg = false;
4363 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4364 unsigned OpReg = Inst.getOperand(i).getReg();
4365 if (OpReg == Reg)
4366 containsReg = true;
4367 // Anything other than a low register isn't legal here.
4368 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4369 return true;
4370 }
4371 return false;
4372}
4373
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004374// Check if the specified regisgter is in the register list of the inst,
4375// starting at the indicated operand number.
4376static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4377 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4378 unsigned OpReg = Inst.getOperand(i).getReg();
4379 if (OpReg == Reg)
4380 return true;
4381 }
4382 return false;
4383}
4384
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004385// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4386// the ARMInsts array) instead. Getting that here requires awkward
4387// API changes, though. Better way?
4388namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004389extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004390}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004391static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004392 return ARMInsts[Opcode];
4393}
4394
Jim Grosbach189610f2011-07-26 18:25:39 +00004395// FIXME: We would really like to be able to tablegen'erate this.
4396bool ARMAsmParser::
4397validateInstruction(MCInst &Inst,
4398 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004399 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004400 SMLoc Loc = Operands[0]->getStartLoc();
4401 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004402 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4403 // being allowed in IT blocks, but not being predicable. It just always
4404 // executes.
4405 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004406 unsigned bit = 1;
4407 if (ITState.FirstCond)
4408 ITState.FirstCond = false;
4409 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004410 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004411 // The instruction must be predicable.
4412 if (!MCID.isPredicable())
4413 return Error(Loc, "instructions in IT block must be predicable");
4414 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4415 unsigned ITCond = bit ? ITState.Cond :
4416 ARMCC::getOppositeCondition(ITState.Cond);
4417 if (Cond != ITCond) {
4418 // Find the condition code Operand to get its SMLoc information.
4419 SMLoc CondLoc;
4420 for (unsigned i = 1; i < Operands.size(); ++i)
4421 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4422 CondLoc = Operands[i]->getStartLoc();
4423 return Error(CondLoc, "incorrect condition in IT block; got '" +
4424 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4425 "', but expected '" +
4426 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4427 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004428 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004429 } else if (isThumbTwo() && MCID.isPredicable() &&
4430 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004431 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4432 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004433 return Error(Loc, "predicated instructions must be in IT block");
4434
Jim Grosbach189610f2011-07-26 18:25:39 +00004435 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004436 case ARM::LDRD:
4437 case ARM::LDRD_PRE:
4438 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004439 case ARM::LDREXD: {
4440 // Rt2 must be Rt + 1.
4441 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4442 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4443 if (Rt2 != Rt + 1)
4444 return Error(Operands[3]->getStartLoc(),
4445 "destination operands must be sequential");
4446 return false;
4447 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004448 case ARM::STRD: {
4449 // Rt2 must be Rt + 1.
4450 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4451 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4452 if (Rt2 != Rt + 1)
4453 return Error(Operands[3]->getStartLoc(),
4454 "source operands must be sequential");
4455 return false;
4456 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004457 case ARM::STRD_PRE:
4458 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004459 case ARM::STREXD: {
4460 // Rt2 must be Rt + 1.
4461 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4462 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4463 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004464 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004465 "source operands must be sequential");
4466 return false;
4467 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004468 case ARM::SBFX:
4469 case ARM::UBFX: {
4470 // width must be in range [1, 32-lsb]
4471 unsigned lsb = Inst.getOperand(2).getImm();
4472 unsigned widthm1 = Inst.getOperand(3).getImm();
4473 if (widthm1 >= 32 - lsb)
4474 return Error(Operands[5]->getStartLoc(),
4475 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004476 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004477 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004478 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004479 // If we're parsing Thumb2, the .w variant is available and handles
4480 // most cases that are normally illegal for a Thumb1 LDM
4481 // instruction. We'll make the transformation in processInstruction()
4482 // if necessary.
4483 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004484 // Thumb LDM instructions are writeback iff the base register is not
4485 // in the register list.
4486 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004487 bool hasWritebackToken =
4488 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4489 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004490 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004491 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004492 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4493 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004494 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004495 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004496 return Error(Operands[2]->getStartLoc(),
4497 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004498 // If we should not have writeback, there must not be a '!'. This is
4499 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004500 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004501 return Error(Operands[3]->getStartLoc(),
4502 "writeback operator '!' not allowed when base register "
4503 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004504
4505 break;
4506 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004507 case ARM::t2LDMIA_UPD: {
4508 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4509 return Error(Operands[4]->getStartLoc(),
4510 "writeback operator '!' not allowed when base register "
4511 "in register list");
4512 break;
4513 }
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004514 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004515 bool listContainsBase;
4516 if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
4517 return Error(Operands[2]->getStartLoc(),
4518 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004519 break;
4520 }
4521 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004522 bool listContainsBase;
4523 if (checkLowRegisterList(Inst, 3, 0, ARM::LR, listContainsBase))
4524 return Error(Operands[2]->getStartLoc(),
4525 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004526 break;
4527 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004528 case ARM::tSTMIA_UPD: {
4529 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004530 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004531 return Error(Operands[4]->getStartLoc(),
4532 "registers must be in range r0-r7");
4533 break;
4534 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004535 }
4536
4537 return false;
4538}
4539
Jim Grosbachf8fce712011-08-11 17:35:48 +00004540void ARMAsmParser::
4541processInstruction(MCInst &Inst,
4542 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4543 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004544 // Handle the MOV complex aliases.
4545 case ARM::ASRi: {
4546 unsigned Amt = Inst.getOperand(2).getImm() + 1;
4547 unsigned ShiftOp = ARM_AM::getSORegOpc(ARM_AM::asr, Amt);
4548 MCInst TmpInst;
4549 TmpInst.setOpcode(ARM::MOVsi);
4550 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4551 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4552 TmpInst.addOperand(MCOperand::CreateImm(ShiftOp)); // Shift value and ty
4553 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4554 TmpInst.addOperand(Inst.getOperand(4));
4555 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4556 Inst = TmpInst;
4557 break;
4558 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004559 case ARM::LDMIA_UPD:
4560 // If this is a load of a single register via a 'pop', then we should use
4561 // a post-indexed LDR instruction instead, per the ARM ARM.
4562 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4563 Inst.getNumOperands() == 5) {
4564 MCInst TmpInst;
4565 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4566 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4567 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4568 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4569 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4570 TmpInst.addOperand(MCOperand::CreateImm(4));
4571 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4572 TmpInst.addOperand(Inst.getOperand(3));
4573 Inst = TmpInst;
4574 }
4575 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004576 case ARM::STMDB_UPD:
4577 // If this is a store of a single register via a 'push', then we should use
4578 // a pre-indexed STR instruction instead, per the ARM ARM.
4579 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4580 Inst.getNumOperands() == 5) {
4581 MCInst TmpInst;
4582 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4583 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4584 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4585 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4586 TmpInst.addOperand(MCOperand::CreateImm(-4));
4587 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4588 TmpInst.addOperand(Inst.getOperand(3));
4589 Inst = TmpInst;
4590 }
4591 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004592 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004593 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4594 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4595 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4596 // to encoding T1 if <Rd> is omitted."
4597 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004598 Inst.setOpcode(ARM::tADDi3);
4599 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004600 case ARM::tSUBi8:
4601 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4602 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4603 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4604 // to encoding T1 if <Rd> is omitted."
4605 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6)
4606 Inst.setOpcode(ARM::tSUBi3);
4607 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004608 case ARM::tB:
4609 // A Thumb conditional branch outside of an IT block is a tBcc.
4610 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4611 Inst.setOpcode(ARM::tBcc);
4612 break;
4613 case ARM::t2B:
4614 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
4615 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock())
4616 Inst.setOpcode(ARM::t2Bcc);
4617 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004618 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004619 // If the conditional is AL or we're in an IT block, we really want t2B.
4620 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock())
Jim Grosbachc0755102011-08-31 21:17:31 +00004621 Inst.setOpcode(ARM::t2B);
4622 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004623 case ARM::tBcc:
4624 // If the conditional is AL, we really want tB.
4625 if (Inst.getOperand(1).getImm() == ARMCC::AL)
4626 Inst.setOpcode(ARM::tB);
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004627 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004628 case ARM::tLDMIA: {
4629 // If the register list contains any high registers, or if the writeback
4630 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4631 // instead if we're in Thumb2. Otherwise, this should have generated
4632 // an error in validateInstruction().
4633 unsigned Rn = Inst.getOperand(0).getReg();
4634 bool hasWritebackToken =
4635 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4636 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4637 bool listContainsBase;
4638 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4639 (!listContainsBase && !hasWritebackToken) ||
4640 (listContainsBase && hasWritebackToken)) {
4641 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4642 assert (isThumbTwo());
4643 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4644 // If we're switching to the updating version, we need to insert
4645 // the writeback tied operand.
4646 if (hasWritebackToken)
4647 Inst.insert(Inst.begin(),
4648 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
4649 }
4650 break;
4651 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004652 case ARM::tSTMIA_UPD: {
4653 // If the register list contains any high registers, we need to use
4654 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4655 // should have generated an error in validateInstruction().
4656 unsigned Rn = Inst.getOperand(0).getReg();
4657 bool listContainsBase;
4658 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4659 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4660 assert (isThumbTwo());
4661 Inst.setOpcode(ARM::t2STMIA_UPD);
4662 }
4663 break;
4664 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004665 case ARM::t2MOVi: {
4666 // If we can use the 16-bit encoding and the user didn't explicitly
4667 // request the 32-bit variant, transform it here.
4668 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4669 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004670 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4671 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4672 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004673 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4674 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4675 // The operands aren't in the same order for tMOVi8...
4676 MCInst TmpInst;
4677 TmpInst.setOpcode(ARM::tMOVi8);
4678 TmpInst.addOperand(Inst.getOperand(0));
4679 TmpInst.addOperand(Inst.getOperand(4));
4680 TmpInst.addOperand(Inst.getOperand(1));
4681 TmpInst.addOperand(Inst.getOperand(2));
4682 TmpInst.addOperand(Inst.getOperand(3));
4683 Inst = TmpInst;
4684 }
4685 break;
4686 }
4687 case ARM::t2MOVr: {
4688 // If we can use the 16-bit encoding and the user didn't explicitly
4689 // request the 32-bit variant, transform it here.
4690 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4691 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4692 Inst.getOperand(2).getImm() == ARMCC::AL &&
4693 Inst.getOperand(4).getReg() == ARM::CPSR &&
4694 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4695 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4696 // The operands aren't the same for tMOV[S]r... (no cc_out)
4697 MCInst TmpInst;
4698 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4699 TmpInst.addOperand(Inst.getOperand(0));
4700 TmpInst.addOperand(Inst.getOperand(1));
4701 TmpInst.addOperand(Inst.getOperand(2));
4702 TmpInst.addOperand(Inst.getOperand(3));
4703 Inst = TmpInst;
4704 }
4705 break;
4706 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004707 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004708 case ARM::t2SXTB:
4709 case ARM::t2UXTH:
4710 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004711 // If we can use the 16-bit encoding and the user didn't explicitly
4712 // request the 32-bit variant, transform it here.
4713 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4714 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4715 Inst.getOperand(2).getImm() == 0 &&
4716 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4717 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004718 unsigned NewOpc;
4719 switch (Inst.getOpcode()) {
4720 default: llvm_unreachable("Illegal opcode!");
4721 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4722 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4723 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4724 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4725 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004726 // The operands aren't the same for thumb1 (no rotate operand).
4727 MCInst TmpInst;
4728 TmpInst.setOpcode(NewOpc);
4729 TmpInst.addOperand(Inst.getOperand(0));
4730 TmpInst.addOperand(Inst.getOperand(1));
4731 TmpInst.addOperand(Inst.getOperand(3));
4732 TmpInst.addOperand(Inst.getOperand(4));
4733 Inst = TmpInst;
4734 }
4735 break;
4736 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004737 case ARM::t2IT: {
4738 // The mask bits for all but the first condition are represented as
4739 // the low bit of the condition code value implies 't'. We currently
4740 // always have 1 implies 't', so XOR toggle the bits if the low bit
4741 // of the condition code is zero. The encoding also expects the low
4742 // bit of the condition to be encoded as bit 4 of the mask operand,
4743 // so mask that in if needed
4744 MCOperand &MO = Inst.getOperand(1);
4745 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004746 unsigned OrigMask = Mask;
4747 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004748 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004749 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4750 for (unsigned i = 3; i != TZ; --i)
4751 Mask ^= 1 << i;
4752 } else
4753 Mask |= 0x10;
4754 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004755
4756 // Set up the IT block state according to the IT instruction we just
4757 // matched.
4758 assert(!inITBlock() && "nested IT blocks?!");
4759 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4760 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4761 ITState.CurPosition = 0;
4762 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004763 break;
4764 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004765 }
4766}
4767
Jim Grosbach47a0d522011-08-16 20:45:50 +00004768unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4769 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4770 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004771 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004772 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004773 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4774 assert(MCID.hasOptionalDef() &&
4775 "optionally flag setting instruction missing optional def operand");
4776 assert(MCID.NumOperands == Inst.getNumOperands() &&
4777 "operand count mismatch!");
4778 // Find the optional-def operand (cc_out).
4779 unsigned OpNo;
4780 for (OpNo = 0;
4781 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4782 ++OpNo)
4783 ;
4784 // If we're parsing Thumb1, reject it completely.
4785 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4786 return Match_MnemonicFail;
4787 // If we're parsing Thumb2, which form is legal depends on whether we're
4788 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004789 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4790 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004791 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004792 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4793 inITBlock())
4794 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004795 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004796 // Some high-register supporting Thumb1 encodings only allow both registers
4797 // to be from r0-r7 when in Thumb2.
4798 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4799 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4800 isARMLowRegister(Inst.getOperand(2).getReg()))
4801 return Match_RequiresThumb2;
4802 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004803 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004804 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4805 isARMLowRegister(Inst.getOperand(1).getReg()))
4806 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004807 return Match_Success;
4808}
4809
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004810bool ARMAsmParser::
4811MatchAndEmitInstruction(SMLoc IDLoc,
4812 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4813 MCStreamer &Out) {
4814 MCInst Inst;
4815 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004816 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004817 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004818 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004819 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004820 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004821 // Context sensitive operand constraints aren't handled by the matcher,
4822 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004823 if (validateInstruction(Inst, Operands)) {
4824 // Still progress the IT block, otherwise one wrong condition causes
4825 // nasty cascading errors.
4826 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004827 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004828 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004829
Jim Grosbachf8fce712011-08-11 17:35:48 +00004830 // Some instructions need post-processing to, for example, tweak which
4831 // encoding is selected.
4832 processInstruction(Inst, Operands);
4833
Jim Grosbacha1109882011-09-02 23:22:08 +00004834 // Only move forward at the very end so that everything in validate
4835 // and process gets a consistent answer about whether we're in an IT
4836 // block.
4837 forwardITPosition();
4838
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004839 Out.EmitInstruction(Inst);
4840 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004841 case Match_MissingFeature:
4842 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
4843 return true;
4844 case Match_InvalidOperand: {
4845 SMLoc ErrorLoc = IDLoc;
4846 if (ErrorInfo != ~0U) {
4847 if (ErrorInfo >= Operands.size())
4848 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00004849
Chris Lattnere73d4f82010-10-28 21:41:58 +00004850 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
4851 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
4852 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004853
Chris Lattnere73d4f82010-10-28 21:41:58 +00004854 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004855 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00004856 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00004857 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00004858 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004859 // The converter function will have already emited a diagnostic.
4860 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004861 case Match_RequiresNotITBlock:
4862 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00004863 case Match_RequiresITBlock:
4864 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00004865 case Match_RequiresV6:
4866 return Error(IDLoc, "instruction variant requires ARMv6 or later");
4867 case Match_RequiresThumb2:
4868 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00004869 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004870
Eric Christopherc223e2b2010-10-29 09:26:59 +00004871 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00004872 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004873}
4874
Jim Grosbach1355cf12011-07-26 17:10:22 +00004875/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004876bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
4877 StringRef IDVal = DirectiveID.getIdentifier();
4878 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004879 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004880 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004881 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004882 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004883 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004884 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004885 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00004886 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00004887 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004888 return true;
4889}
4890
Jim Grosbach1355cf12011-07-26 17:10:22 +00004891/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004892/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00004893bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004894 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4895 for (;;) {
4896 const MCExpr *Value;
4897 if (getParser().ParseExpression(Value))
4898 return true;
4899
Chris Lattneraaec2052010-01-19 19:46:13 +00004900 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004901
4902 if (getLexer().is(AsmToken::EndOfStatement))
4903 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00004904
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004905 // FIXME: Improve diagnostic.
4906 if (getLexer().isNot(AsmToken::Comma))
4907 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004908 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004909 }
4910 }
4911
Sean Callananb9a25b72010-01-19 20:27:46 +00004912 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004913 return false;
4914}
4915
Jim Grosbach1355cf12011-07-26 17:10:22 +00004916/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00004917/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00004918bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00004919 if (getLexer().isNot(AsmToken::EndOfStatement))
4920 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004921 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004922
4923 // TODO: set thumb mode
4924 // TODO: tell the MC streamer the mode
4925 // getParser().getStreamer().Emit???();
4926 return false;
4927}
4928
Jim Grosbach1355cf12011-07-26 17:10:22 +00004929/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00004930/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00004931bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00004932 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
4933 bool isMachO = MAI.hasSubsectionsViaSymbols();
4934 StringRef Name;
4935
4936 // Darwin asm has function name after .thumb_func direction
4937 // ELF doesn't
4938 if (isMachO) {
4939 const AsmToken &Tok = Parser.getTok();
4940 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
4941 return Error(L, "unexpected token in .thumb_func directive");
4942 Name = Tok.getString();
4943 Parser.Lex(); // Consume the identifier token.
4944 }
4945
Kevin Enderby515d5092009-10-15 20:48:48 +00004946 if (getLexer().isNot(AsmToken::EndOfStatement))
4947 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004948 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004949
Rafael Espindola64695402011-05-16 16:17:21 +00004950 // FIXME: assuming function name will be the line following .thumb_func
4951 if (!isMachO) {
4952 Name = Parser.getTok().getString();
4953 }
4954
Jim Grosbach642fc9c2010-11-05 22:33:53 +00004955 // Mark symbol as a thumb symbol.
4956 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
4957 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00004958 return false;
4959}
4960
Jim Grosbach1355cf12011-07-26 17:10:22 +00004961/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00004962/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00004963bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004964 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004965 if (Tok.isNot(AsmToken::Identifier))
4966 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00004967 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00004968 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00004969 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004970 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00004971 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00004972 else
4973 return Error(L, "unrecognized syntax mode in .syntax directive");
4974
4975 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004976 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00004977 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004978
4979 // TODO tell the MC streamer the mode
4980 // getParser().getStreamer().Emit???();
4981 return false;
4982}
4983
Jim Grosbach1355cf12011-07-26 17:10:22 +00004984/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00004985/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00004986bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00004987 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00004988 if (Tok.isNot(AsmToken::Integer))
4989 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00004990 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00004991 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00004992 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00004993 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00004994 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00004995 else
4996 return Error(L, "invalid operand to .code directive");
4997
4998 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00004999 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005000 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005001
Evan Cheng32869202011-07-08 22:36:29 +00005002 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005003 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005004 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005005 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005006 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005007 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005008 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005009 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005010 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005011
Kevin Enderby515d5092009-10-15 20:48:48 +00005012 return false;
5013}
5014
Sean Callanan90b70972010-04-07 20:29:34 +00005015extern "C" void LLVMInitializeARMAsmLexer();
5016
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005017/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005018extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005019 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5020 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005021 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005022}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005023
Chris Lattner0692ee62010-09-06 19:11:01 +00005024#define GET_REGISTER_MATCHER
5025#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005026#include "ARMGenAsmMatcher.inc"