blob: b2e2f7a5b59723ef2f8fc7a5e9c7d0ab3689071d [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 Grosbach83ec8772011-11-10 23:42:14 +0000211 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000212 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 Grosbachee10ff82011-11-10 19:18:01 +0000605 bool isImm0_32() const {
606 if (Kind != k_Immediate)
607 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 < 33;
612 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000613 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000614 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000615 return false;
616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
617 if (!CE) return false;
618 int64_t Value = CE->getValue();
619 return Value >= 0 && Value < 65536;
620 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000621 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000622 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000623 return false;
624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 // If it's not a constant expression, it'll generate a fixup and be
626 // handled later.
627 if (!CE) return true;
628 int64_t Value = CE->getValue();
629 return Value >= 0 && Value < 65536;
630 }
Jim Grosbached838482011-07-26 16:24:27 +0000631 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000632 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24: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 <= 0xffffff;
638 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000639 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000640 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +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 < 33;
646 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000647 bool isPKHLSLImm() 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 }
655 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000656 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000657 return false;
658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
659 if (!CE) return false;
660 int64_t Value = CE->getValue();
661 return Value > 0 && Value <= 32;
662 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000663 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000664 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000665 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 Grosbache70ec842011-10-28 22:50:54 +0000671 bool isARMSOImmNot() const {
672 if (Kind != k_Immediate)
673 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::getSOImmVal(~Value) != -1;
678 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000679 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000680 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000681 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 Grosbach89a63372011-10-28 22:36:30 +0000687 bool isT2SOImmNot() const {
688 if (Kind != k_Immediate)
689 return false;
690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
691 if (!CE) return false;
692 int64_t Value = CE->getValue();
693 return ARM_AM::getT2SOImmVal(~Value) != -1;
694 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000695 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000696 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000697 return false;
698 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
699 if (!CE) return false;
700 int64_t Value = CE->getValue();
701 return Value == 1 || Value == 0;
702 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000703 bool isReg() const { return Kind == k_Register; }
704 bool isRegList() const { return Kind == k_RegisterList; }
705 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
706 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
707 bool isToken() const { return Kind == k_Token; }
708 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
709 bool isMemory() const { return Kind == k_Memory; }
710 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
711 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
712 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
713 bool isRotImm() const { return Kind == k_RotateImmediate; }
714 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
715 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000716 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000717 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000718 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000719 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000720 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000721 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000722 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000723 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
724 (alignOK || Memory.Alignment == 0);
725 }
726 bool isAlignedMemory() const {
727 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000728 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000729 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000730 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000731 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000732 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000733 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000734 if (!Memory.OffsetImm) return true;
735 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000736 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000737 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000738 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000739 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000740 return false;
741 // Immediate offset in range [-4095, 4095].
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 if (!CE) return false;
744 int64_t Val = CE->getValue();
745 return Val > -4096 && Val < 4096;
746 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000747 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000748 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000749 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000750 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000751 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000752 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000753 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000754 if (!Memory.OffsetImm) return true;
755 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000756 return Val > -256 && Val < 256;
757 }
758 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000759 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000760 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000762 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
763 // Immediate offset in range [-255, 255].
764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 if (!CE) return false;
766 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000767 // Special case, #-0 is INT32_MIN.
768 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000769 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000770 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000771 // If we have an immediate that's not a constant, treat it as a label
772 // reference needing a fixup. If it is a constant, it's something else
773 // and we reject it.
774 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
775 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000776 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000777 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000778 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000779 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000780 if (!Memory.OffsetImm) return true;
781 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000782 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000783 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000784 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000785 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000786 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000787 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000788 return false;
789 return true;
790 }
791 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000792 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000793 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
794 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000795 return false;
796 return true;
797 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000798 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000799 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000800 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000801 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000802 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000803 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
805 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000806 return false;
807 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000808 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000809 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000810 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000811 return false;
812 return true;
813 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000814 bool isMemThumbRR() const {
815 // Thumb reg+reg addressing is simple. Just two registers, a base and
816 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000817 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000818 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000819 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000820 return isARMLowRegister(Memory.BaseRegNum) &&
821 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000822 }
823 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000824 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000825 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000826 return false;
827 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000828 if (!Memory.OffsetImm) return true;
829 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000830 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
831 }
Jim Grosbach38466302011-08-19 18:55:51 +0000832 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000833 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000834 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000835 return false;
836 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000837 if (!Memory.OffsetImm) return true;
838 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000839 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
840 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000841 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000842 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000843 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000844 return false;
845 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000846 if (!Memory.OffsetImm) return true;
847 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000848 return Val >= 0 && Val <= 31;
849 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000850 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000851 if (!isMemory() || Memory.OffsetRegNum != 0 ||
852 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000853 return false;
854 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000855 if (!Memory.OffsetImm) return true;
856 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000857 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000858 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000859 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000861 return false;
862 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000863 if (!Memory.OffsetImm) return true;
864 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000865 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
866 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000867 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000869 return false;
870 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000873 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
874 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000875 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000877 return false;
878 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000879 if (!Memory.OffsetImm) return true;
880 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000881 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000883 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000885 return false;
886 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000887 if (!Memory.OffsetImm) return true;
888 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000889 return Val >= 0 && Val < 256;
890 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000891 bool isMemNegImm8Offset() 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 [-255, -1].
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 > -256 && Val < 0;
898 }
899 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000900 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000901 return false;
902 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000903 if (!Memory.OffsetImm) return true;
904 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000905 return (Val >= 0 && Val < 4096);
906 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000907 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000908 // If we have an immediate that's not a constant, treat it as a label
909 // reference needing a fixup. If it is a constant, it's something else
910 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000911 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000912 return true;
913
Jim Grosbach57dcb852011-10-11 17:29:55 +0000914 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000915 return false;
916 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000917 if (!Memory.OffsetImm) return true;
918 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000919 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000920 }
921 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000922 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000923 return false;
924 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
925 if (!CE) return false;
926 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000927 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000928 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000929 bool isPostIdxImm8s4() const {
930 if (Kind != k_Immediate)
931 return false;
932 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
933 if (!CE) return false;
934 int64_t Val = CE->getValue();
935 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
936 (Val == INT32_MIN);
937 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000938
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000939 bool isMSRMask() const { return Kind == k_MSRMask; }
940 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000941
Jim Grosbach0e387b22011-10-17 22:26:03 +0000942 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000943 bool isVecListOneD() const {
944 if (Kind != k_VectorList) return false;
945 return VectorList.Count == 1;
946 }
947
Jim Grosbach280dfad2011-10-21 18:54:25 +0000948 bool isVecListTwoD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 2;
951 }
952
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000953 bool isVecListThreeD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 3;
956 }
957
Jim Grosbachb6310312011-10-21 20:35:01 +0000958 bool isVecListFourD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 4;
961 }
962
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000963 bool isVecListTwoQ() const {
964 if (Kind != k_VectorList) return false;
965 //FIXME: We haven't taught the parser to handle by-two register lists
966 // yet, so don't pretend to know one.
967 return VectorList.Count == 2 && false;
968 }
969
Jim Grosbach460a9052011-10-07 23:56:00 +0000970 bool isVectorIndex8() const {
971 if (Kind != k_VectorIndex) return false;
972 return VectorIndex.Val < 8;
973 }
974 bool isVectorIndex16() const {
975 if (Kind != k_VectorIndex) return false;
976 return VectorIndex.Val < 4;
977 }
978 bool isVectorIndex32() const {
979 if (Kind != k_VectorIndex) return false;
980 return VectorIndex.Val < 2;
981 }
982
Jim Grosbach0e387b22011-10-17 22:26:03 +0000983 bool isNEONi8splat() const {
984 if (Kind != k_Immediate)
985 return false;
986 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
987 // Must be a constant.
988 if (!CE) return false;
989 int64_t Value = CE->getValue();
990 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
991 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +0000992 return Value >= 0 && Value < 256;
993 }
Jim Grosbach460a9052011-10-07 23:56:00 +0000994
Jim Grosbachea461102011-10-17 23:09:09 +0000995 bool isNEONi16splat() const {
996 if (Kind != k_Immediate)
997 return false;
998 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
999 // Must be a constant.
1000 if (!CE) return false;
1001 int64_t Value = CE->getValue();
1002 // i16 value in the range [0,255] or [0x0100, 0xff00]
1003 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1004 }
1005
Jim Grosbach6248a542011-10-18 00:22:00 +00001006 bool isNEONi32splat() const {
1007 if (Kind != k_Immediate)
1008 return false;
1009 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1010 // Must be a constant.
1011 if (!CE) return false;
1012 int64_t Value = CE->getValue();
1013 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1014 return (Value >= 0 && Value < 256) ||
1015 (Value >= 0x0100 && Value <= 0xff00) ||
1016 (Value >= 0x010000 && Value <= 0xff0000) ||
1017 (Value >= 0x01000000 && Value <= 0xff000000);
1018 }
1019
1020 bool isNEONi32vmov() const {
1021 if (Kind != k_Immediate)
1022 return false;
1023 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1024 // Must be a constant.
1025 if (!CE) return false;
1026 int64_t Value = CE->getValue();
1027 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1028 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000) ||
1033 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1034 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1035 }
1036
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001037 bool isNEONi64splat() const {
1038 if (Kind != k_Immediate)
1039 return false;
1040 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1041 // Must be a constant.
1042 if (!CE) return false;
1043 uint64_t Value = CE->getValue();
1044 // i64 value with each byte being either 0 or 0xff.
1045 for (unsigned i = 0; i < 8; ++i)
1046 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1047 return true;
1048 }
1049
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001050 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001051 // Add as immediates when possible. Null MCExpr = 0.
1052 if (Expr == 0)
1053 Inst.addOperand(MCOperand::CreateImm(0));
1054 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001055 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1056 else
1057 Inst.addOperand(MCOperand::CreateExpr(Expr));
1058 }
1059
Daniel Dunbar8462b302010-08-11 06:36:53 +00001060 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001061 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001062 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001063 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1064 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001065 }
1066
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001067 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1068 assert(N == 1 && "Invalid number of operands!");
1069 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1070 }
1071
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001072 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1073 assert(N == 1 && "Invalid number of operands!");
1074 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1075 }
1076
1077 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1080 }
1081
Jim Grosbach89df9962011-08-26 21:43:41 +00001082 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1085 }
1086
1087 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1090 }
1091
Jim Grosbachd67641b2010-12-06 18:21:12 +00001092 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateReg(getReg()));
1095 }
1096
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001097 void addRegOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateReg(getReg()));
1100 }
1101
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001102 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001103 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001104 assert(isRegShiftedReg() &&
1105 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001106 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1107 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001108 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001109 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001110 }
1111
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001112 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001113 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001114 assert(isRegShiftedImm() &&
1115 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001116 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001117 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001118 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001119 }
1120
Jim Grosbach580f4a92011-07-25 22:20:28 +00001121 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001122 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001123 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1124 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001125 }
1126
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001127 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001128 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001129 const SmallVectorImpl<unsigned> &RegList = getRegList();
1130 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001131 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1132 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001133 }
1134
Bill Wendling0f630752010-11-17 04:32:08 +00001135 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1136 addRegListOperands(Inst, N);
1137 }
1138
1139 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1140 addRegListOperands(Inst, N);
1141 }
1142
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001143 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!");
1145 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1146 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1147 }
1148
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001149 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1150 assert(N == 1 && "Invalid number of operands!");
1151 // Munge the lsb/width into a bitfield mask.
1152 unsigned lsb = Bitfield.LSB;
1153 unsigned width = Bitfield.Width;
1154 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1155 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1156 (32 - (lsb + width)));
1157 Inst.addOperand(MCOperand::CreateImm(Mask));
1158 }
1159
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001160 void addImmOperands(MCInst &Inst, unsigned N) const {
1161 assert(N == 1 && "Invalid number of operands!");
1162 addExpr(Inst, getImm());
1163 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001164
Jim Grosbach9d390362011-10-03 23:38:36 +00001165 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1166 assert(N == 1 && "Invalid number of operands!");
1167 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1168 }
1169
Jim Grosbacha77295d2011-09-08 22:07:06 +00001170 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 // FIXME: We really want to scale the value here, but the LDRD/STRD
1173 // instruction don't encode operands that way yet.
1174 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1175 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1176 }
1177
Jim Grosbach72f39f82011-08-24 21:22:15 +00001178 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1179 assert(N == 1 && "Invalid number of operands!");
1180 // The immediate is scaled by four in the encoding and is stored
1181 // in the MCInst as such. Lop off the low two bits here.
1182 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1183 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1184 }
1185
1186 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 // The immediate is scaled by four in the encoding and is stored
1189 // in the MCInst as such. Lop off the low two bits here.
1190 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1191 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1192 }
1193
Jim Grosbachf4943352011-07-25 23:09:14 +00001194 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 // The constant encodes as the immediate-1, and we store in the instruction
1197 // the bits as encoded, so subtract off one here.
1198 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1199 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1200 }
1201
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001202 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1203 assert(N == 1 && "Invalid number of operands!");
1204 // The constant encodes as the immediate-1, and we store in the instruction
1205 // the bits as encoded, so subtract off one here.
1206 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1207 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1208 }
1209
Jim Grosbach70939ee2011-08-17 21:51:27 +00001210 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1211 assert(N == 1 && "Invalid number of operands!");
1212 // The constant encodes as the immediate, except for 32, which encodes as
1213 // zero.
1214 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1215 unsigned Imm = CE->getValue();
1216 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1217 }
1218
Jim Grosbachf6c05252011-07-21 17:23:04 +00001219 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1220 assert(N == 1 && "Invalid number of operands!");
1221 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1222 // the instruction as well.
1223 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1224 int Val = CE->getValue();
1225 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1226 }
1227
Jim Grosbach89a63372011-10-28 22:36:30 +00001228 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1229 assert(N == 1 && "Invalid number of operands!");
1230 // The operand is actually a t2_so_imm, but we have its bitwise
1231 // negation in the assembly source, so twiddle it here.
1232 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1233 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1234 }
1235
Jim Grosbache70ec842011-10-28 22:50:54 +00001236 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 // The operand is actually a so_imm, but we have its bitwise
1239 // negation in the assembly source, so twiddle it here.
1240 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1241 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1242 }
1243
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001244 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1247 }
1248
Jim Grosbach7ce05792011-08-03 23:50:40 +00001249 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1250 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001251 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001252 }
1253
Jim Grosbach57dcb852011-10-11 17:29:55 +00001254 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 2 && "Invalid number of operands!");
1256 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1257 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1258 }
1259
Jim Grosbach7ce05792011-08-03 23:50:40 +00001260 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1261 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001262 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1263 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001264 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1265 // Special case for #-0
1266 if (Val == INT32_MIN) Val = 0;
1267 if (Val < 0) Val = -Val;
1268 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1269 } else {
1270 // For register offset, we encode the shift type and negation flag
1271 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001272 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1273 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001274 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001275 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1276 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001277 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001278 }
1279
Jim Grosbach039c2e12011-08-04 23:01:30 +00001280 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1281 assert(N == 2 && "Invalid number of operands!");
1282 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1283 assert(CE && "non-constant AM2OffsetImm operand!");
1284 int32_t Val = CE->getValue();
1285 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1286 // Special case for #-0
1287 if (Val == INT32_MIN) Val = 0;
1288 if (Val < 0) Val = -Val;
1289 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1290 Inst.addOperand(MCOperand::CreateReg(0));
1291 Inst.addOperand(MCOperand::CreateImm(Val));
1292 }
1293
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001294 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1295 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001296 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1297 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001298 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1299 // Special case for #-0
1300 if (Val == INT32_MIN) Val = 0;
1301 if (Val < 0) Val = -Val;
1302 Val = ARM_AM::getAM3Opc(AddSub, Val);
1303 } else {
1304 // For register offset, we encode the shift type and negation flag
1305 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001306 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001307 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001308 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1309 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001310 Inst.addOperand(MCOperand::CreateImm(Val));
1311 }
1312
1313 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1314 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001315 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001316 int32_t Val =
1317 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1318 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1319 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001320 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001321 }
1322
1323 // Constant offset.
1324 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1325 int32_t Val = CE->getValue();
1326 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1327 // Special case for #-0
1328 if (Val == INT32_MIN) Val = 0;
1329 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001330 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001331 Inst.addOperand(MCOperand::CreateReg(0));
1332 Inst.addOperand(MCOperand::CreateImm(Val));
1333 }
1334
Jim Grosbach7ce05792011-08-03 23:50:40 +00001335 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001337 // If we have an immediate that's not a constant, treat it as a label
1338 // reference needing a fixup. If it is a constant, it's something else
1339 // and we reject it.
1340 if (isImm()) {
1341 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1342 Inst.addOperand(MCOperand::CreateImm(0));
1343 return;
1344 }
1345
Jim Grosbach7ce05792011-08-03 23:50:40 +00001346 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001347 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001348 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1349 // Special case for #-0
1350 if (Val == INT32_MIN) Val = 0;
1351 if (Val < 0) Val = -Val;
1352 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001353 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001354 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001355 }
1356
Jim Grosbacha77295d2011-09-08 22:07:06 +00001357 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1358 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001359 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1360 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001361 Inst.addOperand(MCOperand::CreateImm(Val));
1362 }
1363
Jim Grosbachb6aed502011-09-09 18:37:27 +00001364 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 2 && "Invalid number of operands!");
1366 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001367 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1368 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001369 Inst.addOperand(MCOperand::CreateImm(Val));
1370 }
1371
Jim Grosbach7ce05792011-08-03 23:50:40 +00001372 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001374 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1375 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001376 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001377 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001378
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001379 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1380 addMemImm8OffsetOperands(Inst, N);
1381 }
1382
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001383 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001384 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001385 }
1386
1387 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 2 && "Invalid number of operands!");
1389 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001390 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001391 addExpr(Inst, getImm());
1392 Inst.addOperand(MCOperand::CreateImm(0));
1393 return;
1394 }
1395
1396 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001397 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1398 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001399 Inst.addOperand(MCOperand::CreateImm(Val));
1400 }
1401
Jim Grosbach7ce05792011-08-03 23:50:40 +00001402 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001404 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001405 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001406 addExpr(Inst, getImm());
1407 Inst.addOperand(MCOperand::CreateImm(0));
1408 return;
1409 }
1410
1411 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001412 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1413 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001414 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001415 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001416
Jim Grosbach7f739be2011-09-19 22:21:13 +00001417 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001419 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1420 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001421 }
1422
1423 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1424 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001425 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1426 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001427 }
1428
Jim Grosbach7ce05792011-08-03 23:50:40 +00001429 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001431 unsigned Val =
1432 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1433 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1435 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001436 Inst.addOperand(MCOperand::CreateImm(Val));
1437 }
1438
Jim Grosbachab899c12011-09-07 23:10:15 +00001439 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001441 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1442 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1443 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001444 }
1445
Jim Grosbach7ce05792011-08-03 23:50:40 +00001446 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1447 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001448 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1449 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001450 }
1451
Jim Grosbach60f91a32011-08-19 17:55:24 +00001452 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001454 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1455 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001456 Inst.addOperand(MCOperand::CreateImm(Val));
1457 }
1458
Jim Grosbach38466302011-08-19 18:55:51 +00001459 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1460 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001461 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1462 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001463 Inst.addOperand(MCOperand::CreateImm(Val));
1464 }
1465
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001466 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1467 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001468 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1469 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001470 Inst.addOperand(MCOperand::CreateImm(Val));
1471 }
1472
Jim Grosbachecd85892011-08-19 18:13:48 +00001473 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1474 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001475 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1476 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001477 Inst.addOperand(MCOperand::CreateImm(Val));
1478 }
1479
Jim Grosbach7ce05792011-08-03 23:50:40 +00001480 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1483 assert(CE && "non-constant post-idx-imm8 operand!");
1484 int Imm = CE->getValue();
1485 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001486 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001487 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1488 Inst.addOperand(MCOperand::CreateImm(Imm));
1489 }
1490
Jim Grosbach2bd01182011-10-11 21:55:36 +00001491 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
1493 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1494 assert(CE && "non-constant post-idx-imm8s4 operand!");
1495 int Imm = CE->getValue();
1496 bool isAdd = Imm >= 0;
1497 if (Imm == INT32_MIN) Imm = 0;
1498 // Immediate is scaled by 4.
1499 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1500 Inst.addOperand(MCOperand::CreateImm(Imm));
1501 }
1502
Jim Grosbach7ce05792011-08-03 23:50:40 +00001503 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1504 assert(N == 2 && "Invalid number of operands!");
1505 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001506 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1507 }
1508
1509 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1510 assert(N == 2 && "Invalid number of operands!");
1511 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1512 // The sign, shift type, and shift amount are encoded in a single operand
1513 // using the AM2 encoding helpers.
1514 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1515 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1516 PostIdxReg.ShiftTy);
1517 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001518 }
1519
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001520 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1521 assert(N == 1 && "Invalid number of operands!");
1522 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1523 }
1524
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001525 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1526 assert(N == 1 && "Invalid number of operands!");
1527 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1528 }
1529
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001530 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001531 assert(N == 1 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1533 }
1534
Jim Grosbach460a9052011-10-07 23:56:00 +00001535 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1538 }
1539
1540 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1543 }
1544
1545 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1548 }
1549
Jim Grosbach0e387b22011-10-17 22:26:03 +00001550 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 // The immediate encodes the type of constant as well as the value.
1553 // Mask in that this is an i8 splat.
1554 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1555 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1556 }
1557
Jim Grosbachea461102011-10-17 23:09:09 +00001558 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1559 assert(N == 1 && "Invalid number of operands!");
1560 // The immediate encodes the type of constant as well as the value.
1561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1562 unsigned Value = CE->getValue();
1563 if (Value >= 256)
1564 Value = (Value >> 8) | 0xa00;
1565 else
1566 Value |= 0x800;
1567 Inst.addOperand(MCOperand::CreateImm(Value));
1568 }
1569
Jim Grosbach6248a542011-10-18 00:22:00 +00001570 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
1572 // The immediate encodes the type of constant as well as the value.
1573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1574 unsigned Value = CE->getValue();
1575 if (Value >= 256 && Value <= 0xff00)
1576 Value = (Value >> 8) | 0x200;
1577 else if (Value > 0xffff && Value <= 0xff0000)
1578 Value = (Value >> 16) | 0x400;
1579 else if (Value > 0xffffff)
1580 Value = (Value >> 24) | 0x600;
1581 Inst.addOperand(MCOperand::CreateImm(Value));
1582 }
1583
1584 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1585 assert(N == 1 && "Invalid number of operands!");
1586 // The immediate encodes the type of constant as well as the value.
1587 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1588 unsigned Value = CE->getValue();
1589 if (Value >= 256 && Value <= 0xffff)
1590 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1591 else if (Value > 0xffff && Value <= 0xffffff)
1592 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1593 else if (Value > 0xffffff)
1594 Value = (Value >> 24) | 0x600;
1595 Inst.addOperand(MCOperand::CreateImm(Value));
1596 }
1597
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001598 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1599 assert(N == 1 && "Invalid number of operands!");
1600 // The immediate encodes the type of constant as well as the value.
1601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1602 uint64_t Value = CE->getValue();
1603 unsigned Imm = 0;
1604 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1605 Imm |= (Value & 1) << i;
1606 }
1607 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1608 }
1609
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001610 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001611
Jim Grosbach89df9962011-08-26 21:43:41 +00001612 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001613 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001614 Op->ITMask.Mask = Mask;
1615 Op->StartLoc = S;
1616 Op->EndLoc = S;
1617 return Op;
1618 }
1619
Chris Lattner3a697562010-10-28 17:20:03 +00001620 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001621 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001622 Op->CC.Val = CC;
1623 Op->StartLoc = S;
1624 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001625 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001626 }
1627
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001628 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001629 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001630 Op->Cop.Val = CopVal;
1631 Op->StartLoc = S;
1632 Op->EndLoc = S;
1633 return Op;
1634 }
1635
1636 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001637 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001638 Op->Cop.Val = CopVal;
1639 Op->StartLoc = S;
1640 Op->EndLoc = S;
1641 return Op;
1642 }
1643
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001644 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1645 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1646 Op->Cop.Val = Val;
1647 Op->StartLoc = S;
1648 Op->EndLoc = E;
1649 return Op;
1650 }
1651
Jim Grosbachd67641b2010-12-06 18:21:12 +00001652 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001653 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001654 Op->Reg.RegNum = RegNum;
1655 Op->StartLoc = S;
1656 Op->EndLoc = S;
1657 return Op;
1658 }
1659
Chris Lattner3a697562010-10-28 17:20:03 +00001660 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001661 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001662 Op->Tok.Data = Str.data();
1663 Op->Tok.Length = Str.size();
1664 Op->StartLoc = S;
1665 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001666 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001667 }
1668
Bill Wendling50d0f582010-11-18 23:43:05 +00001669 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001670 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001671 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001672 Op->StartLoc = S;
1673 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001674 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001675 }
1676
Jim Grosbache8606dc2011-07-13 17:50:29 +00001677 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1678 unsigned SrcReg,
1679 unsigned ShiftReg,
1680 unsigned ShiftImm,
1681 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001682 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001683 Op->RegShiftedReg.ShiftTy = ShTy;
1684 Op->RegShiftedReg.SrcReg = SrcReg;
1685 Op->RegShiftedReg.ShiftReg = ShiftReg;
1686 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001687 Op->StartLoc = S;
1688 Op->EndLoc = E;
1689 return Op;
1690 }
1691
Owen Anderson92a20222011-07-21 18:54:16 +00001692 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1693 unsigned SrcReg,
1694 unsigned ShiftImm,
1695 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001696 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001697 Op->RegShiftedImm.ShiftTy = ShTy;
1698 Op->RegShiftedImm.SrcReg = SrcReg;
1699 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001700 Op->StartLoc = S;
1701 Op->EndLoc = E;
1702 return Op;
1703 }
1704
Jim Grosbach580f4a92011-07-25 22:20:28 +00001705 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001706 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001707 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001708 Op->ShifterImm.isASR = isASR;
1709 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001710 Op->StartLoc = S;
1711 Op->EndLoc = E;
1712 return Op;
1713 }
1714
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001715 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001716 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001717 Op->RotImm.Imm = Imm;
1718 Op->StartLoc = S;
1719 Op->EndLoc = E;
1720 return Op;
1721 }
1722
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001723 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1724 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001725 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001726 Op->Bitfield.LSB = LSB;
1727 Op->Bitfield.Width = Width;
1728 Op->StartLoc = S;
1729 Op->EndLoc = E;
1730 return Op;
1731 }
1732
Bill Wendling7729e062010-11-09 22:44:22 +00001733 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001734 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001735 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001736 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001737
Jim Grosbachd300b942011-09-13 22:56:44 +00001738 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001739 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001740 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001741 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001742 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001743
1744 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001745 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001746 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001747 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001748 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001749 Op->StartLoc = StartLoc;
1750 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001751 return Op;
1752 }
1753
Jim Grosbach862019c2011-10-18 23:02:30 +00001754 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1755 SMLoc S, SMLoc E) {
1756 ARMOperand *Op = new ARMOperand(k_VectorList);
1757 Op->VectorList.RegNum = RegNum;
1758 Op->VectorList.Count = Count;
1759 Op->StartLoc = S;
1760 Op->EndLoc = E;
1761 return Op;
1762 }
1763
Jim Grosbach460a9052011-10-07 23:56:00 +00001764 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1765 MCContext &Ctx) {
1766 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1767 Op->VectorIndex.Val = Idx;
1768 Op->StartLoc = S;
1769 Op->EndLoc = E;
1770 return Op;
1771 }
1772
Chris Lattner3a697562010-10-28 17:20:03 +00001773 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001774 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001775 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001776 Op->StartLoc = S;
1777 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001778 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001779 }
1780
Jim Grosbach9d390362011-10-03 23:38:36 +00001781 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001782 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001783 Op->FPImm.Val = Val;
1784 Op->StartLoc = S;
1785 Op->EndLoc = S;
1786 return Op;
1787 }
1788
Jim Grosbach7ce05792011-08-03 23:50:40 +00001789 static ARMOperand *CreateMem(unsigned BaseRegNum,
1790 const MCConstantExpr *OffsetImm,
1791 unsigned OffsetRegNum,
1792 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001793 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001794 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001795 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001796 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001797 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001798 Op->Memory.BaseRegNum = BaseRegNum;
1799 Op->Memory.OffsetImm = OffsetImm;
1800 Op->Memory.OffsetRegNum = OffsetRegNum;
1801 Op->Memory.ShiftType = ShiftType;
1802 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001803 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001804 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001805 Op->StartLoc = S;
1806 Op->EndLoc = E;
1807 return Op;
1808 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001809
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001810 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1811 ARM_AM::ShiftOpc ShiftTy,
1812 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001813 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001814 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001815 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001816 Op->PostIdxReg.isAdd = isAdd;
1817 Op->PostIdxReg.ShiftTy = ShiftTy;
1818 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001819 Op->StartLoc = S;
1820 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001821 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001822 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001823
1824 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001825 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001826 Op->MBOpt.Val = Opt;
1827 Op->StartLoc = S;
1828 Op->EndLoc = S;
1829 return Op;
1830 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001831
1832 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001833 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001834 Op->IFlags.Val = IFlags;
1835 Op->StartLoc = S;
1836 Op->EndLoc = S;
1837 return Op;
1838 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001839
1840 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001841 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001842 Op->MMask.Val = MMask;
1843 Op->StartLoc = S;
1844 Op->EndLoc = S;
1845 return Op;
1846 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001847};
1848
1849} // end anonymous namespace.
1850
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001851void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001852 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001853 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001854 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1855 << ") >";
1856 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001857 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001858 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001859 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001860 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001861 OS << "<ccout " << getReg() << ">";
1862 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001863 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001864 static const char *MaskStr[] = {
1865 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1866 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1867 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001868 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1869 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1870 break;
1871 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001872 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001873 OS << "<coprocessor number: " << getCoproc() << ">";
1874 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001875 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001876 OS << "<coprocessor register: " << getCoproc() << ">";
1877 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001878 case k_CoprocOption:
1879 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1880 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001881 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001882 OS << "<mask: " << getMSRMask() << ">";
1883 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001884 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001885 getImm()->print(OS);
1886 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001887 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001888 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1889 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001890 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001891 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001892 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001893 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001894 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001895 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001896 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1897 << PostIdxReg.RegNum;
1898 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1899 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1900 << PostIdxReg.ShiftImm;
1901 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001902 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001903 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001904 OS << "<ARM_PROC::";
1905 unsigned IFlags = getProcIFlags();
1906 for (int i=2; i >= 0; --i)
1907 if (IFlags & (1 << i))
1908 OS << ARM_PROC::IFlagsToString(1 << i);
1909 OS << ">";
1910 break;
1911 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001913 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001916 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1917 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001918 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001919 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001920 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001921 << RegShiftedReg.SrcReg << " "
1922 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
1923 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001924 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001925 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001926 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001927 << RegShiftedImm.SrcReg << " "
1928 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
1929 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00001930 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001932 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1933 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001934 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001935 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1936 << ", width: " << Bitfield.Width << ">";
1937 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001938 case k_RegisterList:
1939 case k_DPRRegisterList:
1940 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001941 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001942
Bill Wendling5fa22a12010-11-09 23:28:44 +00001943 const SmallVectorImpl<unsigned> &RegList = getRegList();
1944 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001945 I = RegList.begin(), E = RegList.end(); I != E; ) {
1946 OS << *I;
1947 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001948 }
1949
1950 OS << ">";
1951 break;
1952 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001953 case k_VectorList:
1954 OS << "<vector_list " << VectorList.Count << " * "
1955 << VectorList.RegNum << ">";
1956 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001957 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001958 OS << "'" << getToken() << "'";
1959 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001960 case k_VectorIndex:
1961 OS << "<vectorindex " << getVectorIndex() << ">";
1962 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001963 }
1964}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001965
1966/// @name Auto-generated Match Functions
1967/// {
1968
1969static unsigned MatchRegisterName(StringRef Name);
1970
1971/// }
1972
Bob Wilson69df7232011-02-03 21:46:10 +00001973bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1974 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001975 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00001976
1977 return (RegNo == (unsigned)-1);
1978}
1979
Kevin Enderby9c41fa82009-10-30 22:55:57 +00001980/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00001981/// and if it is a register name the token is eaten and the register number is
1982/// returned. Otherwise return -1.
1983///
Jim Grosbach1355cf12011-07-26 17:10:22 +00001984int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00001985 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00001986 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00001987
Chris Lattnere5658fa2010-10-30 04:09:10 +00001988 // FIXME: Validate register for the current architecture; we have to do
1989 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00001990 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00001991 unsigned RegNum = MatchRegisterName(lowerCase);
1992 if (!RegNum) {
1993 RegNum = StringSwitch<unsigned>(lowerCase)
1994 .Case("r13", ARM::SP)
1995 .Case("r14", ARM::LR)
1996 .Case("r15", ARM::PC)
1997 .Case("ip", ARM::R12)
1998 .Default(0);
1999 }
2000 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002001
Chris Lattnere5658fa2010-10-30 04:09:10 +00002002 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002003
Chris Lattnere5658fa2010-10-30 04:09:10 +00002004 return RegNum;
2005}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002006
Jim Grosbach19906722011-07-13 18:49:30 +00002007// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2008// If a recoverable error occurs, return 1. If an irrecoverable error
2009// occurs, return -1. An irrecoverable error is one where tokens have been
2010// consumed in the process of trying to parse the shifter (i.e., when it is
2011// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002012int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002013 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2014 SMLoc S = Parser.getTok().getLoc();
2015 const AsmToken &Tok = Parser.getTok();
2016 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2017
Benjamin Kramer59085362011-11-06 20:37:06 +00002018 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002019 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2020 .Case("lsl", ARM_AM::lsl)
2021 .Case("lsr", ARM_AM::lsr)
2022 .Case("asr", ARM_AM::asr)
2023 .Case("ror", ARM_AM::ror)
2024 .Case("rrx", ARM_AM::rrx)
2025 .Default(ARM_AM::no_shift);
2026
2027 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002028 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002029
Jim Grosbache8606dc2011-07-13 17:50:29 +00002030 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002031
Jim Grosbache8606dc2011-07-13 17:50:29 +00002032 // The source register for the shift has already been added to the
2033 // operand list, so we need to pop it off and combine it into the shifted
2034 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002035 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002036 if (!PrevOp->isReg())
2037 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2038 int SrcReg = PrevOp->getReg();
2039 int64_t Imm = 0;
2040 int ShiftReg = 0;
2041 if (ShiftTy == ARM_AM::rrx) {
2042 // RRX Doesn't have an explicit shift amount. The encoder expects
2043 // the shift register to be the same as the source register. Seems odd,
2044 // but OK.
2045 ShiftReg = SrcReg;
2046 } else {
2047 // Figure out if this is shifted by a constant or a register (for non-RRX).
2048 if (Parser.getTok().is(AsmToken::Hash)) {
2049 Parser.Lex(); // Eat hash.
2050 SMLoc ImmLoc = Parser.getTok().getLoc();
2051 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002052 if (getParser().ParseExpression(ShiftExpr)) {
2053 Error(ImmLoc, "invalid immediate shift value");
2054 return -1;
2055 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002056 // The expression must be evaluatable as an immediate.
2057 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002058 if (!CE) {
2059 Error(ImmLoc, "invalid immediate shift value");
2060 return -1;
2061 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002062 // Range check the immediate.
2063 // lsl, ror: 0 <= imm <= 31
2064 // lsr, asr: 0 <= imm <= 32
2065 Imm = CE->getValue();
2066 if (Imm < 0 ||
2067 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2068 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002069 Error(ImmLoc, "immediate shift value out of range");
2070 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002071 }
2072 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002073 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002074 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002075 if (ShiftReg == -1) {
2076 Error (L, "expected immediate or register in shift operand");
2077 return -1;
2078 }
2079 } else {
2080 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002081 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002082 return -1;
2083 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002084 }
2085
Owen Anderson92a20222011-07-21 18:54:16 +00002086 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2087 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002088 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002089 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002090 else
2091 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2092 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002093
Jim Grosbach19906722011-07-13 18:49:30 +00002094 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002095}
2096
2097
Bill Wendling50d0f582010-11-18 23:43:05 +00002098/// Try to parse a register name. The token must be an Identifier when called.
2099/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2100/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002101///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002102/// TODO this is likely to change to allow different register types and or to
2103/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002104bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002105tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002106 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002107 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002108 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002109 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002110
Bill Wendling50d0f582010-11-18 23:43:05 +00002111 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002112
Chris Lattnere5658fa2010-10-30 04:09:10 +00002113 const AsmToken &ExclaimTok = Parser.getTok();
2114 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002115 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2116 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002117 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002118 return false;
2119 }
2120
2121 // Also check for an index operand. This is only legal for vector registers,
2122 // but that'll get caught OK in operand matching, so we don't need to
2123 // explicitly filter everything else out here.
2124 if (Parser.getTok().is(AsmToken::LBrac)) {
2125 SMLoc SIdx = Parser.getTok().getLoc();
2126 Parser.Lex(); // Eat left bracket token.
2127
2128 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002129 if (getParser().ParseExpression(ImmVal))
2130 return MatchOperand_ParseFail;
2131 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2132 if (!MCE) {
2133 TokError("immediate value expected for vector index");
2134 return MatchOperand_ParseFail;
2135 }
2136
2137 SMLoc E = Parser.getTok().getLoc();
2138 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2139 Error(E, "']' expected");
2140 return MatchOperand_ParseFail;
2141 }
2142
2143 Parser.Lex(); // Eat right bracket token.
2144
2145 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2146 SIdx, E,
2147 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002148 }
2149
Bill Wendling50d0f582010-11-18 23:43:05 +00002150 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002151}
2152
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002153/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2154/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2155/// "c5", ...
2156static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002157 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2158 // but efficient.
2159 switch (Name.size()) {
2160 default: break;
2161 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002162 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002163 return -1;
2164 switch (Name[1]) {
2165 default: return -1;
2166 case '0': return 0;
2167 case '1': return 1;
2168 case '2': return 2;
2169 case '3': return 3;
2170 case '4': return 4;
2171 case '5': return 5;
2172 case '6': return 6;
2173 case '7': return 7;
2174 case '8': return 8;
2175 case '9': return 9;
2176 }
2177 break;
2178 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002179 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002180 return -1;
2181 switch (Name[2]) {
2182 default: return -1;
2183 case '0': return 10;
2184 case '1': return 11;
2185 case '2': return 12;
2186 case '3': return 13;
2187 case '4': return 14;
2188 case '5': return 15;
2189 }
2190 break;
2191 }
2192
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002193 return -1;
2194}
2195
Jim Grosbach89df9962011-08-26 21:43:41 +00002196/// parseITCondCode - Try to parse a condition code for an IT instruction.
2197ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2198parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2199 SMLoc S = Parser.getTok().getLoc();
2200 const AsmToken &Tok = Parser.getTok();
2201 if (!Tok.is(AsmToken::Identifier))
2202 return MatchOperand_NoMatch;
2203 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2204 .Case("eq", ARMCC::EQ)
2205 .Case("ne", ARMCC::NE)
2206 .Case("hs", ARMCC::HS)
2207 .Case("cs", ARMCC::HS)
2208 .Case("lo", ARMCC::LO)
2209 .Case("cc", ARMCC::LO)
2210 .Case("mi", ARMCC::MI)
2211 .Case("pl", ARMCC::PL)
2212 .Case("vs", ARMCC::VS)
2213 .Case("vc", ARMCC::VC)
2214 .Case("hi", ARMCC::HI)
2215 .Case("ls", ARMCC::LS)
2216 .Case("ge", ARMCC::GE)
2217 .Case("lt", ARMCC::LT)
2218 .Case("gt", ARMCC::GT)
2219 .Case("le", ARMCC::LE)
2220 .Case("al", ARMCC::AL)
2221 .Default(~0U);
2222 if (CC == ~0U)
2223 return MatchOperand_NoMatch;
2224 Parser.Lex(); // Eat the token.
2225
2226 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2227
2228 return MatchOperand_Success;
2229}
2230
Jim Grosbach43904292011-07-25 20:14:50 +00002231/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002232/// token must be an Identifier when called, and if it is a coprocessor
2233/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002234ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002235parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002236 SMLoc S = Parser.getTok().getLoc();
2237 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002238 if (Tok.isNot(AsmToken::Identifier))
2239 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002240
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002241 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002242 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002243 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002244
2245 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002246 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002247 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002248}
2249
Jim Grosbach43904292011-07-25 20:14:50 +00002250/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002251/// token must be an Identifier when called, and if it is a coprocessor
2252/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002253ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002254parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002255 SMLoc S = Parser.getTok().getLoc();
2256 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002257 if (Tok.isNot(AsmToken::Identifier))
2258 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002259
2260 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2261 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002262 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002263
2264 Parser.Lex(); // Eat identifier token.
2265 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002266 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002267}
2268
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002269/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2270/// coproc_option : '{' imm0_255 '}'
2271ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2272parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2273 SMLoc S = Parser.getTok().getLoc();
2274
2275 // If this isn't a '{', this isn't a coprocessor immediate operand.
2276 if (Parser.getTok().isNot(AsmToken::LCurly))
2277 return MatchOperand_NoMatch;
2278 Parser.Lex(); // Eat the '{'
2279
2280 const MCExpr *Expr;
2281 SMLoc Loc = Parser.getTok().getLoc();
2282 if (getParser().ParseExpression(Expr)) {
2283 Error(Loc, "illegal expression");
2284 return MatchOperand_ParseFail;
2285 }
2286 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2287 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2288 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2289 return MatchOperand_ParseFail;
2290 }
2291 int Val = CE->getValue();
2292
2293 // Check for and consume the closing '}'
2294 if (Parser.getTok().isNot(AsmToken::RCurly))
2295 return MatchOperand_ParseFail;
2296 SMLoc E = Parser.getTok().getLoc();
2297 Parser.Lex(); // Eat the '}'
2298
2299 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2300 return MatchOperand_Success;
2301}
2302
Jim Grosbachd0588e22011-09-14 18:08:35 +00002303// For register list parsing, we need to map from raw GPR register numbering
2304// to the enumeration values. The enumeration values aren't sorted by
2305// register number due to our using "sp", "lr" and "pc" as canonical names.
2306static unsigned getNextRegister(unsigned Reg) {
2307 // If this is a GPR, we need to do it manually, otherwise we can rely
2308 // on the sort ordering of the enumeration since the other reg-classes
2309 // are sane.
2310 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2311 return Reg + 1;
2312 switch(Reg) {
2313 default: assert(0 && "Invalid GPR number!");
2314 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2315 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2316 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2317 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2318 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2319 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2320 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2321 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2322 }
2323}
2324
Jim Grosbachce485e72011-11-11 21:27:40 +00002325// Return the low-subreg of a given Q register.
2326static unsigned getDRegFromQReg(unsigned QReg) {
2327 switch (QReg) {
2328 default: llvm_unreachable("expected a Q register!");
2329 case ARM::Q0: return ARM::D0;
2330 case ARM::Q1: return ARM::D2;
2331 case ARM::Q2: return ARM::D4;
2332 case ARM::Q3: return ARM::D6;
2333 case ARM::Q4: return ARM::D8;
2334 case ARM::Q5: return ARM::D10;
2335 case ARM::Q6: return ARM::D12;
2336 case ARM::Q7: return ARM::D14;
2337 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002338 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002339 case ARM::Q10: return ARM::D20;
2340 case ARM::Q11: return ARM::D22;
2341 case ARM::Q12: return ARM::D24;
2342 case ARM::Q13: return ARM::D26;
2343 case ARM::Q14: return ARM::D28;
2344 case ARM::Q15: return ARM::D30;
2345 }
2346}
2347
Jim Grosbachd0588e22011-09-14 18:08:35 +00002348/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002349bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002350parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002351 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002352 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002353 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002354 Parser.Lex(); // Eat '{' token.
2355 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002356
Jim Grosbachd0588e22011-09-14 18:08:35 +00002357 // Check the first register in the list to see what register class
2358 // this is a list of.
2359 int Reg = tryParseRegister();
2360 if (Reg == -1)
2361 return Error(RegLoc, "register expected");
2362
Jim Grosbachce485e72011-11-11 21:27:40 +00002363 // The reglist instructions have at most 16 registers, so reserve
2364 // space for that many.
2365 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2366
2367 // Allow Q regs and just interpret them as the two D sub-registers.
2368 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2369 Reg = getDRegFromQReg(Reg);
2370 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2371 ++Reg;
2372 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002373 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002374 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2375 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2376 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2377 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2378 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2379 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2380 else
2381 return Error(RegLoc, "invalid register in register list");
2382
Jim Grosbachce485e72011-11-11 21:27:40 +00002383 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002384 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002385
Jim Grosbachd0588e22011-09-14 18:08:35 +00002386 // This starts immediately after the first register token in the list,
2387 // so we can see either a comma or a minus (range separator) as a legal
2388 // next token.
2389 while (Parser.getTok().is(AsmToken::Comma) ||
2390 Parser.getTok().is(AsmToken::Minus)) {
2391 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002392 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002393 SMLoc EndLoc = Parser.getTok().getLoc();
2394 int EndReg = tryParseRegister();
2395 if (EndReg == -1)
2396 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002397 // Allow Q regs and just interpret them as the two D sub-registers.
2398 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2399 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002400 // If the register is the same as the start reg, there's nothing
2401 // more to do.
2402 if (Reg == EndReg)
2403 continue;
2404 // The register must be in the same register class as the first.
2405 if (!RC->contains(EndReg))
2406 return Error(EndLoc, "invalid register in register list");
2407 // Ranges must go from low to high.
2408 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2409 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002410
Jim Grosbachd0588e22011-09-14 18:08:35 +00002411 // Add all the registers in the range to the register list.
2412 while (Reg != EndReg) {
2413 Reg = getNextRegister(Reg);
2414 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2415 }
2416 continue;
2417 }
2418 Parser.Lex(); // Eat the comma.
2419 RegLoc = Parser.getTok().getLoc();
2420 int OldReg = Reg;
2421 Reg = tryParseRegister();
2422 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002423 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002424 // Allow Q regs and just interpret them as the two D sub-registers.
2425 bool isQReg = false;
2426 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2427 Reg = getDRegFromQReg(Reg);
2428 isQReg = true;
2429 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002430 // The register must be in the same register class as the first.
2431 if (!RC->contains(Reg))
2432 return Error(RegLoc, "invalid register in register list");
2433 // List must be monotonically increasing.
2434 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2435 return Error(RegLoc, "register list not in ascending order");
2436 // VFP register lists must also be contiguous.
2437 // It's OK to use the enumeration values directly here rather, as the
2438 // VFP register classes have the enum sorted properly.
2439 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2440 Reg != OldReg + 1)
2441 return Error(RegLoc, "non-contiguous register range");
2442 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002443 if (isQReg)
2444 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002445 }
2446
Jim Grosbachd0588e22011-09-14 18:08:35 +00002447 SMLoc E = Parser.getTok().getLoc();
2448 if (Parser.getTok().isNot(AsmToken::RCurly))
2449 return Error(E, "'}' expected");
2450 Parser.Lex(); // Eat '}' token.
2451
Bill Wendling50d0f582010-11-18 23:43:05 +00002452 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2453 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002454}
2455
Jim Grosbach862019c2011-10-18 23:02:30 +00002456// parse a vector register list
2457ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2458parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach5c984e42011-11-15 21:45:55 +00002459 SMLoc S = Parser.getTok().getLoc();
2460 // As an extension (to match gas), support a plain D register or Q register
2461 // (without encosing curly braces) as a single or double entry list,
2462 // respectively.
2463 if (Parser.getTok().is(AsmToken::Identifier)) {
2464 int Reg = tryParseRegister();
2465 if (Reg == -1)
2466 return MatchOperand_NoMatch;
2467 SMLoc E = Parser.getTok().getLoc();
2468 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
2469 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2470 return MatchOperand_Success;
2471 }
2472 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2473 Reg = getDRegFromQReg(Reg);
2474 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2475 return MatchOperand_Success;
2476 }
2477 Error(S, "vector register expected");
2478 return MatchOperand_ParseFail;
2479 }
2480
2481 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002482 return MatchOperand_NoMatch;
2483
Jim Grosbach862019c2011-10-18 23:02:30 +00002484 Parser.Lex(); // Eat '{' token.
2485 SMLoc RegLoc = Parser.getTok().getLoc();
2486
2487 int Reg = tryParseRegister();
2488 if (Reg == -1) {
2489 Error(RegLoc, "register expected");
2490 return MatchOperand_ParseFail;
2491 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002492 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002493 unsigned FirstReg = Reg;
2494 // The list is of D registers, but we also allow Q regs and just interpret
2495 // them as the two D sub-registers.
2496 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2497 FirstReg = Reg = getDRegFromQReg(Reg);
2498 ++Reg;
2499 ++Count;
2500 }
2501
Jim Grosbache43862b2011-11-15 23:19:15 +00002502 while (Parser.getTok().is(AsmToken::Comma) ||
2503 Parser.getTok().is(AsmToken::Minus)) {
2504 if (Parser.getTok().is(AsmToken::Minus)) {
2505 Parser.Lex(); // Eat the minus.
2506 SMLoc EndLoc = Parser.getTok().getLoc();
2507 int EndReg = tryParseRegister();
2508 if (EndReg == -1) {
2509 Error(EndLoc, "register expected");
2510 return MatchOperand_ParseFail;
2511 }
2512 // Allow Q regs and just interpret them as the two D sub-registers.
2513 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2514 EndReg = getDRegFromQReg(EndReg) + 1;
2515 // If the register is the same as the start reg, there's nothing
2516 // more to do.
2517 if (Reg == EndReg)
2518 continue;
2519 // The register must be in the same register class as the first.
2520 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2521 Error(EndLoc, "invalid register in register list");
2522 return MatchOperand_ParseFail;
2523 }
2524 // Ranges must go from low to high.
2525 if (Reg > EndReg) {
2526 Error(EndLoc, "bad range in register list");
2527 return MatchOperand_ParseFail;
2528 }
2529
2530 // Add all the registers in the range to the register list.
2531 Count += EndReg - Reg;
2532 Reg = EndReg;
2533 continue;
2534 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002535 Parser.Lex(); // Eat the comma.
2536 RegLoc = Parser.getTok().getLoc();
2537 int OldReg = Reg;
2538 Reg = tryParseRegister();
2539 if (Reg == -1) {
2540 Error(RegLoc, "register expected");
2541 return MatchOperand_ParseFail;
2542 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002543 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002544 // It's OK to use the enumeration values directly here rather, as the
2545 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002546 //
2547 // The list is of D registers, but we also allow Q regs and just interpret
2548 // them as the two D sub-registers.
2549 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2550 Reg = getDRegFromQReg(Reg);
2551 if (Reg != OldReg + 1) {
2552 Error(RegLoc, "non-contiguous register range");
2553 return MatchOperand_ParseFail;
2554 }
2555 ++Reg;
2556 Count += 2;
2557 continue;
2558 }
2559 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002560 if (Reg != OldReg + 1) {
2561 Error(RegLoc, "non-contiguous register range");
2562 return MatchOperand_ParseFail;
2563 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002564 ++Count;
2565 }
2566
2567 SMLoc E = Parser.getTok().getLoc();
2568 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2569 Error(E, "'}' expected");
2570 return MatchOperand_ParseFail;
2571 }
2572 Parser.Lex(); // Eat '}' token.
2573
2574 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2575 return MatchOperand_Success;
2576}
2577
Jim Grosbach43904292011-07-25 20:14:50 +00002578/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002579ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002580parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002581 SMLoc S = Parser.getTok().getLoc();
2582 const AsmToken &Tok = Parser.getTok();
2583 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2584 StringRef OptStr = Tok.getString();
2585
2586 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2587 .Case("sy", ARM_MB::SY)
2588 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002589 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002590 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002591 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002592 .Case("ishst", ARM_MB::ISHST)
2593 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002594 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002595 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002596 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002597 .Case("osh", ARM_MB::OSH)
2598 .Case("oshst", ARM_MB::OSHST)
2599 .Default(~0U);
2600
2601 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002602 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002603
2604 Parser.Lex(); // Eat identifier token.
2605 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002606 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002607}
2608
Jim Grosbach43904292011-07-25 20:14:50 +00002609/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002610ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002611parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002612 SMLoc S = Parser.getTok().getLoc();
2613 const AsmToken &Tok = Parser.getTok();
2614 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2615 StringRef IFlagsStr = Tok.getString();
2616
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002617 // An iflags string of "none" is interpreted to mean that none of the AIF
2618 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002619 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002620 if (IFlagsStr != "none") {
2621 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2622 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2623 .Case("a", ARM_PROC::A)
2624 .Case("i", ARM_PROC::I)
2625 .Case("f", ARM_PROC::F)
2626 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002627
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002628 // If some specific iflag is already set, it means that some letter is
2629 // present more than once, this is not acceptable.
2630 if (Flag == ~0U || (IFlags & Flag))
2631 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002632
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002633 IFlags |= Flag;
2634 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002635 }
2636
2637 Parser.Lex(); // Eat identifier token.
2638 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2639 return MatchOperand_Success;
2640}
2641
Jim Grosbach43904292011-07-25 20:14:50 +00002642/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002643ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002644parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002645 SMLoc S = Parser.getTok().getLoc();
2646 const AsmToken &Tok = Parser.getTok();
2647 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2648 StringRef Mask = Tok.getString();
2649
James Molloyacad68d2011-09-28 14:21:38 +00002650 if (isMClass()) {
2651 // See ARMv6-M 10.1.1
2652 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2653 .Case("apsr", 0)
2654 .Case("iapsr", 1)
2655 .Case("eapsr", 2)
2656 .Case("xpsr", 3)
2657 .Case("ipsr", 5)
2658 .Case("epsr", 6)
2659 .Case("iepsr", 7)
2660 .Case("msp", 8)
2661 .Case("psp", 9)
2662 .Case("primask", 16)
2663 .Case("basepri", 17)
2664 .Case("basepri_max", 18)
2665 .Case("faultmask", 19)
2666 .Case("control", 20)
2667 .Default(~0U);
2668
2669 if (FlagsVal == ~0U)
2670 return MatchOperand_NoMatch;
2671
2672 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2673 // basepri, basepri_max and faultmask only valid for V7m.
2674 return MatchOperand_NoMatch;
2675
2676 Parser.Lex(); // Eat identifier token.
2677 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2678 return MatchOperand_Success;
2679 }
2680
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002681 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2682 size_t Start = 0, Next = Mask.find('_');
2683 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002684 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002685 if (Next != StringRef::npos)
2686 Flags = Mask.slice(Next+1, Mask.size());
2687
2688 // FlagsVal contains the complete mask:
2689 // 3-0: Mask
2690 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2691 unsigned FlagsVal = 0;
2692
2693 if (SpecReg == "apsr") {
2694 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002695 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002696 .Case("g", 0x4) // same as CPSR_s
2697 .Case("nzcvqg", 0xc) // same as CPSR_fs
2698 .Default(~0U);
2699
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002700 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002701 if (!Flags.empty())
2702 return MatchOperand_NoMatch;
2703 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002704 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002705 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002706 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002707 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2708 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002709 for (int i = 0, e = Flags.size(); i != e; ++i) {
2710 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2711 .Case("c", 1)
2712 .Case("x", 2)
2713 .Case("s", 4)
2714 .Case("f", 8)
2715 .Default(~0U);
2716
2717 // If some specific flag is already set, it means that some letter is
2718 // present more than once, this is not acceptable.
2719 if (FlagsVal == ~0U || (FlagsVal & Flag))
2720 return MatchOperand_NoMatch;
2721 FlagsVal |= Flag;
2722 }
2723 } else // No match for special register.
2724 return MatchOperand_NoMatch;
2725
Owen Anderson7784f1d2011-10-21 18:43:28 +00002726 // Special register without flags is NOT equivalent to "fc" flags.
2727 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2728 // two lines would enable gas compatibility at the expense of breaking
2729 // round-tripping.
2730 //
2731 // if (!FlagsVal)
2732 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002733
2734 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2735 if (SpecReg == "spsr")
2736 FlagsVal |= 16;
2737
2738 Parser.Lex(); // Eat identifier token.
2739 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2740 return MatchOperand_Success;
2741}
2742
Jim Grosbachf6c05252011-07-21 17:23:04 +00002743ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2744parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2745 int Low, int High) {
2746 const AsmToken &Tok = Parser.getTok();
2747 if (Tok.isNot(AsmToken::Identifier)) {
2748 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2749 return MatchOperand_ParseFail;
2750 }
2751 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002752 std::string LowerOp = Op.lower();
2753 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002754 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2755 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2756 return MatchOperand_ParseFail;
2757 }
2758 Parser.Lex(); // Eat shift type token.
2759
2760 // There must be a '#' and a shift amount.
2761 if (Parser.getTok().isNot(AsmToken::Hash)) {
2762 Error(Parser.getTok().getLoc(), "'#' expected");
2763 return MatchOperand_ParseFail;
2764 }
2765 Parser.Lex(); // Eat hash token.
2766
2767 const MCExpr *ShiftAmount;
2768 SMLoc Loc = Parser.getTok().getLoc();
2769 if (getParser().ParseExpression(ShiftAmount)) {
2770 Error(Loc, "illegal expression");
2771 return MatchOperand_ParseFail;
2772 }
2773 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2774 if (!CE) {
2775 Error(Loc, "constant expression expected");
2776 return MatchOperand_ParseFail;
2777 }
2778 int Val = CE->getValue();
2779 if (Val < Low || Val > High) {
2780 Error(Loc, "immediate value out of range");
2781 return MatchOperand_ParseFail;
2782 }
2783
2784 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2785
2786 return MatchOperand_Success;
2787}
2788
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002789ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2790parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2791 const AsmToken &Tok = Parser.getTok();
2792 SMLoc S = Tok.getLoc();
2793 if (Tok.isNot(AsmToken::Identifier)) {
2794 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2795 return MatchOperand_ParseFail;
2796 }
2797 int Val = StringSwitch<int>(Tok.getString())
2798 .Case("be", 1)
2799 .Case("le", 0)
2800 .Default(-1);
2801 Parser.Lex(); // Eat the token.
2802
2803 if (Val == -1) {
2804 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2805 return MatchOperand_ParseFail;
2806 }
2807 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2808 getContext()),
2809 S, Parser.getTok().getLoc()));
2810 return MatchOperand_Success;
2811}
2812
Jim Grosbach580f4a92011-07-25 22:20:28 +00002813/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2814/// instructions. Legal values are:
2815/// lsl #n 'n' in [0,31]
2816/// asr #n 'n' in [1,32]
2817/// n == 32 encoded as n == 0.
2818ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2819parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2820 const AsmToken &Tok = Parser.getTok();
2821 SMLoc S = Tok.getLoc();
2822 if (Tok.isNot(AsmToken::Identifier)) {
2823 Error(S, "shift operator 'asr' or 'lsl' expected");
2824 return MatchOperand_ParseFail;
2825 }
2826 StringRef ShiftName = Tok.getString();
2827 bool isASR;
2828 if (ShiftName == "lsl" || ShiftName == "LSL")
2829 isASR = false;
2830 else if (ShiftName == "asr" || ShiftName == "ASR")
2831 isASR = true;
2832 else {
2833 Error(S, "shift operator 'asr' or 'lsl' expected");
2834 return MatchOperand_ParseFail;
2835 }
2836 Parser.Lex(); // Eat the operator.
2837
2838 // A '#' and a shift amount.
2839 if (Parser.getTok().isNot(AsmToken::Hash)) {
2840 Error(Parser.getTok().getLoc(), "'#' expected");
2841 return MatchOperand_ParseFail;
2842 }
2843 Parser.Lex(); // Eat hash token.
2844
2845 const MCExpr *ShiftAmount;
2846 SMLoc E = Parser.getTok().getLoc();
2847 if (getParser().ParseExpression(ShiftAmount)) {
2848 Error(E, "malformed shift expression");
2849 return MatchOperand_ParseFail;
2850 }
2851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2852 if (!CE) {
2853 Error(E, "shift amount must be an immediate");
2854 return MatchOperand_ParseFail;
2855 }
2856
2857 int64_t Val = CE->getValue();
2858 if (isASR) {
2859 // Shift amount must be in [1,32]
2860 if (Val < 1 || Val > 32) {
2861 Error(E, "'asr' shift amount must be in range [1,32]");
2862 return MatchOperand_ParseFail;
2863 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002864 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2865 if (isThumb() && Val == 32) {
2866 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2867 return MatchOperand_ParseFail;
2868 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002869 if (Val == 32) Val = 0;
2870 } else {
2871 // Shift amount must be in [1,32]
2872 if (Val < 0 || Val > 31) {
2873 Error(E, "'lsr' shift amount must be in range [0,31]");
2874 return MatchOperand_ParseFail;
2875 }
2876 }
2877
2878 E = Parser.getTok().getLoc();
2879 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2880
2881 return MatchOperand_Success;
2882}
2883
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002884/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2885/// of instructions. Legal values are:
2886/// ror #n 'n' in {0, 8, 16, 24}
2887ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2888parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2889 const AsmToken &Tok = Parser.getTok();
2890 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002891 if (Tok.isNot(AsmToken::Identifier))
2892 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002893 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002894 if (ShiftName != "ror" && ShiftName != "ROR")
2895 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002896 Parser.Lex(); // Eat the operator.
2897
2898 // A '#' and a rotate amount.
2899 if (Parser.getTok().isNot(AsmToken::Hash)) {
2900 Error(Parser.getTok().getLoc(), "'#' expected");
2901 return MatchOperand_ParseFail;
2902 }
2903 Parser.Lex(); // Eat hash token.
2904
2905 const MCExpr *ShiftAmount;
2906 SMLoc E = Parser.getTok().getLoc();
2907 if (getParser().ParseExpression(ShiftAmount)) {
2908 Error(E, "malformed rotate expression");
2909 return MatchOperand_ParseFail;
2910 }
2911 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2912 if (!CE) {
2913 Error(E, "rotate amount must be an immediate");
2914 return MatchOperand_ParseFail;
2915 }
2916
2917 int64_t Val = CE->getValue();
2918 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2919 // normally, zero is represented in asm by omitting the rotate operand
2920 // entirely.
2921 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2922 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2923 return MatchOperand_ParseFail;
2924 }
2925
2926 E = Parser.getTok().getLoc();
2927 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2928
2929 return MatchOperand_Success;
2930}
2931
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002932ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2933parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2934 SMLoc S = Parser.getTok().getLoc();
2935 // The bitfield descriptor is really two operands, the LSB and the width.
2936 if (Parser.getTok().isNot(AsmToken::Hash)) {
2937 Error(Parser.getTok().getLoc(), "'#' expected");
2938 return MatchOperand_ParseFail;
2939 }
2940 Parser.Lex(); // Eat hash token.
2941
2942 const MCExpr *LSBExpr;
2943 SMLoc E = Parser.getTok().getLoc();
2944 if (getParser().ParseExpression(LSBExpr)) {
2945 Error(E, "malformed immediate expression");
2946 return MatchOperand_ParseFail;
2947 }
2948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2949 if (!CE) {
2950 Error(E, "'lsb' operand must be an immediate");
2951 return MatchOperand_ParseFail;
2952 }
2953
2954 int64_t LSB = CE->getValue();
2955 // The LSB must be in the range [0,31]
2956 if (LSB < 0 || LSB > 31) {
2957 Error(E, "'lsb' operand must be in the range [0,31]");
2958 return MatchOperand_ParseFail;
2959 }
2960 E = Parser.getTok().getLoc();
2961
2962 // Expect another immediate operand.
2963 if (Parser.getTok().isNot(AsmToken::Comma)) {
2964 Error(Parser.getTok().getLoc(), "too few operands");
2965 return MatchOperand_ParseFail;
2966 }
2967 Parser.Lex(); // Eat hash token.
2968 if (Parser.getTok().isNot(AsmToken::Hash)) {
2969 Error(Parser.getTok().getLoc(), "'#' expected");
2970 return MatchOperand_ParseFail;
2971 }
2972 Parser.Lex(); // Eat hash token.
2973
2974 const MCExpr *WidthExpr;
2975 if (getParser().ParseExpression(WidthExpr)) {
2976 Error(E, "malformed immediate expression");
2977 return MatchOperand_ParseFail;
2978 }
2979 CE = dyn_cast<MCConstantExpr>(WidthExpr);
2980 if (!CE) {
2981 Error(E, "'width' operand must be an immediate");
2982 return MatchOperand_ParseFail;
2983 }
2984
2985 int64_t Width = CE->getValue();
2986 // The LSB must be in the range [1,32-lsb]
2987 if (Width < 1 || Width > 32 - LSB) {
2988 Error(E, "'width' operand must be in the range [1,32-lsb]");
2989 return MatchOperand_ParseFail;
2990 }
2991 E = Parser.getTok().getLoc();
2992
2993 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
2994
2995 return MatchOperand_Success;
2996}
2997
Jim Grosbach7ce05792011-08-03 23:50:40 +00002998ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2999parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3000 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003001 // postidx_reg := '+' register {, shift}
3002 // | '-' register {, shift}
3003 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003004
3005 // This method must return MatchOperand_NoMatch without consuming any tokens
3006 // in the case where there is no match, as other alternatives take other
3007 // parse methods.
3008 AsmToken Tok = Parser.getTok();
3009 SMLoc S = Tok.getLoc();
3010 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003011 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003012 int Reg = -1;
3013 if (Tok.is(AsmToken::Plus)) {
3014 Parser.Lex(); // Eat the '+' token.
3015 haveEaten = true;
3016 } else if (Tok.is(AsmToken::Minus)) {
3017 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003018 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003019 haveEaten = true;
3020 }
3021 if (Parser.getTok().is(AsmToken::Identifier))
3022 Reg = tryParseRegister();
3023 if (Reg == -1) {
3024 if (!haveEaten)
3025 return MatchOperand_NoMatch;
3026 Error(Parser.getTok().getLoc(), "register expected");
3027 return MatchOperand_ParseFail;
3028 }
3029 SMLoc E = Parser.getTok().getLoc();
3030
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003031 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3032 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003033 if (Parser.getTok().is(AsmToken::Comma)) {
3034 Parser.Lex(); // Eat the ','.
3035 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3036 return MatchOperand_ParseFail;
3037 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003038
3039 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3040 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003041
3042 return MatchOperand_Success;
3043}
3044
Jim Grosbach251bf252011-08-10 21:56:18 +00003045ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3046parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3047 // Check for a post-index addressing register operand. Specifically:
3048 // am3offset := '+' register
3049 // | '-' register
3050 // | register
3051 // | # imm
3052 // | # + imm
3053 // | # - imm
3054
3055 // This method must return MatchOperand_NoMatch without consuming any tokens
3056 // in the case where there is no match, as other alternatives take other
3057 // parse methods.
3058 AsmToken Tok = Parser.getTok();
3059 SMLoc S = Tok.getLoc();
3060
3061 // Do immediates first, as we always parse those if we have a '#'.
3062 if (Parser.getTok().is(AsmToken::Hash)) {
3063 Parser.Lex(); // Eat the '#'.
3064 // Explicitly look for a '-', as we need to encode negative zero
3065 // differently.
3066 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3067 const MCExpr *Offset;
3068 if (getParser().ParseExpression(Offset))
3069 return MatchOperand_ParseFail;
3070 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3071 if (!CE) {
3072 Error(S, "constant expression expected");
3073 return MatchOperand_ParseFail;
3074 }
3075 SMLoc E = Tok.getLoc();
3076 // Negative zero is encoded as the flag value INT32_MIN.
3077 int32_t Val = CE->getValue();
3078 if (isNegative && Val == 0)
3079 Val = INT32_MIN;
3080
3081 Operands.push_back(
3082 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3083
3084 return MatchOperand_Success;
3085 }
3086
3087
3088 bool haveEaten = false;
3089 bool isAdd = true;
3090 int Reg = -1;
3091 if (Tok.is(AsmToken::Plus)) {
3092 Parser.Lex(); // Eat the '+' token.
3093 haveEaten = true;
3094 } else if (Tok.is(AsmToken::Minus)) {
3095 Parser.Lex(); // Eat the '-' token.
3096 isAdd = false;
3097 haveEaten = true;
3098 }
3099 if (Parser.getTok().is(AsmToken::Identifier))
3100 Reg = tryParseRegister();
3101 if (Reg == -1) {
3102 if (!haveEaten)
3103 return MatchOperand_NoMatch;
3104 Error(Parser.getTok().getLoc(), "register expected");
3105 return MatchOperand_ParseFail;
3106 }
3107 SMLoc E = Parser.getTok().getLoc();
3108
3109 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3110 0, S, E));
3111
3112 return MatchOperand_Success;
3113}
3114
Jim Grosbacha77295d2011-09-08 22:07:06 +00003115/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3116/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3117/// when they refer multiple MIOperands inside a single one.
3118bool ARMAsmParser::
3119cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3120 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3121 // Rt, Rt2
3122 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3123 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3124 // Create a writeback register dummy placeholder.
3125 Inst.addOperand(MCOperand::CreateReg(0));
3126 // addr
3127 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3128 // pred
3129 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3130 return true;
3131}
3132
3133/// cvtT2StrdPre - Convert parsed operands to MCInst.
3134/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3135/// when they refer multiple MIOperands inside a single one.
3136bool ARMAsmParser::
3137cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3138 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3139 // Create a writeback register dummy placeholder.
3140 Inst.addOperand(MCOperand::CreateReg(0));
3141 // Rt, Rt2
3142 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3143 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3144 // addr
3145 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3146 // pred
3147 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3148 return true;
3149}
3150
Jim Grosbacheeec0252011-09-08 00:39:19 +00003151/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3152/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3153/// when they refer multiple MIOperands inside a single one.
3154bool ARMAsmParser::
3155cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3156 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3157 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3158
3159 // Create a writeback register dummy placeholder.
3160 Inst.addOperand(MCOperand::CreateImm(0));
3161
3162 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3163 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3164 return true;
3165}
3166
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003167/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3168/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3169/// when they refer multiple MIOperands inside a single one.
3170bool ARMAsmParser::
3171cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3172 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3173 // Create a writeback register dummy placeholder.
3174 Inst.addOperand(MCOperand::CreateImm(0));
3175 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3176 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3177 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3178 return true;
3179}
3180
Jim Grosbach1355cf12011-07-26 17:10:22 +00003181/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003182/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3183/// when they refer multiple MIOperands inside a single one.
3184bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003185cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003186 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3187 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3188
3189 // Create a writeback register dummy placeholder.
3190 Inst.addOperand(MCOperand::CreateImm(0));
3191
Jim Grosbach7ce05792011-08-03 23:50:40 +00003192 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003193 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3194 return true;
3195}
3196
Owen Anderson9ab0f252011-08-26 20:43:14 +00003197/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3198/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3199/// when they refer multiple MIOperands inside a single one.
3200bool ARMAsmParser::
3201cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3202 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3203 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3204
3205 // Create a writeback register dummy placeholder.
3206 Inst.addOperand(MCOperand::CreateImm(0));
3207
3208 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3209 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3210 return true;
3211}
3212
3213
Jim Grosbach548340c2011-08-11 19:22:40 +00003214/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3215/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3216/// when they refer multiple MIOperands inside a single one.
3217bool ARMAsmParser::
3218cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3219 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3220 // Create a writeback register dummy placeholder.
3221 Inst.addOperand(MCOperand::CreateImm(0));
3222 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3223 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3224 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3225 return true;
3226}
3227
Jim Grosbach1355cf12011-07-26 17:10:22 +00003228/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003229/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3230/// when they refer multiple MIOperands inside a single one.
3231bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003232cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003233 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3234 // Create a writeback register dummy placeholder.
3235 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003236 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3237 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3238 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003239 return true;
3240}
3241
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003242/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3243/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3244/// when they refer multiple MIOperands inside a single one.
3245bool ARMAsmParser::
3246cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3247 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3248 // Create a writeback register dummy placeholder.
3249 Inst.addOperand(MCOperand::CreateImm(0));
3250 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3251 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3252 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3253 return true;
3254}
3255
Jim Grosbach7ce05792011-08-03 23:50:40 +00003256/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3257/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3258/// when they refer multiple MIOperands inside a single one.
3259bool ARMAsmParser::
3260cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3261 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3262 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003263 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003264 // Create a writeback register dummy placeholder.
3265 Inst.addOperand(MCOperand::CreateImm(0));
3266 // addr
3267 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3268 // offset
3269 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3270 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003271 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3272 return true;
3273}
3274
Jim Grosbach7ce05792011-08-03 23:50:40 +00003275/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003276/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3277/// when they refer multiple MIOperands inside a single one.
3278bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003279cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3280 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3281 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003282 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003283 // Create a writeback register dummy placeholder.
3284 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003285 // addr
3286 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3287 // offset
3288 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3289 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003290 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3291 return true;
3292}
3293
Jim Grosbach7ce05792011-08-03 23:50:40 +00003294/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003295/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3296/// when they refer multiple MIOperands inside a single one.
3297bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003298cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3299 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003300 // Create a writeback register dummy placeholder.
3301 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003302 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003303 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003304 // addr
3305 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3306 // offset
3307 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3308 // pred
3309 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3310 return true;
3311}
3312
3313/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3314/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3315/// when they refer multiple MIOperands inside a single one.
3316bool ARMAsmParser::
3317cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3318 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3319 // Create a writeback register dummy placeholder.
3320 Inst.addOperand(MCOperand::CreateImm(0));
3321 // Rt
3322 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3323 // addr
3324 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3325 // offset
3326 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3327 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003328 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3329 return true;
3330}
3331
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003332/// cvtLdrdPre - Convert parsed operands to MCInst.
3333/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3334/// when they refer multiple MIOperands inside a single one.
3335bool ARMAsmParser::
3336cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3337 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3338 // Rt, Rt2
3339 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3340 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3341 // Create a writeback register dummy placeholder.
3342 Inst.addOperand(MCOperand::CreateImm(0));
3343 // addr
3344 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3345 // pred
3346 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3347 return true;
3348}
3349
Jim Grosbach14605d12011-08-11 20:28:23 +00003350/// cvtStrdPre - Convert parsed operands to MCInst.
3351/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3352/// when they refer multiple MIOperands inside a single one.
3353bool ARMAsmParser::
3354cvtStrdPre(MCInst &Inst, unsigned Opcode,
3355 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3356 // Create a writeback register dummy placeholder.
3357 Inst.addOperand(MCOperand::CreateImm(0));
3358 // Rt, Rt2
3359 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3360 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3361 // addr
3362 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3363 // pred
3364 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3365 return true;
3366}
3367
Jim Grosbach623a4542011-08-10 22:42:16 +00003368/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3369/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3370/// when they refer multiple MIOperands inside a single one.
3371bool ARMAsmParser::
3372cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3373 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3374 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3375 // Create a writeback register dummy placeholder.
3376 Inst.addOperand(MCOperand::CreateImm(0));
3377 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3378 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3379 return true;
3380}
3381
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003382/// cvtThumbMultiple- Convert parsed operands to MCInst.
3383/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3384/// when they refer multiple MIOperands inside a single one.
3385bool ARMAsmParser::
3386cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3387 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3388 // The second source operand must be the same register as the destination
3389 // operand.
3390 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003391 (((ARMOperand*)Operands[3])->getReg() !=
3392 ((ARMOperand*)Operands[5])->getReg()) &&
3393 (((ARMOperand*)Operands[3])->getReg() !=
3394 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003395 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003396 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003397 return false;
3398 }
3399 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3400 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003401 // If we have a three-operand form, make sure to set Rn to be the operand
3402 // that isn't the same as Rd.
3403 unsigned RegOp = 4;
3404 if (Operands.size() == 6 &&
3405 ((ARMOperand*)Operands[4])->getReg() ==
3406 ((ARMOperand*)Operands[3])->getReg())
3407 RegOp = 5;
3408 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3409 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003410 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3411
3412 return true;
3413}
Jim Grosbach623a4542011-08-10 22:42:16 +00003414
Jim Grosbach12431322011-10-24 22:16:58 +00003415bool ARMAsmParser::
3416cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3417 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3418 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003419 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003420 // Create a writeback register dummy placeholder.
3421 Inst.addOperand(MCOperand::CreateImm(0));
3422 // Vn
3423 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3424 // pred
3425 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3426 return true;
3427}
3428
3429bool ARMAsmParser::
3430cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3431 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3432 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003433 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003434 // Create a writeback register dummy placeholder.
3435 Inst.addOperand(MCOperand::CreateImm(0));
3436 // Vn
3437 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3438 // Vm
3439 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3440 // pred
3441 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3442 return true;
3443}
3444
Jim Grosbach4334e032011-10-31 21:50:31 +00003445bool ARMAsmParser::
3446cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3447 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3448 // Create a writeback register dummy placeholder.
3449 Inst.addOperand(MCOperand::CreateImm(0));
3450 // Vn
3451 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3452 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003453 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003454 // pred
3455 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3456 return true;
3457}
3458
3459bool ARMAsmParser::
3460cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3461 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3462 // Create a writeback register dummy placeholder.
3463 Inst.addOperand(MCOperand::CreateImm(0));
3464 // Vn
3465 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3466 // Vm
3467 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3468 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003469 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003470 // pred
3471 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3472 return true;
3473}
3474
Bill Wendlinge7176102010-11-06 22:36:58 +00003475/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003476/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003477bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003478parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003479 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003480 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003481 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003482 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003483 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003484
Sean Callanan18b83232010-01-19 21:44:56 +00003485 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003486 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003487 if (BaseRegNum == -1)
3488 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003489
Daniel Dunbar05710932011-01-18 05:34:17 +00003490 // The next token must either be a comma or a closing bracket.
3491 const AsmToken &Tok = Parser.getTok();
3492 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003493 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003494
Jim Grosbach7ce05792011-08-03 23:50:40 +00003495 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003496 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003497 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003498
Jim Grosbach7ce05792011-08-03 23:50:40 +00003499 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003500 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003501
Jim Grosbachfb12f352011-09-19 18:42:21 +00003502 // If there's a pre-indexing writeback marker, '!', just add it as a token
3503 // operand. It's rather odd, but syntactically valid.
3504 if (Parser.getTok().is(AsmToken::Exclaim)) {
3505 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3506 Parser.Lex(); // Eat the '!'.
3507 }
3508
Jim Grosbach7ce05792011-08-03 23:50:40 +00003509 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003510 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003511
Jim Grosbach7ce05792011-08-03 23:50:40 +00003512 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3513 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003514
Jim Grosbach57dcb852011-10-11 17:29:55 +00003515 // If we have a ':', it's an alignment specifier.
3516 if (Parser.getTok().is(AsmToken::Colon)) {
3517 Parser.Lex(); // Eat the ':'.
3518 E = Parser.getTok().getLoc();
3519
3520 const MCExpr *Expr;
3521 if (getParser().ParseExpression(Expr))
3522 return true;
3523
3524 // The expression has to be a constant. Memory references with relocations
3525 // don't come through here, as they use the <label> forms of the relevant
3526 // instructions.
3527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3528 if (!CE)
3529 return Error (E, "constant expression expected");
3530
3531 unsigned Align = 0;
3532 switch (CE->getValue()) {
3533 default:
3534 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3535 case 64: Align = 8; break;
3536 case 128: Align = 16; break;
3537 case 256: Align = 32; break;
3538 }
3539
3540 // Now we should have the closing ']'
3541 E = Parser.getTok().getLoc();
3542 if (Parser.getTok().isNot(AsmToken::RBrac))
3543 return Error(E, "']' expected");
3544 Parser.Lex(); // Eat right bracket token.
3545
3546 // Don't worry about range checking the value here. That's handled by
3547 // the is*() predicates.
3548 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3549 ARM_AM::no_shift, 0, Align,
3550 false, S, E));
3551
3552 // If there's a pre-indexing writeback marker, '!', just add it as a token
3553 // operand.
3554 if (Parser.getTok().is(AsmToken::Exclaim)) {
3555 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3556 Parser.Lex(); // Eat the '!'.
3557 }
3558
3559 return false;
3560 }
3561
3562 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003563 // offset. Be friendly and also accept a plain integer (without a leading
3564 // hash) for gas compatibility.
3565 if (Parser.getTok().is(AsmToken::Hash) ||
3566 Parser.getTok().is(AsmToken::Integer)) {
3567 if (Parser.getTok().is(AsmToken::Hash))
3568 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003569 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003570
Owen Anderson0da10cf2011-08-29 19:36:44 +00003571 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003572 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003573 if (getParser().ParseExpression(Offset))
3574 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003575
3576 // The expression has to be a constant. Memory references with relocations
3577 // don't come through here, as they use the <label> forms of the relevant
3578 // instructions.
3579 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3580 if (!CE)
3581 return Error (E, "constant expression expected");
3582
Owen Anderson0da10cf2011-08-29 19:36:44 +00003583 // If the constant was #-0, represent it as INT32_MIN.
3584 int32_t Val = CE->getValue();
3585 if (isNegative && Val == 0)
3586 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3587
Jim Grosbach7ce05792011-08-03 23:50:40 +00003588 // Now we should have the closing ']'
3589 E = Parser.getTok().getLoc();
3590 if (Parser.getTok().isNot(AsmToken::RBrac))
3591 return Error(E, "']' expected");
3592 Parser.Lex(); // Eat right bracket token.
3593
3594 // Don't worry about range checking the value here. That's handled by
3595 // the is*() predicates.
3596 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003597 ARM_AM::no_shift, 0, 0,
3598 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003599
3600 // If there's a pre-indexing writeback marker, '!', just add it as a token
3601 // operand.
3602 if (Parser.getTok().is(AsmToken::Exclaim)) {
3603 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3604 Parser.Lex(); // Eat the '!'.
3605 }
3606
3607 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003608 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003609
3610 // The register offset is optionally preceded by a '+' or '-'
3611 bool isNegative = false;
3612 if (Parser.getTok().is(AsmToken::Minus)) {
3613 isNegative = true;
3614 Parser.Lex(); // Eat the '-'.
3615 } else if (Parser.getTok().is(AsmToken::Plus)) {
3616 // Nothing to do.
3617 Parser.Lex(); // Eat the '+'.
3618 }
3619
3620 E = Parser.getTok().getLoc();
3621 int OffsetRegNum = tryParseRegister();
3622 if (OffsetRegNum == -1)
3623 return Error(E, "register expected");
3624
3625 // If there's a shift operator, handle it.
3626 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003627 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003628 if (Parser.getTok().is(AsmToken::Comma)) {
3629 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003630 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003631 return true;
3632 }
3633
3634 // Now we should have the closing ']'
3635 E = Parser.getTok().getLoc();
3636 if (Parser.getTok().isNot(AsmToken::RBrac))
3637 return Error(E, "']' expected");
3638 Parser.Lex(); // Eat right bracket token.
3639
3640 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003641 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003642 S, E));
3643
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003644 // If there's a pre-indexing writeback marker, '!', just add it as a token
3645 // operand.
3646 if (Parser.getTok().is(AsmToken::Exclaim)) {
3647 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3648 Parser.Lex(); // Eat the '!'.
3649 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003650
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003651 return false;
3652}
3653
Jim Grosbach7ce05792011-08-03 23:50:40 +00003654/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003655/// ( lsl | lsr | asr | ror ) , # shift_amount
3656/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003657/// return true if it parses a shift otherwise it returns false.
3658bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3659 unsigned &Amount) {
3660 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003661 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003662 if (Tok.isNot(AsmToken::Identifier))
3663 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003664 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003665 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003666 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003667 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003668 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003669 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003670 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003671 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003672 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003673 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003674 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003675 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003676 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003677 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003678
Jim Grosbach7ce05792011-08-03 23:50:40 +00003679 // rrx stands alone.
3680 Amount = 0;
3681 if (St != ARM_AM::rrx) {
3682 Loc = Parser.getTok().getLoc();
3683 // A '#' and a shift amount.
3684 const AsmToken &HashTok = Parser.getTok();
3685 if (HashTok.isNot(AsmToken::Hash))
3686 return Error(HashTok.getLoc(), "'#' expected");
3687 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003688
Jim Grosbach7ce05792011-08-03 23:50:40 +00003689 const MCExpr *Expr;
3690 if (getParser().ParseExpression(Expr))
3691 return true;
3692 // Range check the immediate.
3693 // lsl, ror: 0 <= imm <= 31
3694 // lsr, asr: 0 <= imm <= 32
3695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3696 if (!CE)
3697 return Error(Loc, "shift amount must be an immediate");
3698 int64_t Imm = CE->getValue();
3699 if (Imm < 0 ||
3700 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3701 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3702 return Error(Loc, "immediate shift value out of range");
3703 Amount = Imm;
3704 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003705
3706 return false;
3707}
3708
Jim Grosbach9d390362011-10-03 23:38:36 +00003709/// parseFPImm - A floating point immediate expression operand.
3710ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3711parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3712 SMLoc S = Parser.getTok().getLoc();
3713
3714 if (Parser.getTok().isNot(AsmToken::Hash))
3715 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003716
3717 // Disambiguate the VMOV forms that can accept an FP immediate.
3718 // vmov.f32 <sreg>, #imm
3719 // vmov.f64 <dreg>, #imm
3720 // vmov.f32 <dreg>, #imm @ vector f32x2
3721 // vmov.f32 <qreg>, #imm @ vector f32x4
3722 //
3723 // There are also the NEON VMOV instructions which expect an
3724 // integer constant. Make sure we don't try to parse an FPImm
3725 // for these:
3726 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3727 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3728 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3729 TyOp->getToken() != ".f64"))
3730 return MatchOperand_NoMatch;
3731
Jim Grosbach9d390362011-10-03 23:38:36 +00003732 Parser.Lex(); // Eat the '#'.
3733
3734 // Handle negation, as that still comes through as a separate token.
3735 bool isNegative = false;
3736 if (Parser.getTok().is(AsmToken::Minus)) {
3737 isNegative = true;
3738 Parser.Lex();
3739 }
3740 const AsmToken &Tok = Parser.getTok();
3741 if (Tok.is(AsmToken::Real)) {
3742 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3743 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3744 // If we had a '-' in front, toggle the sign bit.
3745 IntVal ^= (uint64_t)isNegative << 63;
3746 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3747 Parser.Lex(); // Eat the token.
3748 if (Val == -1) {
3749 TokError("floating point value out of range");
3750 return MatchOperand_ParseFail;
3751 }
3752 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3753 return MatchOperand_Success;
3754 }
3755 if (Tok.is(AsmToken::Integer)) {
3756 int64_t Val = Tok.getIntVal();
3757 Parser.Lex(); // Eat the token.
3758 if (Val > 255 || Val < 0) {
3759 TokError("encoded floating point value out of range");
3760 return MatchOperand_ParseFail;
3761 }
3762 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3763 return MatchOperand_Success;
3764 }
3765
3766 TokError("invalid floating point immediate");
3767 return MatchOperand_ParseFail;
3768}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003769/// Parse a arm instruction operand. For now this parses the operand regardless
3770/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003771bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003772 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003773 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003774
3775 // Check if the current operand has a custom associated parser, if so, try to
3776 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003777 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3778 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003779 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003780 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3781 // there was a match, but an error occurred, in which case, just return that
3782 // the operand parsing failed.
3783 if (ResTy == MatchOperand_ParseFail)
3784 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003785
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003786 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003787 default:
3788 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003789 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003790 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003791 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003792 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003793 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003794 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003795 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003796 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003797 else if (Res == -1) // irrecoverable error
3798 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003799 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3800 S = Parser.getTok().getLoc();
3801 Parser.Lex();
3802 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3803 return false;
3804 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003805
3806 // Fall though for the Identifier case that is not a register or a
3807 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003808 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003809 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003810 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003811 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003812 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003813 // This was not a register so parse other operands that start with an
3814 // identifier (like labels) as expressions and create them as immediates.
3815 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003816 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003817 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003818 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003819 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003820 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3821 return false;
3822 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003823 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003824 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003825 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003826 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003827 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003828 // #42 -> immediate.
3829 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003830 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003831 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003832 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003833 const MCExpr *ImmVal;
3834 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003835 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003836 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003837 if (CE) {
3838 int32_t Val = CE->getValue();
3839 if (isNegative && Val == 0)
3840 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003841 }
Sean Callanan76264762010-04-02 22:27:05 +00003842 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003843 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3844 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003845 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003846 case AsmToken::Colon: {
3847 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003848 // FIXME: Check it's an expression prefix,
3849 // e.g. (FOO - :lower16:BAR) isn't legal.
3850 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003851 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003852 return true;
3853
Evan Cheng75972122011-01-13 07:58:56 +00003854 const MCExpr *SubExprVal;
3855 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003856 return true;
3857
Evan Cheng75972122011-01-13 07:58:56 +00003858 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3859 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003860 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003861 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003862 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003863 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003864 }
3865}
3866
Jim Grosbach1355cf12011-07-26 17:10:22 +00003867// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003868// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003869bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003870 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003871
3872 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003873 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003874 Parser.Lex(); // Eat ':'
3875
3876 if (getLexer().isNot(AsmToken::Identifier)) {
3877 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3878 return true;
3879 }
3880
3881 StringRef IDVal = Parser.getTok().getIdentifier();
3882 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003883 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003884 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003885 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003886 } else {
3887 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3888 return true;
3889 }
3890 Parser.Lex();
3891
3892 if (getLexer().isNot(AsmToken::Colon)) {
3893 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3894 return true;
3895 }
3896 Parser.Lex(); // Eat the last ':'
3897 return false;
3898}
3899
Daniel Dunbar352e1482011-01-11 15:59:50 +00003900/// \brief Given a mnemonic, split out possible predication code and carry
3901/// setting letters to form a canonical mnemonic and flags.
3902//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003903// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003904// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003905StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003906 unsigned &PredicationCode,
3907 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003908 unsigned &ProcessorIMod,
3909 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003910 PredicationCode = ARMCC::AL;
3911 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003912 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003913
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003914 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003915 //
3916 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003917 if ((Mnemonic == "movs" && isThumb()) ||
3918 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3919 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3920 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3921 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3922 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3923 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3924 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003925 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003926
Jim Grosbach3f00e312011-07-11 17:09:57 +00003927 // First, split out any predication code. Ignore mnemonics we know aren't
3928 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003929 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003930 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003931 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003932 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003933 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3934 .Case("eq", ARMCC::EQ)
3935 .Case("ne", ARMCC::NE)
3936 .Case("hs", ARMCC::HS)
3937 .Case("cs", ARMCC::HS)
3938 .Case("lo", ARMCC::LO)
3939 .Case("cc", ARMCC::LO)
3940 .Case("mi", ARMCC::MI)
3941 .Case("pl", ARMCC::PL)
3942 .Case("vs", ARMCC::VS)
3943 .Case("vc", ARMCC::VC)
3944 .Case("hi", ARMCC::HI)
3945 .Case("ls", ARMCC::LS)
3946 .Case("ge", ARMCC::GE)
3947 .Case("lt", ARMCC::LT)
3948 .Case("gt", ARMCC::GT)
3949 .Case("le", ARMCC::LE)
3950 .Case("al", ARMCC::AL)
3951 .Default(~0U);
3952 if (CC != ~0U) {
3953 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3954 PredicationCode = CC;
3955 }
Bill Wendling52925b62010-10-29 23:50:21 +00003956 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003957
Daniel Dunbar352e1482011-01-11 15:59:50 +00003958 // Next, determine if we have a carry setting bit. We explicitly ignore all
3959 // the instructions we know end in 's'.
3960 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003961 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003962 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3963 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3964 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003965 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3966 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003967 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3968 CarrySetting = true;
3969 }
3970
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003971 // The "cps" instruction can have a interrupt mode operand which is glued into
3972 // the mnemonic. Check if this is the case, split it and parse the imod op
3973 if (Mnemonic.startswith("cps")) {
3974 // Split out any imod code.
3975 unsigned IMod =
3976 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
3977 .Case("ie", ARM_PROC::IE)
3978 .Case("id", ARM_PROC::ID)
3979 .Default(~0U);
3980 if (IMod != ~0U) {
3981 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
3982 ProcessorIMod = IMod;
3983 }
3984 }
3985
Jim Grosbach89df9962011-08-26 21:43:41 +00003986 // The "it" instruction has the condition mask on the end of the mnemonic.
3987 if (Mnemonic.startswith("it")) {
3988 ITMask = Mnemonic.slice(2, Mnemonic.size());
3989 Mnemonic = Mnemonic.slice(0, 2);
3990 }
3991
Daniel Dunbar352e1482011-01-11 15:59:50 +00003992 return Mnemonic;
3993}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00003994
3995/// \brief Given a canonical mnemonic, determine if the instruction ever allows
3996/// inclusion of carry set or predication code operands.
3997//
3998// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00003999void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004000getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004001 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004002 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4003 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004004 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004005 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004006 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004007 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004008 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004009 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004010 Mnemonic == "mla" || Mnemonic == "smlal" ||
4011 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004012 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004013 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004014 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004015
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004016 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4017 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4018 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4019 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004020 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4021 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004022 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004023 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4024 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4025 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004026 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4027 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004028 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004029 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004030 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004031 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004032
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004033 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004034 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004035 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004036 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004037 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004038}
4039
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004040bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4041 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004042 // FIXME: This is all horribly hacky. We really need a better way to deal
4043 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004044
4045 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4046 // another does not. Specifically, the MOVW instruction does not. So we
4047 // special case it here and remove the defaulted (non-setting) cc_out
4048 // operand if that's the instruction we're trying to match.
4049 //
4050 // We do this as post-processing of the explicit operands rather than just
4051 // conditionally adding the cc_out in the first place because we need
4052 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004053 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004054 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4055 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4056 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4057 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004058
4059 // Register-register 'add' for thumb does not have a cc_out operand
4060 // when there are only two register operands.
4061 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4062 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4063 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4064 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4065 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004066 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004067 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4068 // have to check the immediate range here since Thumb2 has a variant
4069 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004070 if (((isThumb() && Mnemonic == "add") ||
4071 (isThumbTwo() && Mnemonic == "sub")) &&
4072 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004073 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4074 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4075 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004076 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4077 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4078 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004079 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004080 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4081 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004082 // selecting via the generic "add" mnemonic, so to know that we
4083 // should remove the cc_out operand, we have to explicitly check that
4084 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004085 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4086 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004087 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4088 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4089 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4090 // Nest conditions rather than one big 'if' statement for readability.
4091 //
4092 // If either register is a high reg, it's either one of the SP
4093 // variants (handled above) or a 32-bit encoding, so we just
4094 // check against T3.
4095 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4096 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4097 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4098 return false;
4099 // If both registers are low, we're in an IT block, and the immediate is
4100 // in range, we should use encoding T1 instead, which has a cc_out.
4101 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004102 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004103 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4104 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4105 return false;
4106
4107 // Otherwise, we use encoding T4, which does not have a cc_out
4108 // operand.
4109 return true;
4110 }
4111
Jim Grosbach64944f42011-09-14 21:00:40 +00004112 // The thumb2 multiply instruction doesn't have a CCOut register, so
4113 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4114 // use the 16-bit encoding or not.
4115 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4116 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4117 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4118 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4119 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4120 // If the registers aren't low regs, the destination reg isn't the
4121 // same as one of the source regs, or the cc_out operand is zero
4122 // outside of an IT block, we have to use the 32-bit encoding, so
4123 // remove the cc_out operand.
4124 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4125 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004126 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004127 !inITBlock() ||
4128 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4129 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4130 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4131 static_cast<ARMOperand*>(Operands[4])->getReg())))
4132 return true;
4133
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004134 // Also check the 'mul' syntax variant that doesn't specify an explicit
4135 // destination register.
4136 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4137 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4138 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4139 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4140 // If the registers aren't low regs or the cc_out operand is zero
4141 // outside of an IT block, we have to use the 32-bit encoding, so
4142 // remove the cc_out operand.
4143 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4144 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4145 !inITBlock()))
4146 return true;
4147
Jim Grosbach64944f42011-09-14 21:00:40 +00004148
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004149
Jim Grosbachf69c8042011-08-24 21:42:27 +00004150 // Register-register 'add/sub' for thumb does not have a cc_out operand
4151 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4152 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4153 // right, this will result in better diagnostics (which operand is off)
4154 // anyway.
4155 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4156 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004157 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4158 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4159 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4160 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004161
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004162 return false;
4163}
4164
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004165static bool isDataTypeToken(StringRef Tok) {
4166 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4167 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4168 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4169 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4170 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4171 Tok == ".f" || Tok == ".d";
4172}
4173
4174// FIXME: This bit should probably be handled via an explicit match class
4175// in the .td files that matches the suffix instead of having it be
4176// a literal string token the way it is now.
4177static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4178 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4179}
4180
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004181/// Parse an arm instruction mnemonic followed by its operands.
4182bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4183 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4184 // Create the leading tokens for the mnemonic, split by '.' characters.
4185 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004186 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004187
Daniel Dunbar352e1482011-01-11 15:59:50 +00004188 // Split out the predication code and carry setting flag from the mnemonic.
4189 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004190 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004191 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004192 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004193 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004194 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004195
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004196 // In Thumb1, only the branch (B) instruction can be predicated.
4197 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4198 Parser.EatToEndOfStatement();
4199 return Error(NameLoc, "conditional execution not supported in Thumb1");
4200 }
4201
Jim Grosbachffa32252011-07-19 19:13:28 +00004202 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4203
Jim Grosbach89df9962011-08-26 21:43:41 +00004204 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4205 // is the mask as it will be for the IT encoding if the conditional
4206 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4207 // where the conditional bit0 is zero, the instruction post-processing
4208 // will adjust the mask accordingly.
4209 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004210 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4211 if (ITMask.size() > 3) {
4212 Parser.EatToEndOfStatement();
4213 return Error(Loc, "too many conditions on IT instruction");
4214 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004215 unsigned Mask = 8;
4216 for (unsigned i = ITMask.size(); i != 0; --i) {
4217 char pos = ITMask[i - 1];
4218 if (pos != 't' && pos != 'e') {
4219 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004220 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004221 }
4222 Mask >>= 1;
4223 if (ITMask[i - 1] == 't')
4224 Mask |= 8;
4225 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004226 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004227 }
4228
Jim Grosbachffa32252011-07-19 19:13:28 +00004229 // FIXME: This is all a pretty gross hack. We should automatically handle
4230 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004231
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004232 // Next, add the CCOut and ConditionCode operands, if needed.
4233 //
4234 // For mnemonics which can ever incorporate a carry setting bit or predication
4235 // code, our matching model involves us always generating CCOut and
4236 // ConditionCode operands to match the mnemonic "as written" and then we let
4237 // the matcher deal with finding the right instruction or generating an
4238 // appropriate error.
4239 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004240 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004241
Jim Grosbach33c16a22011-07-14 22:04:21 +00004242 // If we had a carry-set on an instruction that can't do that, issue an
4243 // error.
4244 if (!CanAcceptCarrySet && CarrySetting) {
4245 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004246 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004247 "' can not set flags, but 's' suffix specified");
4248 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004249 // If we had a predication code on an instruction that can't do that, issue an
4250 // error.
4251 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4252 Parser.EatToEndOfStatement();
4253 return Error(NameLoc, "instruction '" + Mnemonic +
4254 "' is not predicable, but condition code specified");
4255 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004256
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004257 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004258 if (CanAcceptCarrySet) {
4259 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004260 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004261 Loc));
4262 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004263
4264 // Add the predication code operand, if necessary.
4265 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004266 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4267 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004268 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004269 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004270 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004271
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004272 // Add the processor imod operand, if necessary.
4273 if (ProcessorIMod) {
4274 Operands.push_back(ARMOperand::CreateImm(
4275 MCConstantExpr::Create(ProcessorIMod, getContext()),
4276 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004277 }
4278
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004279 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004280 while (Next != StringRef::npos) {
4281 Start = Next;
4282 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004283 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004284
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004285 // Some NEON instructions have an optional datatype suffix that is
4286 // completely ignored. Check for that.
4287 if (isDataTypeToken(ExtraToken) &&
4288 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4289 continue;
4290
Jim Grosbach81d2e392011-09-07 16:06:04 +00004291 if (ExtraToken != ".n") {
4292 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4293 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4294 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004295 }
4296
4297 // Read the remaining operands.
4298 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004299 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004300 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004301 Parser.EatToEndOfStatement();
4302 return true;
4303 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004304
4305 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004306 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004307
4308 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004309 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004310 Parser.EatToEndOfStatement();
4311 return true;
4312 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004313 }
4314 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004315
Chris Lattnercbf8a982010-09-11 16:18:25 +00004316 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004317 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004318 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004319 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004320 }
Bill Wendling146018f2010-11-06 21:42:12 +00004321
Chris Lattner34e53142010-09-08 05:10:46 +00004322 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004323
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004324 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4325 // do and don't have a cc_out optional-def operand. With some spot-checks
4326 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004327 // parse and adjust accordingly before actually matching. We shouldn't ever
4328 // try to remove a cc_out operand that was explicitly set on the the
4329 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4330 // table driven matcher doesn't fit well with the ARM instruction set.
4331 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004332 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4333 Operands.erase(Operands.begin() + 1);
4334 delete Op;
4335 }
4336
Jim Grosbachcf121c32011-07-28 21:57:55 +00004337 // ARM mode 'blx' need special handling, as the register operand version
4338 // is predicable, but the label operand version is not. So, we can't rely
4339 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004340 // a k_CondCode operand in the list. If we're trying to match the label
4341 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004342 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4343 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4344 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4345 Operands.erase(Operands.begin() + 1);
4346 delete Op;
4347 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004348
4349 // The vector-compare-to-zero instructions have a literal token "#0" at
4350 // the end that comes to here as an immediate operand. Convert it to a
4351 // token to play nicely with the matcher.
4352 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4353 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4354 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4355 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4356 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4357 if (CE && CE->getValue() == 0) {
4358 Operands.erase(Operands.begin() + 5);
4359 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4360 delete Op;
4361 }
4362 }
Jim Grosbach68259142011-10-03 22:30:24 +00004363 // VCMP{E} does the same thing, but with a different operand count.
4364 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4365 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4366 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4367 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4368 if (CE && CE->getValue() == 0) {
4369 Operands.erase(Operands.begin() + 4);
4370 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4371 delete Op;
4372 }
4373 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004374 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4375 // end. Convert it to a token here.
4376 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4377 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4378 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4380 if (CE && CE->getValue() == 0) {
4381 Operands.erase(Operands.begin() + 5);
4382 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4383 delete Op;
4384 }
4385 }
4386
Chris Lattner98986712010-01-14 22:21:20 +00004387 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004388}
4389
Jim Grosbach189610f2011-07-26 18:25:39 +00004390// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004391
4392// return 'true' if register list contains non-low GPR registers,
4393// 'false' otherwise. If Reg is in the register list or is HiReg, set
4394// 'containsReg' to true.
4395static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4396 unsigned HiReg, bool &containsReg) {
4397 containsReg = false;
4398 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4399 unsigned OpReg = Inst.getOperand(i).getReg();
4400 if (OpReg == Reg)
4401 containsReg = true;
4402 // Anything other than a low register isn't legal here.
4403 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4404 return true;
4405 }
4406 return false;
4407}
4408
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004409// Check if the specified regisgter is in the register list of the inst,
4410// starting at the indicated operand number.
4411static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4412 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4413 unsigned OpReg = Inst.getOperand(i).getReg();
4414 if (OpReg == Reg)
4415 return true;
4416 }
4417 return false;
4418}
4419
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004420// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4421// the ARMInsts array) instead. Getting that here requires awkward
4422// API changes, though. Better way?
4423namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004424extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004425}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004426static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004427 return ARMInsts[Opcode];
4428}
4429
Jim Grosbach189610f2011-07-26 18:25:39 +00004430// FIXME: We would really like to be able to tablegen'erate this.
4431bool ARMAsmParser::
4432validateInstruction(MCInst &Inst,
4433 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004434 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004435 SMLoc Loc = Operands[0]->getStartLoc();
4436 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004437 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4438 // being allowed in IT blocks, but not being predicable. It just always
4439 // executes.
4440 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004441 unsigned bit = 1;
4442 if (ITState.FirstCond)
4443 ITState.FirstCond = false;
4444 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004445 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004446 // The instruction must be predicable.
4447 if (!MCID.isPredicable())
4448 return Error(Loc, "instructions in IT block must be predicable");
4449 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4450 unsigned ITCond = bit ? ITState.Cond :
4451 ARMCC::getOppositeCondition(ITState.Cond);
4452 if (Cond != ITCond) {
4453 // Find the condition code Operand to get its SMLoc information.
4454 SMLoc CondLoc;
4455 for (unsigned i = 1; i < Operands.size(); ++i)
4456 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4457 CondLoc = Operands[i]->getStartLoc();
4458 return Error(CondLoc, "incorrect condition in IT block; got '" +
4459 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4460 "', but expected '" +
4461 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4462 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004463 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004464 } else if (isThumbTwo() && MCID.isPredicable() &&
4465 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004466 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4467 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004468 return Error(Loc, "predicated instructions must be in IT block");
4469
Jim Grosbach189610f2011-07-26 18:25:39 +00004470 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004471 case ARM::LDRD:
4472 case ARM::LDRD_PRE:
4473 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004474 case ARM::LDREXD: {
4475 // Rt2 must be Rt + 1.
4476 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4477 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4478 if (Rt2 != Rt + 1)
4479 return Error(Operands[3]->getStartLoc(),
4480 "destination operands must be sequential");
4481 return false;
4482 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004483 case ARM::STRD: {
4484 // Rt2 must be Rt + 1.
4485 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4486 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4487 if (Rt2 != Rt + 1)
4488 return Error(Operands[3]->getStartLoc(),
4489 "source operands must be sequential");
4490 return false;
4491 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004492 case ARM::STRD_PRE:
4493 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004494 case ARM::STREXD: {
4495 // Rt2 must be Rt + 1.
4496 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4497 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4498 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004499 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004500 "source operands must be sequential");
4501 return false;
4502 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004503 case ARM::SBFX:
4504 case ARM::UBFX: {
4505 // width must be in range [1, 32-lsb]
4506 unsigned lsb = Inst.getOperand(2).getImm();
4507 unsigned widthm1 = Inst.getOperand(3).getImm();
4508 if (widthm1 >= 32 - lsb)
4509 return Error(Operands[5]->getStartLoc(),
4510 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004511 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004512 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004513 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004514 // If we're parsing Thumb2, the .w variant is available and handles
4515 // most cases that are normally illegal for a Thumb1 LDM
4516 // instruction. We'll make the transformation in processInstruction()
4517 // if necessary.
4518 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004519 // Thumb LDM instructions are writeback iff the base register is not
4520 // in the register list.
4521 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004522 bool hasWritebackToken =
4523 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4524 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004525 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004526 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004527 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4528 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004529 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004530 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004531 return Error(Operands[2]->getStartLoc(),
4532 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004533 // If we should not have writeback, there must not be a '!'. This is
4534 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004535 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004536 return Error(Operands[3]->getStartLoc(),
4537 "writeback operator '!' not allowed when base register "
4538 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004539
4540 break;
4541 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004542 case ARM::t2LDMIA_UPD: {
4543 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4544 return Error(Operands[4]->getStartLoc(),
4545 "writeback operator '!' not allowed when base register "
4546 "in register list");
4547 break;
4548 }
Jim Grosbach54026372011-11-10 23:17:11 +00004549 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4550 // so only issue a diagnostic for thumb1. The instructions will be
4551 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004552 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004553 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004554 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4555 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004556 return Error(Operands[2]->getStartLoc(),
4557 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004558 break;
4559 }
4560 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004561 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004562 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4563 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004564 return Error(Operands[2]->getStartLoc(),
4565 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004566 break;
4567 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004568 case ARM::tSTMIA_UPD: {
4569 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004570 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004571 return Error(Operands[4]->getStartLoc(),
4572 "registers must be in range r0-r7");
4573 break;
4574 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004575 }
4576
4577 return false;
4578}
4579
Jim Grosbach83ec8772011-11-10 23:42:14 +00004580bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004581processInstruction(MCInst &Inst,
4582 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4583 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004584 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00004585 case ARM::ASRr:
4586 case ARM::LSRr:
4587 case ARM::LSLr:
4588 case ARM::RORr: {
4589 ARM_AM::ShiftOpc ShiftTy;
4590 switch(Inst.getOpcode()) {
4591 default: llvm_unreachable("unexpected opcode!");
4592 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4593 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4594 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4595 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4596 }
4597 // A shift by zero is a plain MOVr, not a MOVsi.
4598 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4599 MCInst TmpInst;
4600 TmpInst.setOpcode(ARM::MOVsr);
4601 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4602 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4603 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4604 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4605 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4606 TmpInst.addOperand(Inst.getOperand(4));
4607 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4608 Inst = TmpInst;
4609 return true;
4610 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00004611 case ARM::ASRi:
4612 case ARM::LSRi:
4613 case ARM::LSLi:
4614 case ARM::RORi: {
4615 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004616 switch(Inst.getOpcode()) {
4617 default: llvm_unreachable("unexpected opcode!");
4618 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4619 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4620 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4621 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4622 }
4623 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00004624 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00004625 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4626 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004627 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004628 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004629 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4630 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004631 if (Opc == ARM::MOVsi)
4632 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004633 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4634 TmpInst.addOperand(Inst.getOperand(4));
4635 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4636 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004637 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004638 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00004639 case ARM::RRXi: {
4640 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4641 MCInst TmpInst;
4642 TmpInst.setOpcode(ARM::MOVsi);
4643 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4644 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4645 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4646 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4647 TmpInst.addOperand(Inst.getOperand(3));
4648 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4649 Inst = TmpInst;
4650 return true;
4651 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004652 case ARM::t2LDMIA_UPD: {
4653 // If this is a load of a single register, then we should use
4654 // a post-indexed LDR instruction instead, per the ARM ARM.
4655 if (Inst.getNumOperands() != 5)
4656 return false;
4657 MCInst TmpInst;
4658 TmpInst.setOpcode(ARM::t2LDR_POST);
4659 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4660 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4661 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4662 TmpInst.addOperand(MCOperand::CreateImm(4));
4663 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4664 TmpInst.addOperand(Inst.getOperand(3));
4665 Inst = TmpInst;
4666 return true;
4667 }
4668 case ARM::t2STMDB_UPD: {
4669 // If this is a store of a single register, then we should use
4670 // a pre-indexed STR instruction instead, per the ARM ARM.
4671 if (Inst.getNumOperands() != 5)
4672 return false;
4673 MCInst TmpInst;
4674 TmpInst.setOpcode(ARM::t2STR_PRE);
4675 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4676 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4677 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4678 TmpInst.addOperand(MCOperand::CreateImm(-4));
4679 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4680 TmpInst.addOperand(Inst.getOperand(3));
4681 Inst = TmpInst;
4682 return true;
4683 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004684 case ARM::LDMIA_UPD:
4685 // If this is a load of a single register via a 'pop', then we should use
4686 // a post-indexed LDR instruction instead, per the ARM ARM.
4687 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4688 Inst.getNumOperands() == 5) {
4689 MCInst TmpInst;
4690 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4691 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4692 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4693 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4694 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4695 TmpInst.addOperand(MCOperand::CreateImm(4));
4696 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4697 TmpInst.addOperand(Inst.getOperand(3));
4698 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004699 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004700 }
4701 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004702 case ARM::STMDB_UPD:
4703 // If this is a store of a single register via a 'push', then we should use
4704 // a pre-indexed STR instruction instead, per the ARM ARM.
4705 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4706 Inst.getNumOperands() == 5) {
4707 MCInst TmpInst;
4708 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4709 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4710 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4711 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4712 TmpInst.addOperand(MCOperand::CreateImm(-4));
4713 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4714 TmpInst.addOperand(Inst.getOperand(3));
4715 Inst = TmpInst;
4716 }
4717 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004718 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004719 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4720 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4721 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4722 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004723 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004724 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004725 return true;
4726 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004727 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004728 case ARM::tSUBi8:
4729 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4730 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4731 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4732 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004733 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004734 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004735 return true;
4736 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004737 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004738 case ARM::tB:
4739 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004740 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004741 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004742 return true;
4743 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004744 break;
4745 case ARM::t2B:
4746 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004747 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004748 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004749 return true;
4750 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004751 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004752 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004753 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004754 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004755 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004756 return true;
4757 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004758 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004759 case ARM::tBcc:
4760 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004761 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004762 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004763 return true;
4764 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004765 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004766 case ARM::tLDMIA: {
4767 // If the register list contains any high registers, or if the writeback
4768 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4769 // instead if we're in Thumb2. Otherwise, this should have generated
4770 // an error in validateInstruction().
4771 unsigned Rn = Inst.getOperand(0).getReg();
4772 bool hasWritebackToken =
4773 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4774 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4775 bool listContainsBase;
4776 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4777 (!listContainsBase && !hasWritebackToken) ||
4778 (listContainsBase && hasWritebackToken)) {
4779 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4780 assert (isThumbTwo());
4781 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4782 // If we're switching to the updating version, we need to insert
4783 // the writeback tied operand.
4784 if (hasWritebackToken)
4785 Inst.insert(Inst.begin(),
4786 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004787 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004788 }
4789 break;
4790 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004791 case ARM::tSTMIA_UPD: {
4792 // If the register list contains any high registers, we need to use
4793 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4794 // should have generated an error in validateInstruction().
4795 unsigned Rn = Inst.getOperand(0).getReg();
4796 bool listContainsBase;
4797 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4798 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4799 assert (isThumbTwo());
4800 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004801 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004802 }
4803 break;
4804 }
Jim Grosbach54026372011-11-10 23:17:11 +00004805 case ARM::tPOP: {
4806 bool listContainsBase;
4807 // If the register list contains any high registers, we need to use
4808 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4809 // should have generated an error in validateInstruction().
4810 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004811 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004812 assert (isThumbTwo());
4813 Inst.setOpcode(ARM::t2LDMIA_UPD);
4814 // Add the base register and writeback operands.
4815 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4816 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004817 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004818 }
4819 case ARM::tPUSH: {
4820 bool listContainsBase;
4821 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004822 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004823 assert (isThumbTwo());
4824 Inst.setOpcode(ARM::t2STMDB_UPD);
4825 // Add the base register and writeback operands.
4826 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4827 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004828 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004829 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004830 case ARM::t2MOVi: {
4831 // If we can use the 16-bit encoding and the user didn't explicitly
4832 // request the 32-bit variant, transform it here.
4833 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4834 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004835 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4836 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4837 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004838 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4839 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4840 // The operands aren't in the same order for tMOVi8...
4841 MCInst TmpInst;
4842 TmpInst.setOpcode(ARM::tMOVi8);
4843 TmpInst.addOperand(Inst.getOperand(0));
4844 TmpInst.addOperand(Inst.getOperand(4));
4845 TmpInst.addOperand(Inst.getOperand(1));
4846 TmpInst.addOperand(Inst.getOperand(2));
4847 TmpInst.addOperand(Inst.getOperand(3));
4848 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004849 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004850 }
4851 break;
4852 }
4853 case ARM::t2MOVr: {
4854 // If we can use the 16-bit encoding and the user didn't explicitly
4855 // request the 32-bit variant, transform it here.
4856 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4857 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4858 Inst.getOperand(2).getImm() == ARMCC::AL &&
4859 Inst.getOperand(4).getReg() == ARM::CPSR &&
4860 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4861 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4862 // The operands aren't the same for tMOV[S]r... (no cc_out)
4863 MCInst TmpInst;
4864 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4865 TmpInst.addOperand(Inst.getOperand(0));
4866 TmpInst.addOperand(Inst.getOperand(1));
4867 TmpInst.addOperand(Inst.getOperand(2));
4868 TmpInst.addOperand(Inst.getOperand(3));
4869 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004870 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004871 }
4872 break;
4873 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004874 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004875 case ARM::t2SXTB:
4876 case ARM::t2UXTH:
4877 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004878 // If we can use the 16-bit encoding and the user didn't explicitly
4879 // request the 32-bit variant, transform it here.
4880 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4881 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4882 Inst.getOperand(2).getImm() == 0 &&
4883 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4884 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004885 unsigned NewOpc;
4886 switch (Inst.getOpcode()) {
4887 default: llvm_unreachable("Illegal opcode!");
4888 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4889 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4890 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4891 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4892 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004893 // The operands aren't the same for thumb1 (no rotate operand).
4894 MCInst TmpInst;
4895 TmpInst.setOpcode(NewOpc);
4896 TmpInst.addOperand(Inst.getOperand(0));
4897 TmpInst.addOperand(Inst.getOperand(1));
4898 TmpInst.addOperand(Inst.getOperand(3));
4899 TmpInst.addOperand(Inst.getOperand(4));
4900 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004901 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00004902 }
4903 break;
4904 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004905 case ARM::t2IT: {
4906 // The mask bits for all but the first condition are represented as
4907 // the low bit of the condition code value implies 't'. We currently
4908 // always have 1 implies 't', so XOR toggle the bits if the low bit
4909 // of the condition code is zero. The encoding also expects the low
4910 // bit of the condition to be encoded as bit 4 of the mask operand,
4911 // so mask that in if needed
4912 MCOperand &MO = Inst.getOperand(1);
4913 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004914 unsigned OrigMask = Mask;
4915 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004916 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004917 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4918 for (unsigned i = 3; i != TZ; --i)
4919 Mask ^= 1 << i;
4920 } else
4921 Mask |= 0x10;
4922 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004923
4924 // Set up the IT block state according to the IT instruction we just
4925 // matched.
4926 assert(!inITBlock() && "nested IT blocks?!");
4927 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4928 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4929 ITState.CurPosition = 0;
4930 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004931 break;
4932 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004933 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00004934 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004935}
4936
Jim Grosbach47a0d522011-08-16 20:45:50 +00004937unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4938 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4939 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004940 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004941 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004942 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4943 assert(MCID.hasOptionalDef() &&
4944 "optionally flag setting instruction missing optional def operand");
4945 assert(MCID.NumOperands == Inst.getNumOperands() &&
4946 "operand count mismatch!");
4947 // Find the optional-def operand (cc_out).
4948 unsigned OpNo;
4949 for (OpNo = 0;
4950 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4951 ++OpNo)
4952 ;
4953 // If we're parsing Thumb1, reject it completely.
4954 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4955 return Match_MnemonicFail;
4956 // If we're parsing Thumb2, which form is legal depends on whether we're
4957 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004958 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4959 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004960 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004961 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4962 inITBlock())
4963 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004964 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004965 // Some high-register supporting Thumb1 encodings only allow both registers
4966 // to be from r0-r7 when in Thumb2.
4967 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4968 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4969 isARMLowRegister(Inst.getOperand(2).getReg()))
4970 return Match_RequiresThumb2;
4971 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00004972 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00004973 isARMLowRegister(Inst.getOperand(0).getReg()) &&
4974 isARMLowRegister(Inst.getOperand(1).getReg()))
4975 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004976 return Match_Success;
4977}
4978
Chris Lattnerfa42fad2010-10-28 21:28:01 +00004979bool ARMAsmParser::
4980MatchAndEmitInstruction(SMLoc IDLoc,
4981 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4982 MCStreamer &Out) {
4983 MCInst Inst;
4984 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004985 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004986 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00004987 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00004988 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00004989 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00004990 // Context sensitive operand constraints aren't handled by the matcher,
4991 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00004992 if (validateInstruction(Inst, Operands)) {
4993 // Still progress the IT block, otherwise one wrong condition causes
4994 // nasty cascading errors.
4995 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00004996 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00004997 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004998
Jim Grosbachf8fce712011-08-11 17:35:48 +00004999 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005000 // encoding is selected. Loop on it while changes happen so the
5001 // individual transformations can chain off each other. E.g.,
5002 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5003 while (processInstruction(Inst, Operands))
5004 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005005
Jim Grosbacha1109882011-09-02 23:22:08 +00005006 // Only move forward at the very end so that everything in validate
5007 // and process gets a consistent answer about whether we're in an IT
5008 // block.
5009 forwardITPosition();
5010
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005011 Out.EmitInstruction(Inst);
5012 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005013 case Match_MissingFeature:
5014 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5015 return true;
5016 case Match_InvalidOperand: {
5017 SMLoc ErrorLoc = IDLoc;
5018 if (ErrorInfo != ~0U) {
5019 if (ErrorInfo >= Operands.size())
5020 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005021
Chris Lattnere73d4f82010-10-28 21:41:58 +00005022 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5023 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5024 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005025
Chris Lattnere73d4f82010-10-28 21:41:58 +00005026 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005027 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005028 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005029 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005030 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005031 // The converter function will have already emited a diagnostic.
5032 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005033 case Match_RequiresNotITBlock:
5034 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005035 case Match_RequiresITBlock:
5036 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005037 case Match_RequiresV6:
5038 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5039 case Match_RequiresThumb2:
5040 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005041 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005042
Eric Christopherc223e2b2010-10-29 09:26:59 +00005043 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005044 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005045}
5046
Jim Grosbach1355cf12011-07-26 17:10:22 +00005047/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005048bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5049 StringRef IDVal = DirectiveID.getIdentifier();
5050 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005051 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005052 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005053 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005054 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005055 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005056 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005057 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005058 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005059 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005060 return true;
5061}
5062
Jim Grosbach1355cf12011-07-26 17:10:22 +00005063/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005064/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005065bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005066 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5067 for (;;) {
5068 const MCExpr *Value;
5069 if (getParser().ParseExpression(Value))
5070 return true;
5071
Chris Lattneraaec2052010-01-19 19:46:13 +00005072 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005073
5074 if (getLexer().is(AsmToken::EndOfStatement))
5075 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005076
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005077 // FIXME: Improve diagnostic.
5078 if (getLexer().isNot(AsmToken::Comma))
5079 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005080 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005081 }
5082 }
5083
Sean Callananb9a25b72010-01-19 20:27:46 +00005084 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005085 return false;
5086}
5087
Jim Grosbach1355cf12011-07-26 17:10:22 +00005088/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005089/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005090bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005091 if (getLexer().isNot(AsmToken::EndOfStatement))
5092 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005093 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005094
5095 // TODO: set thumb mode
5096 // TODO: tell the MC streamer the mode
5097 // getParser().getStreamer().Emit???();
5098 return false;
5099}
5100
Jim Grosbach1355cf12011-07-26 17:10:22 +00005101/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005102/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005103bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005104 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5105 bool isMachO = MAI.hasSubsectionsViaSymbols();
5106 StringRef Name;
5107
5108 // Darwin asm has function name after .thumb_func direction
5109 // ELF doesn't
5110 if (isMachO) {
5111 const AsmToken &Tok = Parser.getTok();
5112 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5113 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005114 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005115 Parser.Lex(); // Consume the identifier token.
5116 }
5117
Jim Grosbachd475f862011-11-10 20:48:53 +00005118 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005119 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005120 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005121
Rafael Espindola64695402011-05-16 16:17:21 +00005122 // FIXME: assuming function name will be the line following .thumb_func
5123 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005124 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005125 }
5126
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005127 // Mark symbol as a thumb symbol.
5128 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5129 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005130 return false;
5131}
5132
Jim Grosbach1355cf12011-07-26 17:10:22 +00005133/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005134/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005135bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005136 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005137 if (Tok.isNot(AsmToken::Identifier))
5138 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005139 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005140 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005141 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005142 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005143 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005144 else
5145 return Error(L, "unrecognized syntax mode in .syntax directive");
5146
5147 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005148 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005149 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005150
5151 // TODO tell the MC streamer the mode
5152 // getParser().getStreamer().Emit???();
5153 return false;
5154}
5155
Jim Grosbach1355cf12011-07-26 17:10:22 +00005156/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005157/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005158bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005159 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005160 if (Tok.isNot(AsmToken::Integer))
5161 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005162 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005163 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005164 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005165 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005166 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005167 else
5168 return Error(L, "invalid operand to .code directive");
5169
5170 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005171 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005172 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005173
Evan Cheng32869202011-07-08 22:36:29 +00005174 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005175 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005176 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005177 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005178 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005179 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005180 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005181 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005182 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005183
Kevin Enderby515d5092009-10-15 20:48:48 +00005184 return false;
5185}
5186
Sean Callanan90b70972010-04-07 20:29:34 +00005187extern "C" void LLVMInitializeARMAsmLexer();
5188
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005189/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005190extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005191 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5192 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005193 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005194}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005195
Chris Lattner0692ee62010-09-06 19:11:01 +00005196#define GET_REGISTER_MATCHER
5197#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005198#include "ARMGenAsmMatcher.inc"