blob: bb83e5e43b5da8adfbdacecaed75f83eae464f37 [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 Grosbach862019c2011-10-18 23:02:30 +00001530 void addVecListOneDOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1533 }
1534
Jim Grosbach280dfad2011-10-21 18:54:25 +00001535 void addVecListTwoDOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 // Only the first register actually goes on the instruction. The rest
1538 // are implied by the opcode.
1539 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1540 }
1541
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001542 void addVecListThreeDOperands(MCInst &Inst, unsigned N) const {
1543 assert(N == 1 && "Invalid number of operands!");
1544 // Only the first register actually goes on the instruction. The rest
1545 // are implied by the opcode.
1546 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1547 }
1548
Jim Grosbachb6310312011-10-21 20:35:01 +00001549 void addVecListFourDOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 1 && "Invalid number of operands!");
1551 // Only the first register actually goes on the instruction. The rest
1552 // are implied by the opcode.
1553 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1554 }
1555
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001556 void addVecListTwoQOperands(MCInst &Inst, unsigned N) const {
1557 assert(N == 1 && "Invalid number of operands!");
1558 // Only the first register actually goes on the instruction. The rest
1559 // are implied by the opcode.
1560 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1561 }
1562
Jim Grosbach460a9052011-10-07 23:56:00 +00001563 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1566 }
1567
1568 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1571 }
1572
1573 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1576 }
1577
Jim Grosbach0e387b22011-10-17 22:26:03 +00001578 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 // The immediate encodes the type of constant as well as the value.
1581 // Mask in that this is an i8 splat.
1582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1583 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1584 }
1585
Jim Grosbachea461102011-10-17 23:09:09 +00001586 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1587 assert(N == 1 && "Invalid number of operands!");
1588 // The immediate encodes the type of constant as well as the value.
1589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1590 unsigned Value = CE->getValue();
1591 if (Value >= 256)
1592 Value = (Value >> 8) | 0xa00;
1593 else
1594 Value |= 0x800;
1595 Inst.addOperand(MCOperand::CreateImm(Value));
1596 }
1597
Jim Grosbach6248a542011-10-18 00:22:00 +00001598 void addNEONi32splatOperands(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 unsigned Value = CE->getValue();
1603 if (Value >= 256 && Value <= 0xff00)
1604 Value = (Value >> 8) | 0x200;
1605 else if (Value > 0xffff && Value <= 0xff0000)
1606 Value = (Value >> 16) | 0x400;
1607 else if (Value > 0xffffff)
1608 Value = (Value >> 24) | 0x600;
1609 Inst.addOperand(MCOperand::CreateImm(Value));
1610 }
1611
1612 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1613 assert(N == 1 && "Invalid number of operands!");
1614 // The immediate encodes the type of constant as well as the value.
1615 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1616 unsigned Value = CE->getValue();
1617 if (Value >= 256 && Value <= 0xffff)
1618 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1619 else if (Value > 0xffff && Value <= 0xffffff)
1620 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1621 else if (Value > 0xffffff)
1622 Value = (Value >> 24) | 0x600;
1623 Inst.addOperand(MCOperand::CreateImm(Value));
1624 }
1625
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001626 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 // The immediate encodes the type of constant as well as the value.
1629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1630 uint64_t Value = CE->getValue();
1631 unsigned Imm = 0;
1632 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1633 Imm |= (Value & 1) << i;
1634 }
1635 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1636 }
1637
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001638 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001639
Jim Grosbach89df9962011-08-26 21:43:41 +00001640 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001641 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001642 Op->ITMask.Mask = Mask;
1643 Op->StartLoc = S;
1644 Op->EndLoc = S;
1645 return Op;
1646 }
1647
Chris Lattner3a697562010-10-28 17:20:03 +00001648 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001649 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001650 Op->CC.Val = CC;
1651 Op->StartLoc = S;
1652 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001653 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001654 }
1655
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001656 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001657 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001658 Op->Cop.Val = CopVal;
1659 Op->StartLoc = S;
1660 Op->EndLoc = S;
1661 return Op;
1662 }
1663
1664 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001665 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001666 Op->Cop.Val = CopVal;
1667 Op->StartLoc = S;
1668 Op->EndLoc = S;
1669 return Op;
1670 }
1671
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001672 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1673 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1674 Op->Cop.Val = Val;
1675 Op->StartLoc = S;
1676 Op->EndLoc = E;
1677 return Op;
1678 }
1679
Jim Grosbachd67641b2010-12-06 18:21:12 +00001680 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001681 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001682 Op->Reg.RegNum = RegNum;
1683 Op->StartLoc = S;
1684 Op->EndLoc = S;
1685 return Op;
1686 }
1687
Chris Lattner3a697562010-10-28 17:20:03 +00001688 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001689 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001690 Op->Tok.Data = Str.data();
1691 Op->Tok.Length = Str.size();
1692 Op->StartLoc = S;
1693 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001694 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001695 }
1696
Bill Wendling50d0f582010-11-18 23:43:05 +00001697 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001698 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001699 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001700 Op->StartLoc = S;
1701 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001702 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001703 }
1704
Jim Grosbache8606dc2011-07-13 17:50:29 +00001705 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1706 unsigned SrcReg,
1707 unsigned ShiftReg,
1708 unsigned ShiftImm,
1709 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001710 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001711 Op->RegShiftedReg.ShiftTy = ShTy;
1712 Op->RegShiftedReg.SrcReg = SrcReg;
1713 Op->RegShiftedReg.ShiftReg = ShiftReg;
1714 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
Owen Anderson92a20222011-07-21 18:54:16 +00001720 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1721 unsigned SrcReg,
1722 unsigned ShiftImm,
1723 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001724 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001725 Op->RegShiftedImm.ShiftTy = ShTy;
1726 Op->RegShiftedImm.SrcReg = SrcReg;
1727 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001728 Op->StartLoc = S;
1729 Op->EndLoc = E;
1730 return Op;
1731 }
1732
Jim Grosbach580f4a92011-07-25 22:20:28 +00001733 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001734 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001735 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001736 Op->ShifterImm.isASR = isASR;
1737 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001738 Op->StartLoc = S;
1739 Op->EndLoc = E;
1740 return Op;
1741 }
1742
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001743 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001744 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001745 Op->RotImm.Imm = Imm;
1746 Op->StartLoc = S;
1747 Op->EndLoc = E;
1748 return Op;
1749 }
1750
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001751 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1752 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001753 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001754 Op->Bitfield.LSB = LSB;
1755 Op->Bitfield.Width = Width;
1756 Op->StartLoc = S;
1757 Op->EndLoc = E;
1758 return Op;
1759 }
1760
Bill Wendling7729e062010-11-09 22:44:22 +00001761 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001762 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001763 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001764 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001765
Jim Grosbachd300b942011-09-13 22:56:44 +00001766 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001767 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001768 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001769 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001770 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001771
1772 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001773 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001774 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001775 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001776 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001777 Op->StartLoc = StartLoc;
1778 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001779 return Op;
1780 }
1781
Jim Grosbach862019c2011-10-18 23:02:30 +00001782 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1783 SMLoc S, SMLoc E) {
1784 ARMOperand *Op = new ARMOperand(k_VectorList);
1785 Op->VectorList.RegNum = RegNum;
1786 Op->VectorList.Count = Count;
1787 Op->StartLoc = S;
1788 Op->EndLoc = E;
1789 return Op;
1790 }
1791
Jim Grosbach460a9052011-10-07 23:56:00 +00001792 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1793 MCContext &Ctx) {
1794 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1795 Op->VectorIndex.Val = Idx;
1796 Op->StartLoc = S;
1797 Op->EndLoc = E;
1798 return Op;
1799 }
1800
Chris Lattner3a697562010-10-28 17:20:03 +00001801 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001802 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001803 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001804 Op->StartLoc = S;
1805 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001806 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001807 }
1808
Jim Grosbach9d390362011-10-03 23:38:36 +00001809 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001810 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001811 Op->FPImm.Val = Val;
1812 Op->StartLoc = S;
1813 Op->EndLoc = S;
1814 return Op;
1815 }
1816
Jim Grosbach7ce05792011-08-03 23:50:40 +00001817 static ARMOperand *CreateMem(unsigned BaseRegNum,
1818 const MCConstantExpr *OffsetImm,
1819 unsigned OffsetRegNum,
1820 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001821 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001822 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001823 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001824 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001825 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001826 Op->Memory.BaseRegNum = BaseRegNum;
1827 Op->Memory.OffsetImm = OffsetImm;
1828 Op->Memory.OffsetRegNum = OffsetRegNum;
1829 Op->Memory.ShiftType = ShiftType;
1830 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001831 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001832 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001833 Op->StartLoc = S;
1834 Op->EndLoc = E;
1835 return Op;
1836 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001837
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001838 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1839 ARM_AM::ShiftOpc ShiftTy,
1840 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001842 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001843 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001844 Op->PostIdxReg.isAdd = isAdd;
1845 Op->PostIdxReg.ShiftTy = ShiftTy;
1846 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001847 Op->StartLoc = S;
1848 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001849 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001850 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001851
1852 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001853 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001854 Op->MBOpt.Val = Opt;
1855 Op->StartLoc = S;
1856 Op->EndLoc = S;
1857 return Op;
1858 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001859
1860 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001861 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001862 Op->IFlags.Val = IFlags;
1863 Op->StartLoc = S;
1864 Op->EndLoc = S;
1865 return Op;
1866 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001867
1868 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001869 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001870 Op->MMask.Val = MMask;
1871 Op->StartLoc = S;
1872 Op->EndLoc = S;
1873 return Op;
1874 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001875};
1876
1877} // end anonymous namespace.
1878
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001879void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001880 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001881 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001882 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1883 << ") >";
1884 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001885 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001886 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001887 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001889 OS << "<ccout " << getReg() << ">";
1890 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001892 static const char *MaskStr[] = {
1893 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1894 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1895 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001896 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1897 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1898 break;
1899 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001900 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001901 OS << "<coprocessor number: " << getCoproc() << ">";
1902 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001903 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001904 OS << "<coprocessor register: " << getCoproc() << ">";
1905 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001906 case k_CoprocOption:
1907 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1908 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001909 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001910 OS << "<mask: " << getMSRMask() << ">";
1911 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001913 getImm()->print(OS);
1914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001916 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1917 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001918 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001919 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001920 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001921 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001922 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001924 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1925 << PostIdxReg.RegNum;
1926 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1927 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1928 << PostIdxReg.ShiftImm;
1929 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001930 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001932 OS << "<ARM_PROC::";
1933 unsigned IFlags = getProcIFlags();
1934 for (int i=2; i >= 0; --i)
1935 if (IFlags & (1 << i))
1936 OS << ARM_PROC::IFlagsToString(1 << i);
1937 OS << ">";
1938 break;
1939 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001941 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001942 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001943 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001944 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1945 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001946 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001947 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001948 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001949 << RegShiftedReg.SrcReg << " "
1950 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
1951 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001952 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001953 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001954 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001955 << RegShiftedImm.SrcReg << " "
1956 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
1957 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00001958 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001960 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1961 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001962 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001963 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1964 << ", width: " << Bitfield.Width << ">";
1965 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 case k_RegisterList:
1967 case k_DPRRegisterList:
1968 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001969 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001970
Bill Wendling5fa22a12010-11-09 23:28:44 +00001971 const SmallVectorImpl<unsigned> &RegList = getRegList();
1972 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001973 I = RegList.begin(), E = RegList.end(); I != E; ) {
1974 OS << *I;
1975 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001976 }
1977
1978 OS << ">";
1979 break;
1980 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001981 case k_VectorList:
1982 OS << "<vector_list " << VectorList.Count << " * "
1983 << VectorList.RegNum << ">";
1984 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001986 OS << "'" << getToken() << "'";
1987 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001988 case k_VectorIndex:
1989 OS << "<vectorindex " << getVectorIndex() << ">";
1990 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001991 }
1992}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001993
1994/// @name Auto-generated Match Functions
1995/// {
1996
1997static unsigned MatchRegisterName(StringRef Name);
1998
1999/// }
2000
Bob Wilson69df7232011-02-03 21:46:10 +00002001bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2002 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002003 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002004
2005 return (RegNo == (unsigned)-1);
2006}
2007
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002008/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002009/// and if it is a register name the token is eaten and the register number is
2010/// returned. Otherwise return -1.
2011///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002012int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002013 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002014 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002015
Chris Lattnere5658fa2010-10-30 04:09:10 +00002016 // FIXME: Validate register for the current architecture; we have to do
2017 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002018 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002019 unsigned RegNum = MatchRegisterName(lowerCase);
2020 if (!RegNum) {
2021 RegNum = StringSwitch<unsigned>(lowerCase)
2022 .Case("r13", ARM::SP)
2023 .Case("r14", ARM::LR)
2024 .Case("r15", ARM::PC)
2025 .Case("ip", ARM::R12)
2026 .Default(0);
2027 }
2028 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002029
Chris Lattnere5658fa2010-10-30 04:09:10 +00002030 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002031
Chris Lattnere5658fa2010-10-30 04:09:10 +00002032 return RegNum;
2033}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002034
Jim Grosbach19906722011-07-13 18:49:30 +00002035// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2036// If a recoverable error occurs, return 1. If an irrecoverable error
2037// occurs, return -1. An irrecoverable error is one where tokens have been
2038// consumed in the process of trying to parse the shifter (i.e., when it is
2039// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002040int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002041 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2042 SMLoc S = Parser.getTok().getLoc();
2043 const AsmToken &Tok = Parser.getTok();
2044 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2045
Benjamin Kramer59085362011-11-06 20:37:06 +00002046 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002047 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2048 .Case("lsl", ARM_AM::lsl)
2049 .Case("lsr", ARM_AM::lsr)
2050 .Case("asr", ARM_AM::asr)
2051 .Case("ror", ARM_AM::ror)
2052 .Case("rrx", ARM_AM::rrx)
2053 .Default(ARM_AM::no_shift);
2054
2055 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002056 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002057
Jim Grosbache8606dc2011-07-13 17:50:29 +00002058 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002059
Jim Grosbache8606dc2011-07-13 17:50:29 +00002060 // The source register for the shift has already been added to the
2061 // operand list, so we need to pop it off and combine it into the shifted
2062 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002063 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002064 if (!PrevOp->isReg())
2065 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2066 int SrcReg = PrevOp->getReg();
2067 int64_t Imm = 0;
2068 int ShiftReg = 0;
2069 if (ShiftTy == ARM_AM::rrx) {
2070 // RRX Doesn't have an explicit shift amount. The encoder expects
2071 // the shift register to be the same as the source register. Seems odd,
2072 // but OK.
2073 ShiftReg = SrcReg;
2074 } else {
2075 // Figure out if this is shifted by a constant or a register (for non-RRX).
2076 if (Parser.getTok().is(AsmToken::Hash)) {
2077 Parser.Lex(); // Eat hash.
2078 SMLoc ImmLoc = Parser.getTok().getLoc();
2079 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002080 if (getParser().ParseExpression(ShiftExpr)) {
2081 Error(ImmLoc, "invalid immediate shift value");
2082 return -1;
2083 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002084 // The expression must be evaluatable as an immediate.
2085 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002086 if (!CE) {
2087 Error(ImmLoc, "invalid immediate shift value");
2088 return -1;
2089 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002090 // Range check the immediate.
2091 // lsl, ror: 0 <= imm <= 31
2092 // lsr, asr: 0 <= imm <= 32
2093 Imm = CE->getValue();
2094 if (Imm < 0 ||
2095 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2096 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002097 Error(ImmLoc, "immediate shift value out of range");
2098 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002099 }
2100 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002101 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002102 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002103 if (ShiftReg == -1) {
2104 Error (L, "expected immediate or register in shift operand");
2105 return -1;
2106 }
2107 } else {
2108 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002109 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002110 return -1;
2111 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002112 }
2113
Owen Anderson92a20222011-07-21 18:54:16 +00002114 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2115 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002116 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002117 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002118 else
2119 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2120 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002121
Jim Grosbach19906722011-07-13 18:49:30 +00002122 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002123}
2124
2125
Bill Wendling50d0f582010-11-18 23:43:05 +00002126/// Try to parse a register name. The token must be an Identifier when called.
2127/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2128/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002129///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002130/// TODO this is likely to change to allow different register types and or to
2131/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002132bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002133tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002134 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002135 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002136 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002137 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002138
Bill Wendling50d0f582010-11-18 23:43:05 +00002139 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002140
Chris Lattnere5658fa2010-10-30 04:09:10 +00002141 const AsmToken &ExclaimTok = Parser.getTok();
2142 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002143 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2144 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002145 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002146 return false;
2147 }
2148
2149 // Also check for an index operand. This is only legal for vector registers,
2150 // but that'll get caught OK in operand matching, so we don't need to
2151 // explicitly filter everything else out here.
2152 if (Parser.getTok().is(AsmToken::LBrac)) {
2153 SMLoc SIdx = Parser.getTok().getLoc();
2154 Parser.Lex(); // Eat left bracket token.
2155
2156 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002157 if (getParser().ParseExpression(ImmVal))
2158 return MatchOperand_ParseFail;
2159 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2160 if (!MCE) {
2161 TokError("immediate value expected for vector index");
2162 return MatchOperand_ParseFail;
2163 }
2164
2165 SMLoc E = Parser.getTok().getLoc();
2166 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2167 Error(E, "']' expected");
2168 return MatchOperand_ParseFail;
2169 }
2170
2171 Parser.Lex(); // Eat right bracket token.
2172
2173 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2174 SIdx, E,
2175 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002176 }
2177
Bill Wendling50d0f582010-11-18 23:43:05 +00002178 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002179}
2180
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002181/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2182/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2183/// "c5", ...
2184static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002185 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2186 // but efficient.
2187 switch (Name.size()) {
2188 default: break;
2189 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002190 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002191 return -1;
2192 switch (Name[1]) {
2193 default: return -1;
2194 case '0': return 0;
2195 case '1': return 1;
2196 case '2': return 2;
2197 case '3': return 3;
2198 case '4': return 4;
2199 case '5': return 5;
2200 case '6': return 6;
2201 case '7': return 7;
2202 case '8': return 8;
2203 case '9': return 9;
2204 }
2205 break;
2206 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002207 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002208 return -1;
2209 switch (Name[2]) {
2210 default: return -1;
2211 case '0': return 10;
2212 case '1': return 11;
2213 case '2': return 12;
2214 case '3': return 13;
2215 case '4': return 14;
2216 case '5': return 15;
2217 }
2218 break;
2219 }
2220
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002221 return -1;
2222}
2223
Jim Grosbach89df9962011-08-26 21:43:41 +00002224/// parseITCondCode - Try to parse a condition code for an IT instruction.
2225ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2226parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2227 SMLoc S = Parser.getTok().getLoc();
2228 const AsmToken &Tok = Parser.getTok();
2229 if (!Tok.is(AsmToken::Identifier))
2230 return MatchOperand_NoMatch;
2231 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2232 .Case("eq", ARMCC::EQ)
2233 .Case("ne", ARMCC::NE)
2234 .Case("hs", ARMCC::HS)
2235 .Case("cs", ARMCC::HS)
2236 .Case("lo", ARMCC::LO)
2237 .Case("cc", ARMCC::LO)
2238 .Case("mi", ARMCC::MI)
2239 .Case("pl", ARMCC::PL)
2240 .Case("vs", ARMCC::VS)
2241 .Case("vc", ARMCC::VC)
2242 .Case("hi", ARMCC::HI)
2243 .Case("ls", ARMCC::LS)
2244 .Case("ge", ARMCC::GE)
2245 .Case("lt", ARMCC::LT)
2246 .Case("gt", ARMCC::GT)
2247 .Case("le", ARMCC::LE)
2248 .Case("al", ARMCC::AL)
2249 .Default(~0U);
2250 if (CC == ~0U)
2251 return MatchOperand_NoMatch;
2252 Parser.Lex(); // Eat the token.
2253
2254 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2255
2256 return MatchOperand_Success;
2257}
2258
Jim Grosbach43904292011-07-25 20:14:50 +00002259/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002260/// token must be an Identifier when called, and if it is a coprocessor
2261/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002262ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002263parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002264 SMLoc S = Parser.getTok().getLoc();
2265 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002266 if (Tok.isNot(AsmToken::Identifier))
2267 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002268
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002269 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002270 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002271 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002272
2273 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002274 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002275 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002276}
2277
Jim Grosbach43904292011-07-25 20:14:50 +00002278/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002279/// token must be an Identifier when called, and if it is a coprocessor
2280/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002281ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002282parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002283 SMLoc S = Parser.getTok().getLoc();
2284 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002285 if (Tok.isNot(AsmToken::Identifier))
2286 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002287
2288 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2289 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002290 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002291
2292 Parser.Lex(); // Eat identifier token.
2293 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002294 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002295}
2296
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002297/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2298/// coproc_option : '{' imm0_255 '}'
2299ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2300parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2301 SMLoc S = Parser.getTok().getLoc();
2302
2303 // If this isn't a '{', this isn't a coprocessor immediate operand.
2304 if (Parser.getTok().isNot(AsmToken::LCurly))
2305 return MatchOperand_NoMatch;
2306 Parser.Lex(); // Eat the '{'
2307
2308 const MCExpr *Expr;
2309 SMLoc Loc = Parser.getTok().getLoc();
2310 if (getParser().ParseExpression(Expr)) {
2311 Error(Loc, "illegal expression");
2312 return MatchOperand_ParseFail;
2313 }
2314 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2315 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2316 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2317 return MatchOperand_ParseFail;
2318 }
2319 int Val = CE->getValue();
2320
2321 // Check for and consume the closing '}'
2322 if (Parser.getTok().isNot(AsmToken::RCurly))
2323 return MatchOperand_ParseFail;
2324 SMLoc E = Parser.getTok().getLoc();
2325 Parser.Lex(); // Eat the '}'
2326
2327 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2328 return MatchOperand_Success;
2329}
2330
Jim Grosbachd0588e22011-09-14 18:08:35 +00002331// For register list parsing, we need to map from raw GPR register numbering
2332// to the enumeration values. The enumeration values aren't sorted by
2333// register number due to our using "sp", "lr" and "pc" as canonical names.
2334static unsigned getNextRegister(unsigned Reg) {
2335 // If this is a GPR, we need to do it manually, otherwise we can rely
2336 // on the sort ordering of the enumeration since the other reg-classes
2337 // are sane.
2338 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2339 return Reg + 1;
2340 switch(Reg) {
2341 default: assert(0 && "Invalid GPR number!");
2342 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2343 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2344 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2345 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2346 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2347 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2348 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2349 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2350 }
2351}
2352
Jim Grosbachce485e72011-11-11 21:27:40 +00002353// Return the low-subreg of a given Q register.
2354static unsigned getDRegFromQReg(unsigned QReg) {
2355 switch (QReg) {
2356 default: llvm_unreachable("expected a Q register!");
2357 case ARM::Q0: return ARM::D0;
2358 case ARM::Q1: return ARM::D2;
2359 case ARM::Q2: return ARM::D4;
2360 case ARM::Q3: return ARM::D6;
2361 case ARM::Q4: return ARM::D8;
2362 case ARM::Q5: return ARM::D10;
2363 case ARM::Q6: return ARM::D12;
2364 case ARM::Q7: return ARM::D14;
2365 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002366 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002367 case ARM::Q10: return ARM::D20;
2368 case ARM::Q11: return ARM::D22;
2369 case ARM::Q12: return ARM::D24;
2370 case ARM::Q13: return ARM::D26;
2371 case ARM::Q14: return ARM::D28;
2372 case ARM::Q15: return ARM::D30;
2373 }
2374}
2375
Jim Grosbachd0588e22011-09-14 18:08:35 +00002376/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002377bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002378parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002379 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002380 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002381 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002382 Parser.Lex(); // Eat '{' token.
2383 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002384
Jim Grosbachd0588e22011-09-14 18:08:35 +00002385 // Check the first register in the list to see what register class
2386 // this is a list of.
2387 int Reg = tryParseRegister();
2388 if (Reg == -1)
2389 return Error(RegLoc, "register expected");
2390
Jim Grosbachce485e72011-11-11 21:27:40 +00002391 // The reglist instructions have at most 16 registers, so reserve
2392 // space for that many.
2393 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2394
2395 // Allow Q regs and just interpret them as the two D sub-registers.
2396 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2397 Reg = getDRegFromQReg(Reg);
2398 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2399 ++Reg;
2400 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002401 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002402 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2403 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2404 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2405 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2406 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2407 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2408 else
2409 return Error(RegLoc, "invalid register in register list");
2410
Jim Grosbachce485e72011-11-11 21:27:40 +00002411 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002412 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002413
Jim Grosbachd0588e22011-09-14 18:08:35 +00002414 // This starts immediately after the first register token in the list,
2415 // so we can see either a comma or a minus (range separator) as a legal
2416 // next token.
2417 while (Parser.getTok().is(AsmToken::Comma) ||
2418 Parser.getTok().is(AsmToken::Minus)) {
2419 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002420 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002421 SMLoc EndLoc = Parser.getTok().getLoc();
2422 int EndReg = tryParseRegister();
2423 if (EndReg == -1)
2424 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002425 // Allow Q regs and just interpret them as the two D sub-registers.
2426 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2427 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002428 // If the register is the same as the start reg, there's nothing
2429 // more to do.
2430 if (Reg == EndReg)
2431 continue;
2432 // The register must be in the same register class as the first.
2433 if (!RC->contains(EndReg))
2434 return Error(EndLoc, "invalid register in register list");
2435 // Ranges must go from low to high.
2436 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2437 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002438
Jim Grosbachd0588e22011-09-14 18:08:35 +00002439 // Add all the registers in the range to the register list.
2440 while (Reg != EndReg) {
2441 Reg = getNextRegister(Reg);
2442 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2443 }
2444 continue;
2445 }
2446 Parser.Lex(); // Eat the comma.
2447 RegLoc = Parser.getTok().getLoc();
2448 int OldReg = Reg;
2449 Reg = tryParseRegister();
2450 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002451 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002452 // Allow Q regs and just interpret them as the two D sub-registers.
2453 bool isQReg = false;
2454 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2455 Reg = getDRegFromQReg(Reg);
2456 isQReg = true;
2457 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002458 // The register must be in the same register class as the first.
2459 if (!RC->contains(Reg))
2460 return Error(RegLoc, "invalid register in register list");
2461 // List must be monotonically increasing.
2462 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2463 return Error(RegLoc, "register list not in ascending order");
2464 // VFP register lists must also be contiguous.
2465 // It's OK to use the enumeration values directly here rather, as the
2466 // VFP register classes have the enum sorted properly.
2467 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2468 Reg != OldReg + 1)
2469 return Error(RegLoc, "non-contiguous register range");
2470 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002471 if (isQReg)
2472 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002473 }
2474
Jim Grosbachd0588e22011-09-14 18:08:35 +00002475 SMLoc E = Parser.getTok().getLoc();
2476 if (Parser.getTok().isNot(AsmToken::RCurly))
2477 return Error(E, "'}' expected");
2478 Parser.Lex(); // Eat '}' token.
2479
Bill Wendling50d0f582010-11-18 23:43:05 +00002480 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2481 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002482}
2483
Jim Grosbach862019c2011-10-18 23:02:30 +00002484// parse a vector register list
2485ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2486parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach5c984e42011-11-15 21:45:55 +00002487 SMLoc S = Parser.getTok().getLoc();
2488 // As an extension (to match gas), support a plain D register or Q register
2489 // (without encosing curly braces) as a single or double entry list,
2490 // respectively.
2491 if (Parser.getTok().is(AsmToken::Identifier)) {
2492 int Reg = tryParseRegister();
2493 if (Reg == -1)
2494 return MatchOperand_NoMatch;
2495 SMLoc E = Parser.getTok().getLoc();
2496 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
2497 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2498 return MatchOperand_Success;
2499 }
2500 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2501 Reg = getDRegFromQReg(Reg);
2502 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2503 return MatchOperand_Success;
2504 }
2505 Error(S, "vector register expected");
2506 return MatchOperand_ParseFail;
2507 }
2508
2509 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002510 return MatchOperand_NoMatch;
2511
Jim Grosbach862019c2011-10-18 23:02:30 +00002512 Parser.Lex(); // Eat '{' token.
2513 SMLoc RegLoc = Parser.getTok().getLoc();
2514
2515 int Reg = tryParseRegister();
2516 if (Reg == -1) {
2517 Error(RegLoc, "register expected");
2518 return MatchOperand_ParseFail;
2519 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002520 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002521 unsigned FirstReg = Reg;
2522 // The list is of D registers, but we also allow Q regs and just interpret
2523 // them as the two D sub-registers.
2524 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2525 FirstReg = Reg = getDRegFromQReg(Reg);
2526 ++Reg;
2527 ++Count;
2528 }
2529
Jim Grosbache43862b2011-11-15 23:19:15 +00002530 while (Parser.getTok().is(AsmToken::Comma) ||
2531 Parser.getTok().is(AsmToken::Minus)) {
2532 if (Parser.getTok().is(AsmToken::Minus)) {
2533 Parser.Lex(); // Eat the minus.
2534 SMLoc EndLoc = Parser.getTok().getLoc();
2535 int EndReg = tryParseRegister();
2536 if (EndReg == -1) {
2537 Error(EndLoc, "register expected");
2538 return MatchOperand_ParseFail;
2539 }
2540 // Allow Q regs and just interpret them as the two D sub-registers.
2541 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2542 EndReg = getDRegFromQReg(EndReg) + 1;
2543 // If the register is the same as the start reg, there's nothing
2544 // more to do.
2545 if (Reg == EndReg)
2546 continue;
2547 // The register must be in the same register class as the first.
2548 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2549 Error(EndLoc, "invalid register in register list");
2550 return MatchOperand_ParseFail;
2551 }
2552 // Ranges must go from low to high.
2553 if (Reg > EndReg) {
2554 Error(EndLoc, "bad range in register list");
2555 return MatchOperand_ParseFail;
2556 }
2557
2558 // Add all the registers in the range to the register list.
2559 Count += EndReg - Reg;
2560 Reg = EndReg;
2561 continue;
2562 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002563 Parser.Lex(); // Eat the comma.
2564 RegLoc = Parser.getTok().getLoc();
2565 int OldReg = Reg;
2566 Reg = tryParseRegister();
2567 if (Reg == -1) {
2568 Error(RegLoc, "register expected");
2569 return MatchOperand_ParseFail;
2570 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002571 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002572 // It's OK to use the enumeration values directly here rather, as the
2573 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002574 //
2575 // The list is of D registers, but we also allow Q regs and just interpret
2576 // them as the two D sub-registers.
2577 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2578 Reg = getDRegFromQReg(Reg);
2579 if (Reg != OldReg + 1) {
2580 Error(RegLoc, "non-contiguous register range");
2581 return MatchOperand_ParseFail;
2582 }
2583 ++Reg;
2584 Count += 2;
2585 continue;
2586 }
2587 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002588 if (Reg != OldReg + 1) {
2589 Error(RegLoc, "non-contiguous register range");
2590 return MatchOperand_ParseFail;
2591 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002592 ++Count;
2593 }
2594
2595 SMLoc E = Parser.getTok().getLoc();
2596 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2597 Error(E, "'}' expected");
2598 return MatchOperand_ParseFail;
2599 }
2600 Parser.Lex(); // Eat '}' token.
2601
2602 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2603 return MatchOperand_Success;
2604}
2605
Jim Grosbach43904292011-07-25 20:14:50 +00002606/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002607ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002608parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002609 SMLoc S = Parser.getTok().getLoc();
2610 const AsmToken &Tok = Parser.getTok();
2611 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2612 StringRef OptStr = Tok.getString();
2613
2614 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2615 .Case("sy", ARM_MB::SY)
2616 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002617 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002618 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002619 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002620 .Case("ishst", ARM_MB::ISHST)
2621 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002622 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002623 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002624 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002625 .Case("osh", ARM_MB::OSH)
2626 .Case("oshst", ARM_MB::OSHST)
2627 .Default(~0U);
2628
2629 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002630 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002631
2632 Parser.Lex(); // Eat identifier token.
2633 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002634 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002635}
2636
Jim Grosbach43904292011-07-25 20:14:50 +00002637/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002638ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002639parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002640 SMLoc S = Parser.getTok().getLoc();
2641 const AsmToken &Tok = Parser.getTok();
2642 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2643 StringRef IFlagsStr = Tok.getString();
2644
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002645 // An iflags string of "none" is interpreted to mean that none of the AIF
2646 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002647 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002648 if (IFlagsStr != "none") {
2649 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2650 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2651 .Case("a", ARM_PROC::A)
2652 .Case("i", ARM_PROC::I)
2653 .Case("f", ARM_PROC::F)
2654 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002655
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002656 // If some specific iflag is already set, it means that some letter is
2657 // present more than once, this is not acceptable.
2658 if (Flag == ~0U || (IFlags & Flag))
2659 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002660
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002661 IFlags |= Flag;
2662 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002663 }
2664
2665 Parser.Lex(); // Eat identifier token.
2666 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2667 return MatchOperand_Success;
2668}
2669
Jim Grosbach43904292011-07-25 20:14:50 +00002670/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002671ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002672parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002673 SMLoc S = Parser.getTok().getLoc();
2674 const AsmToken &Tok = Parser.getTok();
2675 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2676 StringRef Mask = Tok.getString();
2677
James Molloyacad68d2011-09-28 14:21:38 +00002678 if (isMClass()) {
2679 // See ARMv6-M 10.1.1
2680 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2681 .Case("apsr", 0)
2682 .Case("iapsr", 1)
2683 .Case("eapsr", 2)
2684 .Case("xpsr", 3)
2685 .Case("ipsr", 5)
2686 .Case("epsr", 6)
2687 .Case("iepsr", 7)
2688 .Case("msp", 8)
2689 .Case("psp", 9)
2690 .Case("primask", 16)
2691 .Case("basepri", 17)
2692 .Case("basepri_max", 18)
2693 .Case("faultmask", 19)
2694 .Case("control", 20)
2695 .Default(~0U);
2696
2697 if (FlagsVal == ~0U)
2698 return MatchOperand_NoMatch;
2699
2700 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2701 // basepri, basepri_max and faultmask only valid for V7m.
2702 return MatchOperand_NoMatch;
2703
2704 Parser.Lex(); // Eat identifier token.
2705 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2706 return MatchOperand_Success;
2707 }
2708
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002709 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2710 size_t Start = 0, Next = Mask.find('_');
2711 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002712 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002713 if (Next != StringRef::npos)
2714 Flags = Mask.slice(Next+1, Mask.size());
2715
2716 // FlagsVal contains the complete mask:
2717 // 3-0: Mask
2718 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2719 unsigned FlagsVal = 0;
2720
2721 if (SpecReg == "apsr") {
2722 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002723 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002724 .Case("g", 0x4) // same as CPSR_s
2725 .Case("nzcvqg", 0xc) // same as CPSR_fs
2726 .Default(~0U);
2727
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002728 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002729 if (!Flags.empty())
2730 return MatchOperand_NoMatch;
2731 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002732 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002733 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002734 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002735 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2736 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002737 for (int i = 0, e = Flags.size(); i != e; ++i) {
2738 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2739 .Case("c", 1)
2740 .Case("x", 2)
2741 .Case("s", 4)
2742 .Case("f", 8)
2743 .Default(~0U);
2744
2745 // If some specific flag is already set, it means that some letter is
2746 // present more than once, this is not acceptable.
2747 if (FlagsVal == ~0U || (FlagsVal & Flag))
2748 return MatchOperand_NoMatch;
2749 FlagsVal |= Flag;
2750 }
2751 } else // No match for special register.
2752 return MatchOperand_NoMatch;
2753
Owen Anderson7784f1d2011-10-21 18:43:28 +00002754 // Special register without flags is NOT equivalent to "fc" flags.
2755 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2756 // two lines would enable gas compatibility at the expense of breaking
2757 // round-tripping.
2758 //
2759 // if (!FlagsVal)
2760 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002761
2762 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2763 if (SpecReg == "spsr")
2764 FlagsVal |= 16;
2765
2766 Parser.Lex(); // Eat identifier token.
2767 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2768 return MatchOperand_Success;
2769}
2770
Jim Grosbachf6c05252011-07-21 17:23:04 +00002771ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2772parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2773 int Low, int High) {
2774 const AsmToken &Tok = Parser.getTok();
2775 if (Tok.isNot(AsmToken::Identifier)) {
2776 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2777 return MatchOperand_ParseFail;
2778 }
2779 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002780 std::string LowerOp = Op.lower();
2781 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002782 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2783 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2784 return MatchOperand_ParseFail;
2785 }
2786 Parser.Lex(); // Eat shift type token.
2787
2788 // There must be a '#' and a shift amount.
2789 if (Parser.getTok().isNot(AsmToken::Hash)) {
2790 Error(Parser.getTok().getLoc(), "'#' expected");
2791 return MatchOperand_ParseFail;
2792 }
2793 Parser.Lex(); // Eat hash token.
2794
2795 const MCExpr *ShiftAmount;
2796 SMLoc Loc = Parser.getTok().getLoc();
2797 if (getParser().ParseExpression(ShiftAmount)) {
2798 Error(Loc, "illegal expression");
2799 return MatchOperand_ParseFail;
2800 }
2801 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2802 if (!CE) {
2803 Error(Loc, "constant expression expected");
2804 return MatchOperand_ParseFail;
2805 }
2806 int Val = CE->getValue();
2807 if (Val < Low || Val > High) {
2808 Error(Loc, "immediate value out of range");
2809 return MatchOperand_ParseFail;
2810 }
2811
2812 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2813
2814 return MatchOperand_Success;
2815}
2816
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002817ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2818parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2819 const AsmToken &Tok = Parser.getTok();
2820 SMLoc S = Tok.getLoc();
2821 if (Tok.isNot(AsmToken::Identifier)) {
2822 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2823 return MatchOperand_ParseFail;
2824 }
2825 int Val = StringSwitch<int>(Tok.getString())
2826 .Case("be", 1)
2827 .Case("le", 0)
2828 .Default(-1);
2829 Parser.Lex(); // Eat the token.
2830
2831 if (Val == -1) {
2832 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2833 return MatchOperand_ParseFail;
2834 }
2835 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2836 getContext()),
2837 S, Parser.getTok().getLoc()));
2838 return MatchOperand_Success;
2839}
2840
Jim Grosbach580f4a92011-07-25 22:20:28 +00002841/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2842/// instructions. Legal values are:
2843/// lsl #n 'n' in [0,31]
2844/// asr #n 'n' in [1,32]
2845/// n == 32 encoded as n == 0.
2846ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2847parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2848 const AsmToken &Tok = Parser.getTok();
2849 SMLoc S = Tok.getLoc();
2850 if (Tok.isNot(AsmToken::Identifier)) {
2851 Error(S, "shift operator 'asr' or 'lsl' expected");
2852 return MatchOperand_ParseFail;
2853 }
2854 StringRef ShiftName = Tok.getString();
2855 bool isASR;
2856 if (ShiftName == "lsl" || ShiftName == "LSL")
2857 isASR = false;
2858 else if (ShiftName == "asr" || ShiftName == "ASR")
2859 isASR = true;
2860 else {
2861 Error(S, "shift operator 'asr' or 'lsl' expected");
2862 return MatchOperand_ParseFail;
2863 }
2864 Parser.Lex(); // Eat the operator.
2865
2866 // A '#' and a shift amount.
2867 if (Parser.getTok().isNot(AsmToken::Hash)) {
2868 Error(Parser.getTok().getLoc(), "'#' expected");
2869 return MatchOperand_ParseFail;
2870 }
2871 Parser.Lex(); // Eat hash token.
2872
2873 const MCExpr *ShiftAmount;
2874 SMLoc E = Parser.getTok().getLoc();
2875 if (getParser().ParseExpression(ShiftAmount)) {
2876 Error(E, "malformed shift expression");
2877 return MatchOperand_ParseFail;
2878 }
2879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2880 if (!CE) {
2881 Error(E, "shift amount must be an immediate");
2882 return MatchOperand_ParseFail;
2883 }
2884
2885 int64_t Val = CE->getValue();
2886 if (isASR) {
2887 // Shift amount must be in [1,32]
2888 if (Val < 1 || Val > 32) {
2889 Error(E, "'asr' shift amount must be in range [1,32]");
2890 return MatchOperand_ParseFail;
2891 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002892 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2893 if (isThumb() && Val == 32) {
2894 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2895 return MatchOperand_ParseFail;
2896 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002897 if (Val == 32) Val = 0;
2898 } else {
2899 // Shift amount must be in [1,32]
2900 if (Val < 0 || Val > 31) {
2901 Error(E, "'lsr' shift amount must be in range [0,31]");
2902 return MatchOperand_ParseFail;
2903 }
2904 }
2905
2906 E = Parser.getTok().getLoc();
2907 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2908
2909 return MatchOperand_Success;
2910}
2911
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002912/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2913/// of instructions. Legal values are:
2914/// ror #n 'n' in {0, 8, 16, 24}
2915ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2916parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2917 const AsmToken &Tok = Parser.getTok();
2918 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00002919 if (Tok.isNot(AsmToken::Identifier))
2920 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002921 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00002922 if (ShiftName != "ror" && ShiftName != "ROR")
2923 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002924 Parser.Lex(); // Eat the operator.
2925
2926 // A '#' and a rotate amount.
2927 if (Parser.getTok().isNot(AsmToken::Hash)) {
2928 Error(Parser.getTok().getLoc(), "'#' expected");
2929 return MatchOperand_ParseFail;
2930 }
2931 Parser.Lex(); // Eat hash token.
2932
2933 const MCExpr *ShiftAmount;
2934 SMLoc E = Parser.getTok().getLoc();
2935 if (getParser().ParseExpression(ShiftAmount)) {
2936 Error(E, "malformed rotate expression");
2937 return MatchOperand_ParseFail;
2938 }
2939 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2940 if (!CE) {
2941 Error(E, "rotate amount must be an immediate");
2942 return MatchOperand_ParseFail;
2943 }
2944
2945 int64_t Val = CE->getValue();
2946 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
2947 // normally, zero is represented in asm by omitting the rotate operand
2948 // entirely.
2949 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
2950 Error(E, "'ror' rotate amount must be 8, 16, or 24");
2951 return MatchOperand_ParseFail;
2952 }
2953
2954 E = Parser.getTok().getLoc();
2955 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
2956
2957 return MatchOperand_Success;
2958}
2959
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002960ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2961parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2962 SMLoc S = Parser.getTok().getLoc();
2963 // The bitfield descriptor is really two operands, the LSB and the width.
2964 if (Parser.getTok().isNot(AsmToken::Hash)) {
2965 Error(Parser.getTok().getLoc(), "'#' expected");
2966 return MatchOperand_ParseFail;
2967 }
2968 Parser.Lex(); // Eat hash token.
2969
2970 const MCExpr *LSBExpr;
2971 SMLoc E = Parser.getTok().getLoc();
2972 if (getParser().ParseExpression(LSBExpr)) {
2973 Error(E, "malformed immediate expression");
2974 return MatchOperand_ParseFail;
2975 }
2976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
2977 if (!CE) {
2978 Error(E, "'lsb' operand must be an immediate");
2979 return MatchOperand_ParseFail;
2980 }
2981
2982 int64_t LSB = CE->getValue();
2983 // The LSB must be in the range [0,31]
2984 if (LSB < 0 || LSB > 31) {
2985 Error(E, "'lsb' operand must be in the range [0,31]");
2986 return MatchOperand_ParseFail;
2987 }
2988 E = Parser.getTok().getLoc();
2989
2990 // Expect another immediate operand.
2991 if (Parser.getTok().isNot(AsmToken::Comma)) {
2992 Error(Parser.getTok().getLoc(), "too few operands");
2993 return MatchOperand_ParseFail;
2994 }
2995 Parser.Lex(); // Eat hash token.
2996 if (Parser.getTok().isNot(AsmToken::Hash)) {
2997 Error(Parser.getTok().getLoc(), "'#' expected");
2998 return MatchOperand_ParseFail;
2999 }
3000 Parser.Lex(); // Eat hash token.
3001
3002 const MCExpr *WidthExpr;
3003 if (getParser().ParseExpression(WidthExpr)) {
3004 Error(E, "malformed immediate expression");
3005 return MatchOperand_ParseFail;
3006 }
3007 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3008 if (!CE) {
3009 Error(E, "'width' operand must be an immediate");
3010 return MatchOperand_ParseFail;
3011 }
3012
3013 int64_t Width = CE->getValue();
3014 // The LSB must be in the range [1,32-lsb]
3015 if (Width < 1 || Width > 32 - LSB) {
3016 Error(E, "'width' operand must be in the range [1,32-lsb]");
3017 return MatchOperand_ParseFail;
3018 }
3019 E = Parser.getTok().getLoc();
3020
3021 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3022
3023 return MatchOperand_Success;
3024}
3025
Jim Grosbach7ce05792011-08-03 23:50:40 +00003026ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3027parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3028 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003029 // postidx_reg := '+' register {, shift}
3030 // | '-' register {, shift}
3031 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003032
3033 // This method must return MatchOperand_NoMatch without consuming any tokens
3034 // in the case where there is no match, as other alternatives take other
3035 // parse methods.
3036 AsmToken Tok = Parser.getTok();
3037 SMLoc S = Tok.getLoc();
3038 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003039 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003040 int Reg = -1;
3041 if (Tok.is(AsmToken::Plus)) {
3042 Parser.Lex(); // Eat the '+' token.
3043 haveEaten = true;
3044 } else if (Tok.is(AsmToken::Minus)) {
3045 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003046 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003047 haveEaten = true;
3048 }
3049 if (Parser.getTok().is(AsmToken::Identifier))
3050 Reg = tryParseRegister();
3051 if (Reg == -1) {
3052 if (!haveEaten)
3053 return MatchOperand_NoMatch;
3054 Error(Parser.getTok().getLoc(), "register expected");
3055 return MatchOperand_ParseFail;
3056 }
3057 SMLoc E = Parser.getTok().getLoc();
3058
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003059 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3060 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003061 if (Parser.getTok().is(AsmToken::Comma)) {
3062 Parser.Lex(); // Eat the ','.
3063 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3064 return MatchOperand_ParseFail;
3065 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003066
3067 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3068 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003069
3070 return MatchOperand_Success;
3071}
3072
Jim Grosbach251bf252011-08-10 21:56:18 +00003073ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3074parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3075 // Check for a post-index addressing register operand. Specifically:
3076 // am3offset := '+' register
3077 // | '-' register
3078 // | register
3079 // | # imm
3080 // | # + imm
3081 // | # - imm
3082
3083 // This method must return MatchOperand_NoMatch without consuming any tokens
3084 // in the case where there is no match, as other alternatives take other
3085 // parse methods.
3086 AsmToken Tok = Parser.getTok();
3087 SMLoc S = Tok.getLoc();
3088
3089 // Do immediates first, as we always parse those if we have a '#'.
3090 if (Parser.getTok().is(AsmToken::Hash)) {
3091 Parser.Lex(); // Eat the '#'.
3092 // Explicitly look for a '-', as we need to encode negative zero
3093 // differently.
3094 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3095 const MCExpr *Offset;
3096 if (getParser().ParseExpression(Offset))
3097 return MatchOperand_ParseFail;
3098 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3099 if (!CE) {
3100 Error(S, "constant expression expected");
3101 return MatchOperand_ParseFail;
3102 }
3103 SMLoc E = Tok.getLoc();
3104 // Negative zero is encoded as the flag value INT32_MIN.
3105 int32_t Val = CE->getValue();
3106 if (isNegative && Val == 0)
3107 Val = INT32_MIN;
3108
3109 Operands.push_back(
3110 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3111
3112 return MatchOperand_Success;
3113 }
3114
3115
3116 bool haveEaten = false;
3117 bool isAdd = true;
3118 int Reg = -1;
3119 if (Tok.is(AsmToken::Plus)) {
3120 Parser.Lex(); // Eat the '+' token.
3121 haveEaten = true;
3122 } else if (Tok.is(AsmToken::Minus)) {
3123 Parser.Lex(); // Eat the '-' token.
3124 isAdd = false;
3125 haveEaten = true;
3126 }
3127 if (Parser.getTok().is(AsmToken::Identifier))
3128 Reg = tryParseRegister();
3129 if (Reg == -1) {
3130 if (!haveEaten)
3131 return MatchOperand_NoMatch;
3132 Error(Parser.getTok().getLoc(), "register expected");
3133 return MatchOperand_ParseFail;
3134 }
3135 SMLoc E = Parser.getTok().getLoc();
3136
3137 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3138 0, S, E));
3139
3140 return MatchOperand_Success;
3141}
3142
Jim Grosbacha77295d2011-09-08 22:07:06 +00003143/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3144/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3145/// when they refer multiple MIOperands inside a single one.
3146bool ARMAsmParser::
3147cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3148 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3149 // Rt, Rt2
3150 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3151 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3152 // Create a writeback register dummy placeholder.
3153 Inst.addOperand(MCOperand::CreateReg(0));
3154 // addr
3155 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3156 // pred
3157 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3158 return true;
3159}
3160
3161/// cvtT2StrdPre - Convert parsed operands to MCInst.
3162/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3163/// when they refer multiple MIOperands inside a single one.
3164bool ARMAsmParser::
3165cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3166 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3167 // Create a writeback register dummy placeholder.
3168 Inst.addOperand(MCOperand::CreateReg(0));
3169 // Rt, Rt2
3170 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3171 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3172 // addr
3173 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3174 // pred
3175 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3176 return true;
3177}
3178
Jim Grosbacheeec0252011-09-08 00:39:19 +00003179/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3180/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3181/// when they refer multiple MIOperands inside a single one.
3182bool ARMAsmParser::
3183cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3184 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3185 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3186
3187 // Create a writeback register dummy placeholder.
3188 Inst.addOperand(MCOperand::CreateImm(0));
3189
3190 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3191 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3192 return true;
3193}
3194
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003195/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3196/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3197/// when they refer multiple MIOperands inside a single one.
3198bool ARMAsmParser::
3199cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3200 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3201 // Create a writeback register dummy placeholder.
3202 Inst.addOperand(MCOperand::CreateImm(0));
3203 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3204 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3205 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3206 return true;
3207}
3208
Jim Grosbach1355cf12011-07-26 17:10:22 +00003209/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003210/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3211/// when they refer multiple MIOperands inside a single one.
3212bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003213cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003214 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3215 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3216
3217 // Create a writeback register dummy placeholder.
3218 Inst.addOperand(MCOperand::CreateImm(0));
3219
Jim Grosbach7ce05792011-08-03 23:50:40 +00003220 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003221 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3222 return true;
3223}
3224
Owen Anderson9ab0f252011-08-26 20:43:14 +00003225/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3226/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3227/// when they refer multiple MIOperands inside a single one.
3228bool ARMAsmParser::
3229cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3230 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3231 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3232
3233 // Create a writeback register dummy placeholder.
3234 Inst.addOperand(MCOperand::CreateImm(0));
3235
3236 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3237 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3238 return true;
3239}
3240
3241
Jim Grosbach548340c2011-08-11 19:22:40 +00003242/// cvtStWriteBackRegAddrModeImm12 - 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::
3246cvtStWriteBackRegAddrModeImm12(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])->addMemImm12OffsetOperands(Inst, 2);
3252 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3253 return true;
3254}
3255
Jim Grosbach1355cf12011-07-26 17:10:22 +00003256/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003257/// 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::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003260cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003261 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3262 // Create a writeback register dummy placeholder.
3263 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003264 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3265 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3266 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003267 return true;
3268}
3269
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003270/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3271/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3272/// when they refer multiple MIOperands inside a single one.
3273bool ARMAsmParser::
3274cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3275 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3276 // Create a writeback register dummy placeholder.
3277 Inst.addOperand(MCOperand::CreateImm(0));
3278 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3279 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3280 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3281 return true;
3282}
3283
Jim Grosbach7ce05792011-08-03 23:50:40 +00003284/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3285/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3286/// when they refer multiple MIOperands inside a single one.
3287bool ARMAsmParser::
3288cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3289 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3290 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003291 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003292 // Create a writeback register dummy placeholder.
3293 Inst.addOperand(MCOperand::CreateImm(0));
3294 // addr
3295 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3296 // offset
3297 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3298 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003299 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3300 return true;
3301}
3302
Jim Grosbach7ce05792011-08-03 23:50:40 +00003303/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003304/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3305/// when they refer multiple MIOperands inside a single one.
3306bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003307cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3308 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3309 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003310 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003311 // Create a writeback register dummy placeholder.
3312 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003313 // addr
3314 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3315 // offset
3316 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3317 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003318 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3319 return true;
3320}
3321
Jim Grosbach7ce05792011-08-03 23:50:40 +00003322/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003323/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3324/// when they refer multiple MIOperands inside a single one.
3325bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003326cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3327 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003328 // Create a writeback register dummy placeholder.
3329 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003330 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003331 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003332 // addr
3333 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3334 // offset
3335 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3336 // pred
3337 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3338 return true;
3339}
3340
3341/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3342/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3343/// when they refer multiple MIOperands inside a single one.
3344bool ARMAsmParser::
3345cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3346 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3347 // Create a writeback register dummy placeholder.
3348 Inst.addOperand(MCOperand::CreateImm(0));
3349 // Rt
3350 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3351 // addr
3352 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3353 // offset
3354 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3355 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003356 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3357 return true;
3358}
3359
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003360/// cvtLdrdPre - Convert parsed operands to MCInst.
3361/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3362/// when they refer multiple MIOperands inside a single one.
3363bool ARMAsmParser::
3364cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3365 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3366 // Rt, Rt2
3367 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3368 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3369 // Create a writeback register dummy placeholder.
3370 Inst.addOperand(MCOperand::CreateImm(0));
3371 // addr
3372 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3373 // pred
3374 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3375 return true;
3376}
3377
Jim Grosbach14605d12011-08-11 20:28:23 +00003378/// cvtStrdPre - Convert parsed operands to MCInst.
3379/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3380/// when they refer multiple MIOperands inside a single one.
3381bool ARMAsmParser::
3382cvtStrdPre(MCInst &Inst, unsigned Opcode,
3383 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3384 // Create a writeback register dummy placeholder.
3385 Inst.addOperand(MCOperand::CreateImm(0));
3386 // Rt, Rt2
3387 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3388 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3389 // addr
3390 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3391 // pred
3392 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3393 return true;
3394}
3395
Jim Grosbach623a4542011-08-10 22:42:16 +00003396/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3397/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3398/// when they refer multiple MIOperands inside a single one.
3399bool ARMAsmParser::
3400cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3401 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3402 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3403 // Create a writeback register dummy placeholder.
3404 Inst.addOperand(MCOperand::CreateImm(0));
3405 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3406 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3407 return true;
3408}
3409
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003410/// cvtThumbMultiple- Convert parsed operands to MCInst.
3411/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3412/// when they refer multiple MIOperands inside a single one.
3413bool ARMAsmParser::
3414cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3415 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3416 // The second source operand must be the same register as the destination
3417 // operand.
3418 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003419 (((ARMOperand*)Operands[3])->getReg() !=
3420 ((ARMOperand*)Operands[5])->getReg()) &&
3421 (((ARMOperand*)Operands[3])->getReg() !=
3422 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003423 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003424 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003425 return false;
3426 }
3427 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3428 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003429 // If we have a three-operand form, make sure to set Rn to be the operand
3430 // that isn't the same as Rd.
3431 unsigned RegOp = 4;
3432 if (Operands.size() == 6 &&
3433 ((ARMOperand*)Operands[4])->getReg() ==
3434 ((ARMOperand*)Operands[3])->getReg())
3435 RegOp = 5;
3436 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3437 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003438 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3439
3440 return true;
3441}
Jim Grosbach623a4542011-08-10 22:42:16 +00003442
Jim Grosbach12431322011-10-24 22:16:58 +00003443bool ARMAsmParser::
3444cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3445 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3446 // Vd
3447 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3448 // Create a writeback register dummy placeholder.
3449 Inst.addOperand(MCOperand::CreateImm(0));
3450 // Vn
3451 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3452 // pred
3453 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3454 return true;
3455}
3456
3457bool ARMAsmParser::
3458cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3459 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3460 // Vd
3461 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
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 // pred
3469 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3470 return true;
3471}
3472
Jim Grosbach4334e032011-10-31 21:50:31 +00003473bool ARMAsmParser::
3474cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3475 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3476 // Create a writeback register dummy placeholder.
3477 Inst.addOperand(MCOperand::CreateImm(0));
3478 // Vn
3479 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3480 // Vt
3481 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3482 // pred
3483 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3484 return true;
3485}
3486
3487bool ARMAsmParser::
3488cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3489 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3490 // Create a writeback register dummy placeholder.
3491 Inst.addOperand(MCOperand::CreateImm(0));
3492 // Vn
3493 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3494 // Vm
3495 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3496 // Vt
3497 ((ARMOperand*)Operands[3])->addVecListTwoDOperands(Inst, 1);
3498 // pred
3499 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3500 return true;
3501}
3502
Bill Wendlinge7176102010-11-06 22:36:58 +00003503/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003504/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003505bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003506parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003507 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003508 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003509 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003510 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003511 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003512
Sean Callanan18b83232010-01-19 21:44:56 +00003513 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003514 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003515 if (BaseRegNum == -1)
3516 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003517
Daniel Dunbar05710932011-01-18 05:34:17 +00003518 // The next token must either be a comma or a closing bracket.
3519 const AsmToken &Tok = Parser.getTok();
3520 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003521 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003522
Jim Grosbach7ce05792011-08-03 23:50:40 +00003523 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003524 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003525 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003526
Jim Grosbach7ce05792011-08-03 23:50:40 +00003527 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003528 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003529
Jim Grosbachfb12f352011-09-19 18:42:21 +00003530 // If there's a pre-indexing writeback marker, '!', just add it as a token
3531 // operand. It's rather odd, but syntactically valid.
3532 if (Parser.getTok().is(AsmToken::Exclaim)) {
3533 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3534 Parser.Lex(); // Eat the '!'.
3535 }
3536
Jim Grosbach7ce05792011-08-03 23:50:40 +00003537 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003538 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003539
Jim Grosbach7ce05792011-08-03 23:50:40 +00003540 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3541 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003542
Jim Grosbach57dcb852011-10-11 17:29:55 +00003543 // If we have a ':', it's an alignment specifier.
3544 if (Parser.getTok().is(AsmToken::Colon)) {
3545 Parser.Lex(); // Eat the ':'.
3546 E = Parser.getTok().getLoc();
3547
3548 const MCExpr *Expr;
3549 if (getParser().ParseExpression(Expr))
3550 return true;
3551
3552 // The expression has to be a constant. Memory references with relocations
3553 // don't come through here, as they use the <label> forms of the relevant
3554 // instructions.
3555 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3556 if (!CE)
3557 return Error (E, "constant expression expected");
3558
3559 unsigned Align = 0;
3560 switch (CE->getValue()) {
3561 default:
3562 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3563 case 64: Align = 8; break;
3564 case 128: Align = 16; break;
3565 case 256: Align = 32; break;
3566 }
3567
3568 // Now we should have the closing ']'
3569 E = Parser.getTok().getLoc();
3570 if (Parser.getTok().isNot(AsmToken::RBrac))
3571 return Error(E, "']' expected");
3572 Parser.Lex(); // Eat right bracket token.
3573
3574 // Don't worry about range checking the value here. That's handled by
3575 // the is*() predicates.
3576 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3577 ARM_AM::no_shift, 0, Align,
3578 false, S, E));
3579
3580 // If there's a pre-indexing writeback marker, '!', just add it as a token
3581 // operand.
3582 if (Parser.getTok().is(AsmToken::Exclaim)) {
3583 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3584 Parser.Lex(); // Eat the '!'.
3585 }
3586
3587 return false;
3588 }
3589
3590 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003591 // offset. Be friendly and also accept a plain integer (without a leading
3592 // hash) for gas compatibility.
3593 if (Parser.getTok().is(AsmToken::Hash) ||
3594 Parser.getTok().is(AsmToken::Integer)) {
3595 if (Parser.getTok().is(AsmToken::Hash))
3596 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003597 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003598
Owen Anderson0da10cf2011-08-29 19:36:44 +00003599 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003600 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003601 if (getParser().ParseExpression(Offset))
3602 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003603
3604 // The expression has to be a constant. Memory references with relocations
3605 // don't come through here, as they use the <label> forms of the relevant
3606 // instructions.
3607 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3608 if (!CE)
3609 return Error (E, "constant expression expected");
3610
Owen Anderson0da10cf2011-08-29 19:36:44 +00003611 // If the constant was #-0, represent it as INT32_MIN.
3612 int32_t Val = CE->getValue();
3613 if (isNegative && Val == 0)
3614 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3615
Jim Grosbach7ce05792011-08-03 23:50:40 +00003616 // Now we should have the closing ']'
3617 E = Parser.getTok().getLoc();
3618 if (Parser.getTok().isNot(AsmToken::RBrac))
3619 return Error(E, "']' expected");
3620 Parser.Lex(); // Eat right bracket token.
3621
3622 // Don't worry about range checking the value here. That's handled by
3623 // the is*() predicates.
3624 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003625 ARM_AM::no_shift, 0, 0,
3626 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003627
3628 // If there's a pre-indexing writeback marker, '!', just add it as a token
3629 // operand.
3630 if (Parser.getTok().is(AsmToken::Exclaim)) {
3631 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3632 Parser.Lex(); // Eat the '!'.
3633 }
3634
3635 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003636 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003637
3638 // The register offset is optionally preceded by a '+' or '-'
3639 bool isNegative = false;
3640 if (Parser.getTok().is(AsmToken::Minus)) {
3641 isNegative = true;
3642 Parser.Lex(); // Eat the '-'.
3643 } else if (Parser.getTok().is(AsmToken::Plus)) {
3644 // Nothing to do.
3645 Parser.Lex(); // Eat the '+'.
3646 }
3647
3648 E = Parser.getTok().getLoc();
3649 int OffsetRegNum = tryParseRegister();
3650 if (OffsetRegNum == -1)
3651 return Error(E, "register expected");
3652
3653 // If there's a shift operator, handle it.
3654 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003655 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003656 if (Parser.getTok().is(AsmToken::Comma)) {
3657 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003658 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003659 return true;
3660 }
3661
3662 // Now we should have the closing ']'
3663 E = Parser.getTok().getLoc();
3664 if (Parser.getTok().isNot(AsmToken::RBrac))
3665 return Error(E, "']' expected");
3666 Parser.Lex(); // Eat right bracket token.
3667
3668 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003669 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003670 S, E));
3671
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003672 // If there's a pre-indexing writeback marker, '!', just add it as a token
3673 // operand.
3674 if (Parser.getTok().is(AsmToken::Exclaim)) {
3675 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3676 Parser.Lex(); // Eat the '!'.
3677 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003678
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003679 return false;
3680}
3681
Jim Grosbach7ce05792011-08-03 23:50:40 +00003682/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003683/// ( lsl | lsr | asr | ror ) , # shift_amount
3684/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003685/// return true if it parses a shift otherwise it returns false.
3686bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3687 unsigned &Amount) {
3688 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003689 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003690 if (Tok.isNot(AsmToken::Identifier))
3691 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003692 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003693 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003694 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003695 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003696 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003697 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003698 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003699 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003700 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003701 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003702 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003703 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003704 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003705 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003706
Jim Grosbach7ce05792011-08-03 23:50:40 +00003707 // rrx stands alone.
3708 Amount = 0;
3709 if (St != ARM_AM::rrx) {
3710 Loc = Parser.getTok().getLoc();
3711 // A '#' and a shift amount.
3712 const AsmToken &HashTok = Parser.getTok();
3713 if (HashTok.isNot(AsmToken::Hash))
3714 return Error(HashTok.getLoc(), "'#' expected");
3715 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003716
Jim Grosbach7ce05792011-08-03 23:50:40 +00003717 const MCExpr *Expr;
3718 if (getParser().ParseExpression(Expr))
3719 return true;
3720 // Range check the immediate.
3721 // lsl, ror: 0 <= imm <= 31
3722 // lsr, asr: 0 <= imm <= 32
3723 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3724 if (!CE)
3725 return Error(Loc, "shift amount must be an immediate");
3726 int64_t Imm = CE->getValue();
3727 if (Imm < 0 ||
3728 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3729 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3730 return Error(Loc, "immediate shift value out of range");
3731 Amount = Imm;
3732 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003733
3734 return false;
3735}
3736
Jim Grosbach9d390362011-10-03 23:38:36 +00003737/// parseFPImm - A floating point immediate expression operand.
3738ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3739parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3740 SMLoc S = Parser.getTok().getLoc();
3741
3742 if (Parser.getTok().isNot(AsmToken::Hash))
3743 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003744
3745 // Disambiguate the VMOV forms that can accept an FP immediate.
3746 // vmov.f32 <sreg>, #imm
3747 // vmov.f64 <dreg>, #imm
3748 // vmov.f32 <dreg>, #imm @ vector f32x2
3749 // vmov.f32 <qreg>, #imm @ vector f32x4
3750 //
3751 // There are also the NEON VMOV instructions which expect an
3752 // integer constant. Make sure we don't try to parse an FPImm
3753 // for these:
3754 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3755 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3756 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3757 TyOp->getToken() != ".f64"))
3758 return MatchOperand_NoMatch;
3759
Jim Grosbach9d390362011-10-03 23:38:36 +00003760 Parser.Lex(); // Eat the '#'.
3761
3762 // Handle negation, as that still comes through as a separate token.
3763 bool isNegative = false;
3764 if (Parser.getTok().is(AsmToken::Minus)) {
3765 isNegative = true;
3766 Parser.Lex();
3767 }
3768 const AsmToken &Tok = Parser.getTok();
3769 if (Tok.is(AsmToken::Real)) {
3770 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3771 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3772 // If we had a '-' in front, toggle the sign bit.
3773 IntVal ^= (uint64_t)isNegative << 63;
3774 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3775 Parser.Lex(); // Eat the token.
3776 if (Val == -1) {
3777 TokError("floating point value out of range");
3778 return MatchOperand_ParseFail;
3779 }
3780 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3781 return MatchOperand_Success;
3782 }
3783 if (Tok.is(AsmToken::Integer)) {
3784 int64_t Val = Tok.getIntVal();
3785 Parser.Lex(); // Eat the token.
3786 if (Val > 255 || Val < 0) {
3787 TokError("encoded floating point value out of range");
3788 return MatchOperand_ParseFail;
3789 }
3790 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3791 return MatchOperand_Success;
3792 }
3793
3794 TokError("invalid floating point immediate");
3795 return MatchOperand_ParseFail;
3796}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003797/// Parse a arm instruction operand. For now this parses the operand regardless
3798/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003799bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003800 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003801 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003802
3803 // Check if the current operand has a custom associated parser, if so, try to
3804 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003805 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3806 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003807 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003808 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3809 // there was a match, but an error occurred, in which case, just return that
3810 // the operand parsing failed.
3811 if (ResTy == MatchOperand_ParseFail)
3812 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003813
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003814 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003815 default:
3816 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003817 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003818 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003819 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003820 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003821 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003822 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003823 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003824 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003825 else if (Res == -1) // irrecoverable error
3826 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003827 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3828 S = Parser.getTok().getLoc();
3829 Parser.Lex();
3830 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3831 return false;
3832 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003833
3834 // Fall though for the Identifier case that is not a register or a
3835 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003836 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003837 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003838 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003839 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003840 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003841 // This was not a register so parse other operands that start with an
3842 // identifier (like labels) as expressions and create them as immediates.
3843 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003844 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003845 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003846 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003847 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003848 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3849 return false;
3850 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003851 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003852 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003853 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003854 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003855 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003856 // #42 -> immediate.
3857 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003858 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003859 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003860 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003861 const MCExpr *ImmVal;
3862 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003863 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003865 if (CE) {
3866 int32_t Val = CE->getValue();
3867 if (isNegative && Val == 0)
3868 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003869 }
Sean Callanan76264762010-04-02 22:27:05 +00003870 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003871 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3872 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003873 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003874 case AsmToken::Colon: {
3875 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003876 // FIXME: Check it's an expression prefix,
3877 // e.g. (FOO - :lower16:BAR) isn't legal.
3878 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003879 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003880 return true;
3881
Evan Cheng75972122011-01-13 07:58:56 +00003882 const MCExpr *SubExprVal;
3883 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003884 return true;
3885
Evan Cheng75972122011-01-13 07:58:56 +00003886 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3887 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003888 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003889 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003890 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003891 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003892 }
3893}
3894
Jim Grosbach1355cf12011-07-26 17:10:22 +00003895// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003896// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003897bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003898 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003899
3900 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003901 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003902 Parser.Lex(); // Eat ':'
3903
3904 if (getLexer().isNot(AsmToken::Identifier)) {
3905 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3906 return true;
3907 }
3908
3909 StringRef IDVal = Parser.getTok().getIdentifier();
3910 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003911 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003912 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003913 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003914 } else {
3915 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3916 return true;
3917 }
3918 Parser.Lex();
3919
3920 if (getLexer().isNot(AsmToken::Colon)) {
3921 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
3922 return true;
3923 }
3924 Parser.Lex(); // Eat the last ':'
3925 return false;
3926}
3927
Daniel Dunbar352e1482011-01-11 15:59:50 +00003928/// \brief Given a mnemonic, split out possible predication code and carry
3929/// setting letters to form a canonical mnemonic and flags.
3930//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003931// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00003932// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003933StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00003934 unsigned &PredicationCode,
3935 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00003936 unsigned &ProcessorIMod,
3937 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003938 PredicationCode = ARMCC::AL;
3939 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003940 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00003941
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00003942 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00003943 //
3944 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00003945 if ((Mnemonic == "movs" && isThumb()) ||
3946 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
3947 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
3948 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
3949 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
3950 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
3951 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
3952 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00003953 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00003954
Jim Grosbach3f00e312011-07-11 17:09:57 +00003955 // First, split out any predication code. Ignore mnemonics we know aren't
3956 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00003957 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00003958 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00003959 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00003960 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00003961 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
3962 .Case("eq", ARMCC::EQ)
3963 .Case("ne", ARMCC::NE)
3964 .Case("hs", ARMCC::HS)
3965 .Case("cs", ARMCC::HS)
3966 .Case("lo", ARMCC::LO)
3967 .Case("cc", ARMCC::LO)
3968 .Case("mi", ARMCC::MI)
3969 .Case("pl", ARMCC::PL)
3970 .Case("vs", ARMCC::VS)
3971 .Case("vc", ARMCC::VC)
3972 .Case("hi", ARMCC::HI)
3973 .Case("ls", ARMCC::LS)
3974 .Case("ge", ARMCC::GE)
3975 .Case("lt", ARMCC::LT)
3976 .Case("gt", ARMCC::GT)
3977 .Case("le", ARMCC::LE)
3978 .Case("al", ARMCC::AL)
3979 .Default(~0U);
3980 if (CC != ~0U) {
3981 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
3982 PredicationCode = CC;
3983 }
Bill Wendling52925b62010-10-29 23:50:21 +00003984 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00003985
Daniel Dunbar352e1482011-01-11 15:59:50 +00003986 // Next, determine if we have a carry setting bit. We explicitly ignore all
3987 // the instructions we know end in 's'.
3988 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00003989 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00003990 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
3991 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
3992 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00003993 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
3994 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00003995 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
3996 CarrySetting = true;
3997 }
3998
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003999 // The "cps" instruction can have a interrupt mode operand which is glued into
4000 // the mnemonic. Check if this is the case, split it and parse the imod op
4001 if (Mnemonic.startswith("cps")) {
4002 // Split out any imod code.
4003 unsigned IMod =
4004 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4005 .Case("ie", ARM_PROC::IE)
4006 .Case("id", ARM_PROC::ID)
4007 .Default(~0U);
4008 if (IMod != ~0U) {
4009 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4010 ProcessorIMod = IMod;
4011 }
4012 }
4013
Jim Grosbach89df9962011-08-26 21:43:41 +00004014 // The "it" instruction has the condition mask on the end of the mnemonic.
4015 if (Mnemonic.startswith("it")) {
4016 ITMask = Mnemonic.slice(2, Mnemonic.size());
4017 Mnemonic = Mnemonic.slice(0, 2);
4018 }
4019
Daniel Dunbar352e1482011-01-11 15:59:50 +00004020 return Mnemonic;
4021}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004022
4023/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4024/// inclusion of carry set or predication code operands.
4025//
4026// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004027void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004028getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004029 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004030 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4031 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004032 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004033 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004034 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004035 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004036 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004037 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004038 Mnemonic == "mla" || Mnemonic == "smlal" ||
4039 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004040 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004041 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004042 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004043
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004044 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4045 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4046 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4047 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004048 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4049 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004050 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004051 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4052 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4053 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004054 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4055 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004056 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004057 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004058 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004059 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004060
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004061 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004062 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004063 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004064 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004065 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004066}
4067
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004068bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4069 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004070 // FIXME: This is all horribly hacky. We really need a better way to deal
4071 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004072
4073 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4074 // another does not. Specifically, the MOVW instruction does not. So we
4075 // special case it here and remove the defaulted (non-setting) cc_out
4076 // operand if that's the instruction we're trying to match.
4077 //
4078 // We do this as post-processing of the explicit operands rather than just
4079 // conditionally adding the cc_out in the first place because we need
4080 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004081 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004082 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4083 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4084 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4085 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004086
4087 // Register-register 'add' for thumb does not have a cc_out operand
4088 // when there are only two register operands.
4089 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4090 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4091 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4092 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4093 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004094 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004095 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4096 // have to check the immediate range here since Thumb2 has a variant
4097 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004098 if (((isThumb() && Mnemonic == "add") ||
4099 (isThumbTwo() && Mnemonic == "sub")) &&
4100 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004101 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4102 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4103 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004104 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4105 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4106 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004107 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004108 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4109 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004110 // selecting via the generic "add" mnemonic, so to know that we
4111 // should remove the cc_out operand, we have to explicitly check that
4112 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004113 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4114 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004115 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4116 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4117 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4118 // Nest conditions rather than one big 'if' statement for readability.
4119 //
4120 // If either register is a high reg, it's either one of the SP
4121 // variants (handled above) or a 32-bit encoding, so we just
4122 // check against T3.
4123 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4124 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4125 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4126 return false;
4127 // If both registers are low, we're in an IT block, and the immediate is
4128 // in range, we should use encoding T1 instead, which has a cc_out.
4129 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004130 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004131 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4132 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4133 return false;
4134
4135 // Otherwise, we use encoding T4, which does not have a cc_out
4136 // operand.
4137 return true;
4138 }
4139
Jim Grosbach64944f42011-09-14 21:00:40 +00004140 // The thumb2 multiply instruction doesn't have a CCOut register, so
4141 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4142 // use the 16-bit encoding or not.
4143 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4144 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4145 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4146 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4147 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4148 // If the registers aren't low regs, the destination reg isn't the
4149 // same as one of the source regs, or the cc_out operand is zero
4150 // outside of an IT block, we have to use the 32-bit encoding, so
4151 // remove the cc_out operand.
4152 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4153 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004154 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004155 !inITBlock() ||
4156 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4157 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4158 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4159 static_cast<ARMOperand*>(Operands[4])->getReg())))
4160 return true;
4161
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004162 // Also check the 'mul' syntax variant that doesn't specify an explicit
4163 // destination register.
4164 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4165 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4166 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4167 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4168 // If the registers aren't low regs or the cc_out operand is zero
4169 // outside of an IT block, we have to use the 32-bit encoding, so
4170 // remove the cc_out operand.
4171 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4172 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4173 !inITBlock()))
4174 return true;
4175
Jim Grosbach64944f42011-09-14 21:00:40 +00004176
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004177
Jim Grosbachf69c8042011-08-24 21:42:27 +00004178 // Register-register 'add/sub' for thumb does not have a cc_out operand
4179 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4180 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4181 // right, this will result in better diagnostics (which operand is off)
4182 // anyway.
4183 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4184 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004185 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4186 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4187 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4188 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004189
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004190 return false;
4191}
4192
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004193static bool isDataTypeToken(StringRef Tok) {
4194 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4195 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4196 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4197 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4198 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4199 Tok == ".f" || Tok == ".d";
4200}
4201
4202// FIXME: This bit should probably be handled via an explicit match class
4203// in the .td files that matches the suffix instead of having it be
4204// a literal string token the way it is now.
4205static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4206 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4207}
4208
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004209/// Parse an arm instruction mnemonic followed by its operands.
4210bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4211 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4212 // Create the leading tokens for the mnemonic, split by '.' characters.
4213 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004214 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004215
Daniel Dunbar352e1482011-01-11 15:59:50 +00004216 // Split out the predication code and carry setting flag from the mnemonic.
4217 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004218 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004219 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004220 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004221 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004222 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004223
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004224 // In Thumb1, only the branch (B) instruction can be predicated.
4225 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4226 Parser.EatToEndOfStatement();
4227 return Error(NameLoc, "conditional execution not supported in Thumb1");
4228 }
4229
Jim Grosbachffa32252011-07-19 19:13:28 +00004230 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4231
Jim Grosbach89df9962011-08-26 21:43:41 +00004232 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4233 // is the mask as it will be for the IT encoding if the conditional
4234 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4235 // where the conditional bit0 is zero, the instruction post-processing
4236 // will adjust the mask accordingly.
4237 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004238 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4239 if (ITMask.size() > 3) {
4240 Parser.EatToEndOfStatement();
4241 return Error(Loc, "too many conditions on IT instruction");
4242 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004243 unsigned Mask = 8;
4244 for (unsigned i = ITMask.size(); i != 0; --i) {
4245 char pos = ITMask[i - 1];
4246 if (pos != 't' && pos != 'e') {
4247 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004248 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004249 }
4250 Mask >>= 1;
4251 if (ITMask[i - 1] == 't')
4252 Mask |= 8;
4253 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004254 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004255 }
4256
Jim Grosbachffa32252011-07-19 19:13:28 +00004257 // FIXME: This is all a pretty gross hack. We should automatically handle
4258 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004259
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004260 // Next, add the CCOut and ConditionCode operands, if needed.
4261 //
4262 // For mnemonics which can ever incorporate a carry setting bit or predication
4263 // code, our matching model involves us always generating CCOut and
4264 // ConditionCode operands to match the mnemonic "as written" and then we let
4265 // the matcher deal with finding the right instruction or generating an
4266 // appropriate error.
4267 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004268 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004269
Jim Grosbach33c16a22011-07-14 22:04:21 +00004270 // If we had a carry-set on an instruction that can't do that, issue an
4271 // error.
4272 if (!CanAcceptCarrySet && CarrySetting) {
4273 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004274 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004275 "' can not set flags, but 's' suffix specified");
4276 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004277 // If we had a predication code on an instruction that can't do that, issue an
4278 // error.
4279 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4280 Parser.EatToEndOfStatement();
4281 return Error(NameLoc, "instruction '" + Mnemonic +
4282 "' is not predicable, but condition code specified");
4283 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004284
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004285 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004286 if (CanAcceptCarrySet) {
4287 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004288 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004289 Loc));
4290 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004291
4292 // Add the predication code operand, if necessary.
4293 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004294 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4295 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004296 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004297 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004298 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004299
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004300 // Add the processor imod operand, if necessary.
4301 if (ProcessorIMod) {
4302 Operands.push_back(ARMOperand::CreateImm(
4303 MCConstantExpr::Create(ProcessorIMod, getContext()),
4304 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004305 }
4306
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004307 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004308 while (Next != StringRef::npos) {
4309 Start = Next;
4310 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004311 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004312
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004313 // Some NEON instructions have an optional datatype suffix that is
4314 // completely ignored. Check for that.
4315 if (isDataTypeToken(ExtraToken) &&
4316 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4317 continue;
4318
Jim Grosbach81d2e392011-09-07 16:06:04 +00004319 if (ExtraToken != ".n") {
4320 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4321 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4322 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004323 }
4324
4325 // Read the remaining operands.
4326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004327 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004328 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004329 Parser.EatToEndOfStatement();
4330 return true;
4331 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004332
4333 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004334 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004335
4336 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004337 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004338 Parser.EatToEndOfStatement();
4339 return true;
4340 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004341 }
4342 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004343
Chris Lattnercbf8a982010-09-11 16:18:25 +00004344 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004345 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004346 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004347 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004348 }
Bill Wendling146018f2010-11-06 21:42:12 +00004349
Chris Lattner34e53142010-09-08 05:10:46 +00004350 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004351
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004352 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4353 // do and don't have a cc_out optional-def operand. With some spot-checks
4354 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004355 // parse and adjust accordingly before actually matching. We shouldn't ever
4356 // try to remove a cc_out operand that was explicitly set on the the
4357 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4358 // table driven matcher doesn't fit well with the ARM instruction set.
4359 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004360 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4361 Operands.erase(Operands.begin() + 1);
4362 delete Op;
4363 }
4364
Jim Grosbachcf121c32011-07-28 21:57:55 +00004365 // ARM mode 'blx' need special handling, as the register operand version
4366 // is predicable, but the label operand version is not. So, we can't rely
4367 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004368 // a k_CondCode operand in the list. If we're trying to match the label
4369 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004370 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4371 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4372 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4373 Operands.erase(Operands.begin() + 1);
4374 delete Op;
4375 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004376
4377 // The vector-compare-to-zero instructions have a literal token "#0" at
4378 // the end that comes to here as an immediate operand. Convert it to a
4379 // token to play nicely with the matcher.
4380 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4381 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4382 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4383 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4384 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4385 if (CE && CE->getValue() == 0) {
4386 Operands.erase(Operands.begin() + 5);
4387 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4388 delete Op;
4389 }
4390 }
Jim Grosbach68259142011-10-03 22:30:24 +00004391 // VCMP{E} does the same thing, but with a different operand count.
4392 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4393 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4394 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4395 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4396 if (CE && CE->getValue() == 0) {
4397 Operands.erase(Operands.begin() + 4);
4398 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4399 delete Op;
4400 }
4401 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004402 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4403 // end. Convert it to a token here.
4404 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4405 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4406 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4407 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4408 if (CE && CE->getValue() == 0) {
4409 Operands.erase(Operands.begin() + 5);
4410 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4411 delete Op;
4412 }
4413 }
4414
Chris Lattner98986712010-01-14 22:21:20 +00004415 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004416}
4417
Jim Grosbach189610f2011-07-26 18:25:39 +00004418// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004419
4420// return 'true' if register list contains non-low GPR registers,
4421// 'false' otherwise. If Reg is in the register list or is HiReg, set
4422// 'containsReg' to true.
4423static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4424 unsigned HiReg, bool &containsReg) {
4425 containsReg = false;
4426 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4427 unsigned OpReg = Inst.getOperand(i).getReg();
4428 if (OpReg == Reg)
4429 containsReg = true;
4430 // Anything other than a low register isn't legal here.
4431 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4432 return true;
4433 }
4434 return false;
4435}
4436
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004437// Check if the specified regisgter is in the register list of the inst,
4438// starting at the indicated operand number.
4439static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4440 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4441 unsigned OpReg = Inst.getOperand(i).getReg();
4442 if (OpReg == Reg)
4443 return true;
4444 }
4445 return false;
4446}
4447
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004448// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4449// the ARMInsts array) instead. Getting that here requires awkward
4450// API changes, though. Better way?
4451namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004452extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004453}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004454static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004455 return ARMInsts[Opcode];
4456}
4457
Jim Grosbach189610f2011-07-26 18:25:39 +00004458// FIXME: We would really like to be able to tablegen'erate this.
4459bool ARMAsmParser::
4460validateInstruction(MCInst &Inst,
4461 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004462 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004463 SMLoc Loc = Operands[0]->getStartLoc();
4464 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004465 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4466 // being allowed in IT blocks, but not being predicable. It just always
4467 // executes.
4468 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004469 unsigned bit = 1;
4470 if (ITState.FirstCond)
4471 ITState.FirstCond = false;
4472 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004473 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004474 // The instruction must be predicable.
4475 if (!MCID.isPredicable())
4476 return Error(Loc, "instructions in IT block must be predicable");
4477 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4478 unsigned ITCond = bit ? ITState.Cond :
4479 ARMCC::getOppositeCondition(ITState.Cond);
4480 if (Cond != ITCond) {
4481 // Find the condition code Operand to get its SMLoc information.
4482 SMLoc CondLoc;
4483 for (unsigned i = 1; i < Operands.size(); ++i)
4484 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4485 CondLoc = Operands[i]->getStartLoc();
4486 return Error(CondLoc, "incorrect condition in IT block; got '" +
4487 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4488 "', but expected '" +
4489 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4490 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004491 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004492 } else if (isThumbTwo() && MCID.isPredicable() &&
4493 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004494 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4495 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004496 return Error(Loc, "predicated instructions must be in IT block");
4497
Jim Grosbach189610f2011-07-26 18:25:39 +00004498 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004499 case ARM::LDRD:
4500 case ARM::LDRD_PRE:
4501 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004502 case ARM::LDREXD: {
4503 // Rt2 must be Rt + 1.
4504 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4505 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4506 if (Rt2 != Rt + 1)
4507 return Error(Operands[3]->getStartLoc(),
4508 "destination operands must be sequential");
4509 return false;
4510 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004511 case ARM::STRD: {
4512 // Rt2 must be Rt + 1.
4513 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4514 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4515 if (Rt2 != Rt + 1)
4516 return Error(Operands[3]->getStartLoc(),
4517 "source operands must be sequential");
4518 return false;
4519 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004520 case ARM::STRD_PRE:
4521 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004522 case ARM::STREXD: {
4523 // Rt2 must be Rt + 1.
4524 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4525 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4526 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004527 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004528 "source operands must be sequential");
4529 return false;
4530 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004531 case ARM::SBFX:
4532 case ARM::UBFX: {
4533 // width must be in range [1, 32-lsb]
4534 unsigned lsb = Inst.getOperand(2).getImm();
4535 unsigned widthm1 = Inst.getOperand(3).getImm();
4536 if (widthm1 >= 32 - lsb)
4537 return Error(Operands[5]->getStartLoc(),
4538 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004539 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004540 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004541 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004542 // If we're parsing Thumb2, the .w variant is available and handles
4543 // most cases that are normally illegal for a Thumb1 LDM
4544 // instruction. We'll make the transformation in processInstruction()
4545 // if necessary.
4546 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004547 // Thumb LDM instructions are writeback iff the base register is not
4548 // in the register list.
4549 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004550 bool hasWritebackToken =
4551 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4552 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004553 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004554 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004555 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4556 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004557 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004558 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004559 return Error(Operands[2]->getStartLoc(),
4560 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004561 // If we should not have writeback, there must not be a '!'. This is
4562 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004563 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004564 return Error(Operands[3]->getStartLoc(),
4565 "writeback operator '!' not allowed when base register "
4566 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004567
4568 break;
4569 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004570 case ARM::t2LDMIA_UPD: {
4571 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4572 return Error(Operands[4]->getStartLoc(),
4573 "writeback operator '!' not allowed when base register "
4574 "in register list");
4575 break;
4576 }
Jim Grosbach54026372011-11-10 23:17:11 +00004577 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4578 // so only issue a diagnostic for thumb1. The instructions will be
4579 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004580 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004581 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004582 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4583 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004584 return Error(Operands[2]->getStartLoc(),
4585 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004586 break;
4587 }
4588 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004589 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004590 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4591 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004592 return Error(Operands[2]->getStartLoc(),
4593 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004594 break;
4595 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004596 case ARM::tSTMIA_UPD: {
4597 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004598 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004599 return Error(Operands[4]->getStartLoc(),
4600 "registers must be in range r0-r7");
4601 break;
4602 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004603 }
4604
4605 return false;
4606}
4607
Jim Grosbach83ec8772011-11-10 23:42:14 +00004608bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004609processInstruction(MCInst &Inst,
4610 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4611 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004612 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00004613 case ARM::ASRr:
4614 case ARM::LSRr:
4615 case ARM::LSLr:
4616 case ARM::RORr: {
4617 ARM_AM::ShiftOpc ShiftTy;
4618 switch(Inst.getOpcode()) {
4619 default: llvm_unreachable("unexpected opcode!");
4620 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4621 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4622 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4623 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4624 }
4625 // A shift by zero is a plain MOVr, not a MOVsi.
4626 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4627 MCInst TmpInst;
4628 TmpInst.setOpcode(ARM::MOVsr);
4629 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4630 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4631 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4632 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4633 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4634 TmpInst.addOperand(Inst.getOperand(4));
4635 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4636 Inst = TmpInst;
4637 return true;
4638 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00004639 case ARM::ASRi:
4640 case ARM::LSRi:
4641 case ARM::LSLi:
4642 case ARM::RORi: {
4643 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004644 switch(Inst.getOpcode()) {
4645 default: llvm_unreachable("unexpected opcode!");
4646 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4647 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4648 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4649 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4650 }
4651 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00004652 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00004653 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4654 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004655 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004656 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004657 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4658 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004659 if (Opc == ARM::MOVsi)
4660 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004661 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4662 TmpInst.addOperand(Inst.getOperand(4));
4663 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4664 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004665 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004666 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00004667 case ARM::RRXi: {
4668 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4669 MCInst TmpInst;
4670 TmpInst.setOpcode(ARM::MOVsi);
4671 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4672 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4673 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4674 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4675 TmpInst.addOperand(Inst.getOperand(3));
4676 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4677 Inst = TmpInst;
4678 return true;
4679 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004680 case ARM::t2LDMIA_UPD: {
4681 // If this is a load of a single register, then we should use
4682 // a post-indexed LDR instruction instead, per the ARM ARM.
4683 if (Inst.getNumOperands() != 5)
4684 return false;
4685 MCInst TmpInst;
4686 TmpInst.setOpcode(ARM::t2LDR_POST);
4687 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4688 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4689 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4690 TmpInst.addOperand(MCOperand::CreateImm(4));
4691 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4692 TmpInst.addOperand(Inst.getOperand(3));
4693 Inst = TmpInst;
4694 return true;
4695 }
4696 case ARM::t2STMDB_UPD: {
4697 // If this is a store of a single register, then we should use
4698 // a pre-indexed STR instruction instead, per the ARM ARM.
4699 if (Inst.getNumOperands() != 5)
4700 return false;
4701 MCInst TmpInst;
4702 TmpInst.setOpcode(ARM::t2STR_PRE);
4703 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4704 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4705 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4706 TmpInst.addOperand(MCOperand::CreateImm(-4));
4707 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4708 TmpInst.addOperand(Inst.getOperand(3));
4709 Inst = TmpInst;
4710 return true;
4711 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004712 case ARM::LDMIA_UPD:
4713 // If this is a load of a single register via a 'pop', then we should use
4714 // a post-indexed LDR instruction instead, per the ARM ARM.
4715 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4716 Inst.getNumOperands() == 5) {
4717 MCInst TmpInst;
4718 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4719 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4720 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4721 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4722 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4723 TmpInst.addOperand(MCOperand::CreateImm(4));
4724 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4725 TmpInst.addOperand(Inst.getOperand(3));
4726 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004727 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004728 }
4729 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004730 case ARM::STMDB_UPD:
4731 // If this is a store of a single register via a 'push', then we should use
4732 // a pre-indexed STR instruction instead, per the ARM ARM.
4733 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4734 Inst.getNumOperands() == 5) {
4735 MCInst TmpInst;
4736 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4737 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4738 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4739 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4740 TmpInst.addOperand(MCOperand::CreateImm(-4));
4741 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4742 TmpInst.addOperand(Inst.getOperand(3));
4743 Inst = TmpInst;
4744 }
4745 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004746 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004747 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4748 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4749 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4750 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004751 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004752 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004753 return true;
4754 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004755 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004756 case ARM::tSUBi8:
4757 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4758 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4759 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4760 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004761 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004762 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004763 return true;
4764 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004765 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004766 case ARM::tB:
4767 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004768 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004769 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004770 return true;
4771 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004772 break;
4773 case ARM::t2B:
4774 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004775 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004776 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004777 return true;
4778 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004779 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004780 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004781 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004782 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004783 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004784 return true;
4785 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004786 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004787 case ARM::tBcc:
4788 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004789 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004790 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004791 return true;
4792 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004793 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004794 case ARM::tLDMIA: {
4795 // If the register list contains any high registers, or if the writeback
4796 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4797 // instead if we're in Thumb2. Otherwise, this should have generated
4798 // an error in validateInstruction().
4799 unsigned Rn = Inst.getOperand(0).getReg();
4800 bool hasWritebackToken =
4801 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4802 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4803 bool listContainsBase;
4804 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4805 (!listContainsBase && !hasWritebackToken) ||
4806 (listContainsBase && hasWritebackToken)) {
4807 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4808 assert (isThumbTwo());
4809 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4810 // If we're switching to the updating version, we need to insert
4811 // the writeback tied operand.
4812 if (hasWritebackToken)
4813 Inst.insert(Inst.begin(),
4814 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004815 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004816 }
4817 break;
4818 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004819 case ARM::tSTMIA_UPD: {
4820 // If the register list contains any high registers, we need to use
4821 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4822 // should have generated an error in validateInstruction().
4823 unsigned Rn = Inst.getOperand(0).getReg();
4824 bool listContainsBase;
4825 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4826 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4827 assert (isThumbTwo());
4828 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004829 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004830 }
4831 break;
4832 }
Jim Grosbach54026372011-11-10 23:17:11 +00004833 case ARM::tPOP: {
4834 bool listContainsBase;
4835 // If the register list contains any high registers, we need to use
4836 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4837 // should have generated an error in validateInstruction().
4838 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004839 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004840 assert (isThumbTwo());
4841 Inst.setOpcode(ARM::t2LDMIA_UPD);
4842 // Add the base register and writeback operands.
4843 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4844 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004845 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004846 }
4847 case ARM::tPUSH: {
4848 bool listContainsBase;
4849 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004850 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004851 assert (isThumbTwo());
4852 Inst.setOpcode(ARM::t2STMDB_UPD);
4853 // Add the base register and writeback operands.
4854 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4855 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004856 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004857 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004858 case ARM::t2MOVi: {
4859 // If we can use the 16-bit encoding and the user didn't explicitly
4860 // request the 32-bit variant, transform it here.
4861 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4862 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004863 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4864 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4865 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004866 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4867 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4868 // The operands aren't in the same order for tMOVi8...
4869 MCInst TmpInst;
4870 TmpInst.setOpcode(ARM::tMOVi8);
4871 TmpInst.addOperand(Inst.getOperand(0));
4872 TmpInst.addOperand(Inst.getOperand(4));
4873 TmpInst.addOperand(Inst.getOperand(1));
4874 TmpInst.addOperand(Inst.getOperand(2));
4875 TmpInst.addOperand(Inst.getOperand(3));
4876 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004877 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004878 }
4879 break;
4880 }
4881 case ARM::t2MOVr: {
4882 // If we can use the 16-bit encoding and the user didn't explicitly
4883 // request the 32-bit variant, transform it here.
4884 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4885 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4886 Inst.getOperand(2).getImm() == ARMCC::AL &&
4887 Inst.getOperand(4).getReg() == ARM::CPSR &&
4888 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4889 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4890 // The operands aren't the same for tMOV[S]r... (no cc_out)
4891 MCInst TmpInst;
4892 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4893 TmpInst.addOperand(Inst.getOperand(0));
4894 TmpInst.addOperand(Inst.getOperand(1));
4895 TmpInst.addOperand(Inst.getOperand(2));
4896 TmpInst.addOperand(Inst.getOperand(3));
4897 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004898 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004899 }
4900 break;
4901 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004902 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004903 case ARM::t2SXTB:
4904 case ARM::t2UXTH:
4905 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004906 // If we can use the 16-bit encoding and the user didn't explicitly
4907 // request the 32-bit variant, transform it here.
4908 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4909 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4910 Inst.getOperand(2).getImm() == 0 &&
4911 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4912 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004913 unsigned NewOpc;
4914 switch (Inst.getOpcode()) {
4915 default: llvm_unreachable("Illegal opcode!");
4916 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
4917 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
4918 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
4919 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
4920 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004921 // The operands aren't the same for thumb1 (no rotate operand).
4922 MCInst TmpInst;
4923 TmpInst.setOpcode(NewOpc);
4924 TmpInst.addOperand(Inst.getOperand(0));
4925 TmpInst.addOperand(Inst.getOperand(1));
4926 TmpInst.addOperand(Inst.getOperand(3));
4927 TmpInst.addOperand(Inst.getOperand(4));
4928 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004929 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00004930 }
4931 break;
4932 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004933 case ARM::t2IT: {
4934 // The mask bits for all but the first condition are represented as
4935 // the low bit of the condition code value implies 't'. We currently
4936 // always have 1 implies 't', so XOR toggle the bits if the low bit
4937 // of the condition code is zero. The encoding also expects the low
4938 // bit of the condition to be encoded as bit 4 of the mask operand,
4939 // so mask that in if needed
4940 MCOperand &MO = Inst.getOperand(1);
4941 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004942 unsigned OrigMask = Mask;
4943 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00004944 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00004945 assert(Mask && TZ <= 3 && "illegal IT mask value!");
4946 for (unsigned i = 3; i != TZ; --i)
4947 Mask ^= 1 << i;
4948 } else
4949 Mask |= 0x10;
4950 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004951
4952 // Set up the IT block state according to the IT instruction we just
4953 // matched.
4954 assert(!inITBlock() && "nested IT blocks?!");
4955 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
4956 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
4957 ITState.CurPosition = 0;
4958 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00004959 break;
4960 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004961 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00004962 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004963}
4964
Jim Grosbach47a0d522011-08-16 20:45:50 +00004965unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
4966 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
4967 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00004968 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004969 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00004970 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
4971 assert(MCID.hasOptionalDef() &&
4972 "optionally flag setting instruction missing optional def operand");
4973 assert(MCID.NumOperands == Inst.getNumOperands() &&
4974 "operand count mismatch!");
4975 // Find the optional-def operand (cc_out).
4976 unsigned OpNo;
4977 for (OpNo = 0;
4978 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
4979 ++OpNo)
4980 ;
4981 // If we're parsing Thumb1, reject it completely.
4982 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
4983 return Match_MnemonicFail;
4984 // If we're parsing Thumb2, which form is legal depends on whether we're
4985 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004986 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
4987 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00004988 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004989 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
4990 inITBlock())
4991 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00004992 }
Jim Grosbach194bd892011-08-16 22:20:01 +00004993 // Some high-register supporting Thumb1 encodings only allow both registers
4994 // to be from r0-r7 when in Thumb2.
4995 else if (Opc == ARM::tADDhirr && isThumbOne() &&
4996 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4997 isARMLowRegister(Inst.getOperand(2).getReg()))
4998 return Match_RequiresThumb2;
4999 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005000 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005001 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5002 isARMLowRegister(Inst.getOperand(1).getReg()))
5003 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005004 return Match_Success;
5005}
5006
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005007bool ARMAsmParser::
5008MatchAndEmitInstruction(SMLoc IDLoc,
5009 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5010 MCStreamer &Out) {
5011 MCInst Inst;
5012 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005013 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005014 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005015 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005016 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005017 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005018 // Context sensitive operand constraints aren't handled by the matcher,
5019 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005020 if (validateInstruction(Inst, Operands)) {
5021 // Still progress the IT block, otherwise one wrong condition causes
5022 // nasty cascading errors.
5023 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005024 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005025 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005026
Jim Grosbachf8fce712011-08-11 17:35:48 +00005027 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005028 // encoding is selected. Loop on it while changes happen so the
5029 // individual transformations can chain off each other. E.g.,
5030 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5031 while (processInstruction(Inst, Operands))
5032 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005033
Jim Grosbacha1109882011-09-02 23:22:08 +00005034 // Only move forward at the very end so that everything in validate
5035 // and process gets a consistent answer about whether we're in an IT
5036 // block.
5037 forwardITPosition();
5038
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005039 Out.EmitInstruction(Inst);
5040 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005041 case Match_MissingFeature:
5042 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5043 return true;
5044 case Match_InvalidOperand: {
5045 SMLoc ErrorLoc = IDLoc;
5046 if (ErrorInfo != ~0U) {
5047 if (ErrorInfo >= Operands.size())
5048 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005049
Chris Lattnere73d4f82010-10-28 21:41:58 +00005050 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5051 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5052 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005053
Chris Lattnere73d4f82010-10-28 21:41:58 +00005054 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005055 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005056 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005057 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005058 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005059 // The converter function will have already emited a diagnostic.
5060 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005061 case Match_RequiresNotITBlock:
5062 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005063 case Match_RequiresITBlock:
5064 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005065 case Match_RequiresV6:
5066 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5067 case Match_RequiresThumb2:
5068 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005069 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005070
Eric Christopherc223e2b2010-10-29 09:26:59 +00005071 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005072 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005073}
5074
Jim Grosbach1355cf12011-07-26 17:10:22 +00005075/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005076bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5077 StringRef IDVal = DirectiveID.getIdentifier();
5078 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005079 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005080 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005081 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005082 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005083 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005084 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005085 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005086 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005087 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005088 return true;
5089}
5090
Jim Grosbach1355cf12011-07-26 17:10:22 +00005091/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005092/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005093bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005094 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5095 for (;;) {
5096 const MCExpr *Value;
5097 if (getParser().ParseExpression(Value))
5098 return true;
5099
Chris Lattneraaec2052010-01-19 19:46:13 +00005100 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005101
5102 if (getLexer().is(AsmToken::EndOfStatement))
5103 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005104
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005105 // FIXME: Improve diagnostic.
5106 if (getLexer().isNot(AsmToken::Comma))
5107 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005108 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005109 }
5110 }
5111
Sean Callananb9a25b72010-01-19 20:27:46 +00005112 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005113 return false;
5114}
5115
Jim Grosbach1355cf12011-07-26 17:10:22 +00005116/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005117/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005118bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005119 if (getLexer().isNot(AsmToken::EndOfStatement))
5120 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005121 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005122
5123 // TODO: set thumb mode
5124 // TODO: tell the MC streamer the mode
5125 // getParser().getStreamer().Emit???();
5126 return false;
5127}
5128
Jim Grosbach1355cf12011-07-26 17:10:22 +00005129/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005130/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005131bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005132 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5133 bool isMachO = MAI.hasSubsectionsViaSymbols();
5134 StringRef Name;
5135
5136 // Darwin asm has function name after .thumb_func direction
5137 // ELF doesn't
5138 if (isMachO) {
5139 const AsmToken &Tok = Parser.getTok();
5140 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5141 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005142 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005143 Parser.Lex(); // Consume the identifier token.
5144 }
5145
Jim Grosbachd475f862011-11-10 20:48:53 +00005146 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005147 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005148 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005149
Rafael Espindola64695402011-05-16 16:17:21 +00005150 // FIXME: assuming function name will be the line following .thumb_func
5151 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005152 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005153 }
5154
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005155 // Mark symbol as a thumb symbol.
5156 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5157 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005158 return false;
5159}
5160
Jim Grosbach1355cf12011-07-26 17:10:22 +00005161/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005162/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005163bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005164 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005165 if (Tok.isNot(AsmToken::Identifier))
5166 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005167 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005168 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005169 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005170 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005171 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005172 else
5173 return Error(L, "unrecognized syntax mode in .syntax directive");
5174
5175 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005176 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005177 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005178
5179 // TODO tell the MC streamer the mode
5180 // getParser().getStreamer().Emit???();
5181 return false;
5182}
5183
Jim Grosbach1355cf12011-07-26 17:10:22 +00005184/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005185/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005186bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005187 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005188 if (Tok.isNot(AsmToken::Integer))
5189 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005190 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005191 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005192 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005193 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005194 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005195 else
5196 return Error(L, "invalid operand to .code directive");
5197
5198 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005199 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005200 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005201
Evan Cheng32869202011-07-08 22:36:29 +00005202 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005203 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005204 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005205 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005206 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005207 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005208 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005209 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005210 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005211
Kevin Enderby515d5092009-10-15 20:48:48 +00005212 return false;
5213}
5214
Sean Callanan90b70972010-04-07 20:29:34 +00005215extern "C" void LLVMInitializeARMAsmLexer();
5216
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005217/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005218extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005219 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5220 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005221 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005222}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005223
Chris Lattner0692ee62010-09-06 19:11:01 +00005224#define GET_REGISTER_MATCHER
5225#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005226#include "ARMGenAsmMatcher.inc"