blob: a96b37d53ac8a5cbe0eee53f0060148397c87128 [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
Jim Grosbach98b05a52011-11-30 01:09:44 +000042enum VectorLaneTy { NoLanes, AllLanes };
43
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
47
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000048 struct {
49 ARMCC::CondCodes Cond; // Condition for IT block.
50 unsigned Mask:4; // Condition mask for instructions.
51 // Starting at first 1 (from lsb).
52 // '1' condition as indicated in IT.
53 // '0' inverse of condition (else).
54 // Count of instructions in IT block is
55 // 4 - trailingzeroes(mask)
56
57 bool FirstCond; // Explicit flag for when we're parsing the
58 // First instruction in the IT block. It's
59 // implied in the mask, so needs special
60 // handling.
61
62 unsigned CurPosition; // Current position in parsing of IT
63 // block. In range [0,3]. Initialized
64 // according to count of instructions in block.
65 // ~0U if no active IT block.
66 } ITState;
67 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000068 void forwardITPosition() {
69 if (!inITBlock()) return;
70 // Move to the next instruction in the IT block, if there is one. If not,
71 // mark the block as done.
72 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
73 if (++ITState.CurPosition == 5 - TZ)
74 ITState.CurPosition = ~0U; // Done with the IT block after this.
75 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000076
77
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000078 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000079 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
80
81 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
83
Jim Grosbach1355cf12011-07-26 17:10:22 +000084 int tryParseRegister();
85 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000086 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000088 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000089 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
90 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
92 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000093 bool parseDirectiveWord(unsigned Size, SMLoc L);
94 bool parseDirectiveThumb(SMLoc L);
95 bool parseDirectiveThumbFunc(SMLoc L);
96 bool parseDirectiveCode(SMLoc L);
97 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000098
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000100 bool &CarrySetting, unsigned &ProcessorIMod,
101 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000102 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000103 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000104
Evan Chengebdeeab2011-07-08 01:53:10 +0000105 bool isThumb() const {
106 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000107 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000108 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000110 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000111 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000112 bool isThumbTwo() const {
113 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
114 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000115 bool hasV6Ops() const {
116 return STI.getFeatureBits() & ARM::HasV6Ops;
117 }
James Molloyacad68d2011-09-28 14:21:38 +0000118 bool hasV7Ops() const {
119 return STI.getFeatureBits() & ARM::HasV7Ops;
120 }
Evan Cheng32869202011-07-08 22:36:29 +0000121 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000122 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
123 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000124 }
James Molloyacad68d2011-09-28 14:21:38 +0000125 bool isMClass() const {
126 return STI.getFeatureBits() & ARM::FeatureMClass;
127 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000128
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000129 /// @name Auto-generated Match Functions
130 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000131
Chris Lattner0692ee62010-09-06 19:11:01 +0000132#define GET_ASSEMBLER_HEADER
133#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000134
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135 /// }
136
Jim Grosbach89df9962011-08-26 21:43:41 +0000137 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000138 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000139 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000140 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000141 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000142 OperandMatchResultTy parseCoprocOptionOperand(
143 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000150 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
151 StringRef Op, int Low, int High);
152 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
153 return parsePKHImm(O, "lsl", 0, 31);
154 }
155 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
156 return parsePKHImm(O, "asr", 1, 32);
157 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000158 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000159 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000160 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000161 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000162 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000163 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000164 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000165 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach98b05a52011-11-30 01:09:44 +0000166 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000167
168 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000169 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
170 const SmallVectorImpl<MCParsedAsmOperand*> &);
171 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
172 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000173 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
174 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000175 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000177 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000179 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000181 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000183 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000185 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000187 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
189 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
191 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
193 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000195 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000197 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000199 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000201 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000203 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
205 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000207 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
209 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000211
212 bool validateInstruction(MCInst &Inst,
213 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000214 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000215 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000216 bool shouldOmitCCOutOperand(StringRef Mnemonic,
217 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000218
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000219public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000220 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000221 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000222 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000223 Match_RequiresV6,
224 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000225 };
226
Evan Chengffc0e732011-07-09 05:47:46 +0000227 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000228 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000229 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000230
Evan Chengebdeeab2011-07-08 01:53:10 +0000231 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000232 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000233
234 // Not in an ITBlock to start with.
235 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000236 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000237
Jim Grosbach1355cf12011-07-26 17:10:22 +0000238 // Implementation of the MCTargetAsmParser interface:
239 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
240 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000241 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000242 bool ParseDirective(AsmToken DirectiveID);
243
Jim Grosbach47a0d522011-08-16 20:45:50 +0000244 unsigned checkTargetMatchPredicate(MCInst &Inst);
245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 bool MatchAndEmitInstruction(SMLoc IDLoc,
247 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
248 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000249};
Jim Grosbach16c74252010-10-29 14:46:02 +0000250} // end anonymous namespace
251
Chris Lattner3a697562010-10-28 17:20:03 +0000252namespace {
253
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000254/// ARMOperand - Instances of this class represent a parsed ARM machine
255/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000256class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000257 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000258 k_CondCode,
259 k_CCOut,
260 k_ITCondMask,
261 k_CoprocNum,
262 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000263 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000264 k_Immediate,
265 k_FPImmediate,
266 k_MemBarrierOpt,
267 k_Memory,
268 k_PostIndexRegister,
269 k_MSRMask,
270 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000271 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Register,
273 k_RegisterList,
274 k_DPRRegisterList,
275 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000276 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000277 k_VectorListAllLanes,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000278 k_ShiftedRegister,
279 k_ShiftedImmediate,
280 k_ShifterImmediate,
281 k_RotateImmediate,
282 k_BitfieldDescriptor,
283 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000284 } Kind;
285
Sean Callanan76264762010-04-02 22:27:05 +0000286 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000287 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000288
289 union {
290 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000291 ARMCC::CondCodes Val;
292 } CC;
293
294 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000295 unsigned Val;
296 } Cop;
297
298 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000299 unsigned Val;
300 } CoprocOption;
301
302 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000303 unsigned Mask:4;
304 } ITMask;
305
306 struct {
307 ARM_MB::MemBOpt Val;
308 } MBOpt;
309
310 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000311 ARM_PROC::IFlags Val;
312 } IFlags;
313
314 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000315 unsigned Val;
316 } MMask;
317
318 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000319 const char *Data;
320 unsigned Length;
321 } Tok;
322
323 struct {
324 unsigned RegNum;
325 } Reg;
326
Jim Grosbach862019c2011-10-18 23:02:30 +0000327 // A vector register list is a sequential list of 1 to 4 registers.
328 struct {
329 unsigned RegNum;
330 unsigned Count;
331 } VectorList;
332
Bill Wendling8155e5b2010-11-06 22:19:43 +0000333 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000334 unsigned Val;
335 } VectorIndex;
336
337 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000338 const MCExpr *Val;
339 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000340
Jim Grosbach9d390362011-10-03 23:38:36 +0000341 struct {
342 unsigned Val; // encoded 8-bit representation
343 } FPImm;
344
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000345 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000346 struct {
347 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000348 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
349 // was specified.
350 const MCConstantExpr *OffsetImm; // Offset immediate value
351 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
352 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000353 unsigned ShiftImm; // shift for OffsetReg.
354 unsigned Alignment; // 0 = no alignment specified
355 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000356 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000357 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000358
359 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000360 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000361 bool isAdd;
362 ARM_AM::ShiftOpc ShiftTy;
363 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000364 } PostIdxReg;
365
366 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000367 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000368 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000369 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000370 struct {
371 ARM_AM::ShiftOpc ShiftTy;
372 unsigned SrcReg;
373 unsigned ShiftReg;
374 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000375 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000376 struct {
377 ARM_AM::ShiftOpc ShiftTy;
378 unsigned SrcReg;
379 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000380 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000381 struct {
382 unsigned Imm;
383 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000384 struct {
385 unsigned LSB;
386 unsigned Width;
387 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000388 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000389
Bill Wendling146018f2010-11-06 21:42:12 +0000390 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
391public:
Sean Callanan76264762010-04-02 22:27:05 +0000392 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
393 Kind = o.Kind;
394 StartLoc = o.StartLoc;
395 EndLoc = o.EndLoc;
396 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000397 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000398 CC = o.CC;
399 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000400 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000401 ITMask = o.ITMask;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000404 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_CCOut:
407 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000408 Reg = o.Reg;
409 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000410 case k_RegisterList:
411 case k_DPRRegisterList:
412 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000413 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000414 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000415 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000416 case k_VectorListAllLanes:
Jim Grosbach862019c2011-10-18 23:02:30 +0000417 VectorList = o.VectorList;
418 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000419 case k_CoprocNum:
420 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000421 Cop = o.Cop;
422 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000423 case k_CoprocOption:
424 CoprocOption = o.CoprocOption;
425 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000426 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000427 Imm = o.Imm;
428 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000429 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000430 FPImm = o.FPImm;
431 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000432 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000433 MBOpt = o.MBOpt;
434 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000435 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000436 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000439 PostIdxReg = o.PostIdxReg;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000442 MMask = o.MMask;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000445 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000448 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000451 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000454 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000457 RotImm = o.RotImm;
458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000460 Bitfield = o.Bitfield;
461 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000462 case k_VectorIndex:
463 VectorIndex = o.VectorIndex;
464 break;
Sean Callanan76264762010-04-02 22:27:05 +0000465 }
466 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000467
Sean Callanan76264762010-04-02 22:27:05 +0000468 /// getStartLoc - Get the location of the first token of this operand.
469 SMLoc getStartLoc() const { return StartLoc; }
470 /// getEndLoc - Get the location of the last token of this operand.
471 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000472
Daniel Dunbar8462b302010-08-11 06:36:53 +0000473 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000474 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000475 return CC.Val;
476 }
477
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000478 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000479 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000480 return Cop.Val;
481 }
482
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000483 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000484 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000485 return StringRef(Tok.Data, Tok.Length);
486 }
487
488 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000489 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000490 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000491 }
492
Bill Wendling5fa22a12010-11-09 23:28:44 +0000493 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000494 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
495 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000496 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000497 }
498
Kevin Enderbycfe07242009-10-13 22:19:02 +0000499 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000500 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000501 return Imm.Val;
502 }
503
Jim Grosbach9d390362011-10-03 23:38:36 +0000504 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000505 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000506 return FPImm.Val;
507 }
508
Jim Grosbach460a9052011-10-07 23:56:00 +0000509 unsigned getVectorIndex() const {
510 assert(Kind == k_VectorIndex && "Invalid access!");
511 return VectorIndex.Val;
512 }
513
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000514 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000515 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000516 return MBOpt.Val;
517 }
518
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000519 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000520 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000521 return IFlags.Val;
522 }
523
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000524 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000525 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000526 return MMask.Val;
527 }
528
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 bool isCoprocNum() const { return Kind == k_CoprocNum; }
530 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000531 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 bool isCondCode() const { return Kind == k_CondCode; }
533 bool isCCOut() const { return Kind == k_CCOut; }
534 bool isITMask() const { return Kind == k_ITCondMask; }
535 bool isITCondCode() const { return Kind == k_CondCode; }
536 bool isImm() const { return Kind == k_Immediate; }
537 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000538 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000539 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000540 return false;
541 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
542 if (!CE) return false;
543 int64_t Value = CE->getValue();
544 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
545 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000546 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000547 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000548 return false;
549 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
550 if (!CE) return false;
551 int64_t Value = CE->getValue();
552 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
553 }
554 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000555 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000556 return false;
557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
558 if (!CE) return false;
559 int64_t Value = CE->getValue();
560 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
561 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000562 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000563 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000564 return false;
565 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
566 if (!CE) return false;
567 int64_t Value = CE->getValue();
568 return Value >= 0 && Value < 256;
569 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000570 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000571 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000572 return false;
573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
574 if (!CE) return false;
575 int64_t Value = CE->getValue();
576 return Value >= 0 && Value < 8;
577 }
578 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000579 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000580 return false;
581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return Value >= 0 && Value < 16;
585 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000586 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000587 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000588 return false;
589 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
590 if (!CE) return false;
591 int64_t Value = CE->getValue();
592 return Value >= 0 && Value < 32;
593 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000594 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000595 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000596 return false;
597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
598 if (!CE) return false;
599 int64_t Value = CE->getValue();
600 return Value > 0 && Value < 17;
601 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000602 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000603 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000604 return false;
605 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
606 if (!CE) return false;
607 int64_t Value = CE->getValue();
608 return Value > 0 && Value < 33;
609 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000610 bool isImm0_32() const {
611 if (Kind != k_Immediate)
612 return false;
613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
614 if (!CE) return false;
615 int64_t Value = CE->getValue();
616 return Value >= 0 && Value < 33;
617 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000618 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000619 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000620 return false;
621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
622 if (!CE) return false;
623 int64_t Value = CE->getValue();
624 return Value >= 0 && Value < 65536;
625 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000626 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000627 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000628 return false;
629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630 // If it's not a constant expression, it'll generate a fixup and be
631 // handled later.
632 if (!CE) return true;
633 int64_t Value = CE->getValue();
634 return Value >= 0 && Value < 65536;
635 }
Jim Grosbached838482011-07-26 16:24:27 +0000636 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000637 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000638 return false;
639 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
640 if (!CE) return false;
641 int64_t Value = CE->getValue();
642 return Value >= 0 && Value <= 0xffffff;
643 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000644 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000645 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000646 return false;
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
648 if (!CE) return false;
649 int64_t Value = CE->getValue();
650 return Value > 0 && Value < 33;
651 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000652 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000653 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000654 return false;
655 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
656 if (!CE) return false;
657 int64_t Value = CE->getValue();
658 return Value >= 0 && Value < 32;
659 }
660 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000661 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000662 return false;
663 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
664 if (!CE) return false;
665 int64_t Value = CE->getValue();
666 return Value > 0 && Value <= 32;
667 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000668 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000669 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000670 return false;
671 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672 if (!CE) return false;
673 int64_t Value = CE->getValue();
674 return ARM_AM::getSOImmVal(Value) != -1;
675 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000676 bool isARMSOImmNot() const {
677 if (Kind != k_Immediate)
678 return false;
679 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
680 if (!CE) return false;
681 int64_t Value = CE->getValue();
682 return ARM_AM::getSOImmVal(~Value) != -1;
683 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000684 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000685 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000686 return false;
687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return ARM_AM::getT2SOImmVal(Value) != -1;
691 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000692 bool isT2SOImmNot() const {
693 if (Kind != k_Immediate)
694 return false;
695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
696 if (!CE) return false;
697 int64_t Value = CE->getValue();
698 return ARM_AM::getT2SOImmVal(~Value) != -1;
699 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000700 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000701 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000702 return false;
703 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
704 if (!CE) return false;
705 int64_t Value = CE->getValue();
706 return Value == 1 || Value == 0;
707 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000708 bool isReg() const { return Kind == k_Register; }
709 bool isRegList() const { return Kind == k_RegisterList; }
710 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
711 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
712 bool isToken() const { return Kind == k_Token; }
713 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
714 bool isMemory() const { return Kind == k_Memory; }
715 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
716 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
717 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
718 bool isRotImm() const { return Kind == k_RotateImmediate; }
719 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
720 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000721 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000722 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000723 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000724 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000725 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000726 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000727 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000728 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
729 (alignOK || Memory.Alignment == 0);
730 }
731 bool isAlignedMemory() const {
732 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000733 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000734 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000735 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000736 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000737 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000738 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000739 if (!Memory.OffsetImm) return true;
740 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000741 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000742 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000743 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000744 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000745 return false;
746 // Immediate offset in range [-4095, 4095].
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Val = CE->getValue();
750 return Val > -4096 && Val < 4096;
751 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000752 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000753 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000754 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000755 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000756 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000757 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000758 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000759 if (!Memory.OffsetImm) return true;
760 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000761 return Val > -256 && Val < 256;
762 }
763 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000764 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000765 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000766 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000767 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
768 // Immediate offset in range [-255, 255].
769 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
770 if (!CE) return false;
771 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000772 // Special case, #-0 is INT32_MIN.
773 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000774 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000775 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000776 // If we have an immediate that's not a constant, treat it as a label
777 // reference needing a fixup. If it is a constant, it's something else
778 // and we reject it.
779 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
780 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000781 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000782 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000783 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000784 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000785 if (!Memory.OffsetImm) return true;
786 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000787 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000788 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000789 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000790 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000791 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000792 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000793 return false;
794 return true;
795 }
796 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000797 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000798 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
799 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000800 return false;
801 return true;
802 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000803 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000804 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000805 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000806 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000807 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000808 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000809 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
810 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000811 return false;
812 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000813 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000814 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000815 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000816 return false;
817 return true;
818 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000819 bool isMemThumbRR() const {
820 // Thumb reg+reg addressing is simple. Just two registers, a base and
821 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000822 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000823 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000824 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000825 return isARMLowRegister(Memory.BaseRegNum) &&
826 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000827 }
828 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000829 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000830 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000831 return false;
832 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000833 if (!Memory.OffsetImm) return true;
834 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000835 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
836 }
Jim Grosbach38466302011-08-19 18:55:51 +0000837 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000838 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000839 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000840 return false;
841 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000842 if (!Memory.OffsetImm) return true;
843 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000844 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
845 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000846 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000848 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000849 return false;
850 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000853 return Val >= 0 && Val <= 31;
854 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000855 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 if (!isMemory() || Memory.OffsetRegNum != 0 ||
857 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000858 return false;
859 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000860 if (!Memory.OffsetImm) return true;
861 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000862 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000863 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000864 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000865 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000866 return false;
867 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000868 if (!Memory.OffsetImm) return true;
869 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000870 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
871 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000872 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000874 return false;
875 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000876 if (!Memory.OffsetImm) return true;
877 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000878 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
879 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000880 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000881 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000882 return false;
883 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000884 if (!Memory.OffsetImm) return true;
885 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000886 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000887 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000888 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000889 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000890 return false;
891 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (!Memory.OffsetImm) return true;
893 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000894 return Val >= 0 && Val < 256;
895 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000896 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000897 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000898 return false;
899 // Immediate offset in range [-255, -1].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000900 if (!Memory.OffsetImm) return true;
901 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000902 return Val > -256 && Val < 0;
903 }
904 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000905 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000906 return false;
907 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000908 if (!Memory.OffsetImm) return true;
909 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000910 return (Val >= 0 && Val < 4096);
911 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +0000917 return true;
918
Jim Grosbach57dcb852011-10-11 17:29:55 +0000919 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000920 return false;
921 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000924 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000925 }
926 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000927 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000928 return false;
929 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
930 if (!CE) return false;
931 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +0000932 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000933 }
Jim Grosbach2bd01182011-10-11 21:55:36 +0000934 bool isPostIdxImm8s4() const {
935 if (Kind != k_Immediate)
936 return false;
937 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
938 if (!CE) return false;
939 int64_t Val = CE->getValue();
940 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
941 (Val == INT32_MIN);
942 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000943
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000944 bool isMSRMask() const { return Kind == k_MSRMask; }
945 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000946
Jim Grosbach0e387b22011-10-17 22:26:03 +0000947 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +0000948 bool isVecListOneD() const {
949 if (Kind != k_VectorList) return false;
950 return VectorList.Count == 1;
951 }
952
Jim Grosbach280dfad2011-10-21 18:54:25 +0000953 bool isVecListTwoD() const {
954 if (Kind != k_VectorList) return false;
955 return VectorList.Count == 2;
956 }
957
Jim Grosbachcdcfa282011-10-21 20:02:19 +0000958 bool isVecListThreeD() const {
959 if (Kind != k_VectorList) return false;
960 return VectorList.Count == 3;
961 }
962
Jim Grosbachb6310312011-10-21 20:35:01 +0000963 bool isVecListFourD() const {
964 if (Kind != k_VectorList) return false;
965 return VectorList.Count == 4;
966 }
967
Jim Grosbach4661d4c2011-10-21 22:21:10 +0000968 bool isVecListTwoQ() const {
969 if (Kind != k_VectorList) return false;
970 //FIXME: We haven't taught the parser to handle by-two register lists
971 // yet, so don't pretend to know one.
972 return VectorList.Count == 2 && false;
973 }
974
Jim Grosbach98b05a52011-11-30 01:09:44 +0000975 bool isVecListOneDAllLanes() const {
976 if (Kind != k_VectorListAllLanes) return false;
977 return VectorList.Count == 1;
978 }
979
Jim Grosbach460a9052011-10-07 23:56:00 +0000980 bool isVectorIndex8() const {
981 if (Kind != k_VectorIndex) return false;
982 return VectorIndex.Val < 8;
983 }
984 bool isVectorIndex16() const {
985 if (Kind != k_VectorIndex) return false;
986 return VectorIndex.Val < 4;
987 }
988 bool isVectorIndex32() const {
989 if (Kind != k_VectorIndex) return false;
990 return VectorIndex.Val < 2;
991 }
992
Jim Grosbach0e387b22011-10-17 22:26:03 +0000993 bool isNEONi8splat() const {
994 if (Kind != k_Immediate)
995 return false;
996 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
997 // Must be a constant.
998 if (!CE) return false;
999 int64_t Value = CE->getValue();
1000 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1001 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001002 return Value >= 0 && Value < 256;
1003 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001004
Jim Grosbachea461102011-10-17 23:09:09 +00001005 bool isNEONi16splat() const {
1006 if (Kind != k_Immediate)
1007 return false;
1008 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1009 // Must be a constant.
1010 if (!CE) return false;
1011 int64_t Value = CE->getValue();
1012 // i16 value in the range [0,255] or [0x0100, 0xff00]
1013 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1014 }
1015
Jim Grosbach6248a542011-10-18 00:22:00 +00001016 bool isNEONi32splat() const {
1017 if (Kind != k_Immediate)
1018 return false;
1019 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1020 // Must be a constant.
1021 if (!CE) return false;
1022 int64_t Value = CE->getValue();
1023 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1024 return (Value >= 0 && Value < 256) ||
1025 (Value >= 0x0100 && Value <= 0xff00) ||
1026 (Value >= 0x010000 && Value <= 0xff0000) ||
1027 (Value >= 0x01000000 && Value <= 0xff000000);
1028 }
1029
1030 bool isNEONi32vmov() const {
1031 if (Kind != k_Immediate)
1032 return false;
1033 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1034 // Must be a constant.
1035 if (!CE) return false;
1036 int64_t Value = CE->getValue();
1037 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1038 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1039 return (Value >= 0 && Value < 256) ||
1040 (Value >= 0x0100 && Value <= 0xff00) ||
1041 (Value >= 0x010000 && Value <= 0xff0000) ||
1042 (Value >= 0x01000000 && Value <= 0xff000000) ||
1043 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1044 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1045 }
1046
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001047 bool isNEONi64splat() const {
1048 if (Kind != k_Immediate)
1049 return false;
1050 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1051 // Must be a constant.
1052 if (!CE) return false;
1053 uint64_t Value = CE->getValue();
1054 // i64 value with each byte being either 0 or 0xff.
1055 for (unsigned i = 0; i < 8; ++i)
1056 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1057 return true;
1058 }
1059
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001060 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001061 // Add as immediates when possible. Null MCExpr = 0.
1062 if (Expr == 0)
1063 Inst.addOperand(MCOperand::CreateImm(0));
1064 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001065 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1066 else
1067 Inst.addOperand(MCOperand::CreateExpr(Expr));
1068 }
1069
Daniel Dunbar8462b302010-08-11 06:36:53 +00001070 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001071 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001072 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001073 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1074 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001075 }
1076
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001077 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1078 assert(N == 1 && "Invalid number of operands!");
1079 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1080 }
1081
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001082 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1085 }
1086
1087 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1090 }
1091
Jim Grosbach89df9962011-08-26 21:43:41 +00001092 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1095 }
1096
1097 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1100 }
1101
Jim Grosbachd67641b2010-12-06 18:21:12 +00001102 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
1104 Inst.addOperand(MCOperand::CreateReg(getReg()));
1105 }
1106
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001107 void addRegOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 Inst.addOperand(MCOperand::CreateReg(getReg()));
1110 }
1111
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001112 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001113 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001114 assert(isRegShiftedReg() &&
1115 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001116 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1117 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001118 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001119 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001120 }
1121
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001122 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001123 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001124 assert(isRegShiftedImm() &&
1125 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001126 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001127 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001128 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001129 }
1130
Jim Grosbach580f4a92011-07-25 22:20:28 +00001131 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001132 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001133 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1134 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001135 }
1136
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001137 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001138 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001139 const SmallVectorImpl<unsigned> &RegList = getRegList();
1140 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001141 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1142 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001143 }
1144
Bill Wendling0f630752010-11-17 04:32:08 +00001145 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1146 addRegListOperands(Inst, N);
1147 }
1148
1149 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1150 addRegListOperands(Inst, N);
1151 }
1152
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001153 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1154 assert(N == 1 && "Invalid number of operands!");
1155 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1156 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1157 }
1158
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001159 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1160 assert(N == 1 && "Invalid number of operands!");
1161 // Munge the lsb/width into a bitfield mask.
1162 unsigned lsb = Bitfield.LSB;
1163 unsigned width = Bitfield.Width;
1164 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1165 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1166 (32 - (lsb + width)));
1167 Inst.addOperand(MCOperand::CreateImm(Mask));
1168 }
1169
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001170 void addImmOperands(MCInst &Inst, unsigned N) const {
1171 assert(N == 1 && "Invalid number of operands!");
1172 addExpr(Inst, getImm());
1173 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001174
Jim Grosbach9d390362011-10-03 23:38:36 +00001175 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
1177 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1178 }
1179
Jim Grosbacha77295d2011-09-08 22:07:06 +00001180 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 // FIXME: We really want to scale the value here, but the LDRD/STRD
1183 // instruction don't encode operands that way yet.
1184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1185 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1186 }
1187
Jim Grosbach72f39f82011-08-24 21:22:15 +00001188 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1189 assert(N == 1 && "Invalid number of operands!");
1190 // The immediate is scaled by four in the encoding and is stored
1191 // in the MCInst as such. Lop off the low two bits here.
1192 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1193 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1194 }
1195
1196 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 // The immediate is scaled by four in the encoding and is stored
1199 // in the MCInst as such. Lop off the low two bits here.
1200 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1201 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1202 }
1203
Jim Grosbachf4943352011-07-25 23:09:14 +00001204 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 // The constant encodes as the immediate-1, and we store in the instruction
1207 // the bits as encoded, so subtract off one here.
1208 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1209 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1210 }
1211
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001212 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1213 assert(N == 1 && "Invalid number of operands!");
1214 // The constant encodes as the immediate-1, and we store in the instruction
1215 // the bits as encoded, so subtract off one here.
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1218 }
1219
Jim Grosbach70939ee2011-08-17 21:51:27 +00001220 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1221 assert(N == 1 && "Invalid number of operands!");
1222 // The constant encodes as the immediate, except for 32, which encodes as
1223 // zero.
1224 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1225 unsigned Imm = CE->getValue();
1226 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1227 }
1228
Jim Grosbachf6c05252011-07-21 17:23:04 +00001229 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1230 assert(N == 1 && "Invalid number of operands!");
1231 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1232 // the instruction as well.
1233 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1234 int Val = CE->getValue();
1235 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1236 }
1237
Jim Grosbach89a63372011-10-28 22:36:30 +00001238 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1239 assert(N == 1 && "Invalid number of operands!");
1240 // The operand is actually a t2_so_imm, but we have its bitwise
1241 // negation in the assembly source, so twiddle it here.
1242 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1243 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1244 }
1245
Jim Grosbache70ec842011-10-28 22:50:54 +00001246 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
1248 // The operand is actually a so_imm, but we have its bitwise
1249 // negation in the assembly source, so twiddle it here.
1250 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1251 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1252 }
1253
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001254 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1255 assert(N == 1 && "Invalid number of operands!");
1256 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1257 }
1258
Jim Grosbach7ce05792011-08-03 23:50:40 +00001259 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001261 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001262 }
1263
Jim Grosbach57dcb852011-10-11 17:29:55 +00001264 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 2 && "Invalid number of operands!");
1266 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1267 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1268 }
1269
Jim Grosbach7ce05792011-08-03 23:50:40 +00001270 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1271 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001272 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1273 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001274 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1275 // Special case for #-0
1276 if (Val == INT32_MIN) Val = 0;
1277 if (Val < 0) Val = -Val;
1278 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1279 } else {
1280 // For register offset, we encode the shift type and negation flag
1281 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001282 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1283 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001284 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001285 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1286 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001287 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001288 }
1289
Jim Grosbach039c2e12011-08-04 23:01:30 +00001290 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 2 && "Invalid number of operands!");
1292 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1293 assert(CE && "non-constant AM2OffsetImm operand!");
1294 int32_t Val = CE->getValue();
1295 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1296 // Special case for #-0
1297 if (Val == INT32_MIN) Val = 0;
1298 if (Val < 0) Val = -Val;
1299 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1300 Inst.addOperand(MCOperand::CreateReg(0));
1301 Inst.addOperand(MCOperand::CreateImm(Val));
1302 }
1303
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001304 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1305 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001306 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1307 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001308 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1309 // Special case for #-0
1310 if (Val == INT32_MIN) Val = 0;
1311 if (Val < 0) Val = -Val;
1312 Val = ARM_AM::getAM3Opc(AddSub, Val);
1313 } else {
1314 // For register offset, we encode the shift type and negation flag
1315 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001316 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001317 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001318 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1319 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001320 Inst.addOperand(MCOperand::CreateImm(Val));
1321 }
1322
1323 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001325 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001326 int32_t Val =
1327 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1328 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1329 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001330 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001331 }
1332
1333 // Constant offset.
1334 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1335 int32_t Val = CE->getValue();
1336 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1337 // Special case for #-0
1338 if (Val == INT32_MIN) Val = 0;
1339 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001340 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001341 Inst.addOperand(MCOperand::CreateReg(0));
1342 Inst.addOperand(MCOperand::CreateImm(Val));
1343 }
1344
Jim Grosbach7ce05792011-08-03 23:50:40 +00001345 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1346 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001347 // If we have an immediate that's not a constant, treat it as a label
1348 // reference needing a fixup. If it is a constant, it's something else
1349 // and we reject it.
1350 if (isImm()) {
1351 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1352 Inst.addOperand(MCOperand::CreateImm(0));
1353 return;
1354 }
1355
Jim Grosbach7ce05792011-08-03 23:50:40 +00001356 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001357 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001358 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1359 // Special case for #-0
1360 if (Val == INT32_MIN) Val = 0;
1361 if (Val < 0) Val = -Val;
1362 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001363 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001364 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001365 }
1366
Jim Grosbacha77295d2011-09-08 22:07:06 +00001367 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1368 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001369 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1370 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001371 Inst.addOperand(MCOperand::CreateImm(Val));
1372 }
1373
Jim Grosbachb6aed502011-09-09 18:37:27 +00001374 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1375 assert(N == 2 && "Invalid number of operands!");
1376 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001377 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1378 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001379 Inst.addOperand(MCOperand::CreateImm(Val));
1380 }
1381
Jim Grosbach7ce05792011-08-03 23:50:40 +00001382 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1383 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001384 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1385 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001386 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001387 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001388
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001389 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1390 addMemImm8OffsetOperands(Inst, N);
1391 }
1392
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001393 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001394 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001395 }
1396
1397 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1398 assert(N == 2 && "Invalid number of operands!");
1399 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001400 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001401 addExpr(Inst, getImm());
1402 Inst.addOperand(MCOperand::CreateImm(0));
1403 return;
1404 }
1405
1406 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001407 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1408 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001409 Inst.addOperand(MCOperand::CreateImm(Val));
1410 }
1411
Jim Grosbach7ce05792011-08-03 23:50:40 +00001412 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1413 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001414 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001415 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001416 addExpr(Inst, getImm());
1417 Inst.addOperand(MCOperand::CreateImm(0));
1418 return;
1419 }
1420
1421 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001422 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1423 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001424 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001425 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001426
Jim Grosbach7f739be2011-09-19 22:21:13 +00001427 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1428 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001429 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1430 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001431 }
1432
1433 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001435 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1436 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001437 }
1438
Jim Grosbach7ce05792011-08-03 23:50:40 +00001439 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1440 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001441 unsigned Val =
1442 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1443 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001444 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1445 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001446 Inst.addOperand(MCOperand::CreateImm(Val));
1447 }
1448
Jim Grosbachab899c12011-09-07 23:10:15 +00001449 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1450 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001451 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1452 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1453 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001454 }
1455
Jim Grosbach7ce05792011-08-03 23:50:40 +00001456 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1457 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001458 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1459 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001460 }
1461
Jim Grosbach60f91a32011-08-19 17:55:24 +00001462 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1463 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001464 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1465 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001466 Inst.addOperand(MCOperand::CreateImm(Val));
1467 }
1468
Jim Grosbach38466302011-08-19 18:55:51 +00001469 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1470 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001471 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1472 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001473 Inst.addOperand(MCOperand::CreateImm(Val));
1474 }
1475
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001476 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1477 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001478 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1479 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001480 Inst.addOperand(MCOperand::CreateImm(Val));
1481 }
1482
Jim Grosbachecd85892011-08-19 18:13:48 +00001483 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001485 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1486 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001487 Inst.addOperand(MCOperand::CreateImm(Val));
1488 }
1489
Jim Grosbach7ce05792011-08-03 23:50:40 +00001490 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1491 assert(N == 1 && "Invalid number of operands!");
1492 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1493 assert(CE && "non-constant post-idx-imm8 operand!");
1494 int Imm = CE->getValue();
1495 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001496 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001497 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1498 Inst.addOperand(MCOperand::CreateImm(Imm));
1499 }
1500
Jim Grosbach2bd01182011-10-11 21:55:36 +00001501 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1502 assert(N == 1 && "Invalid number of operands!");
1503 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1504 assert(CE && "non-constant post-idx-imm8s4 operand!");
1505 int Imm = CE->getValue();
1506 bool isAdd = Imm >= 0;
1507 if (Imm == INT32_MIN) Imm = 0;
1508 // Immediate is scaled by 4.
1509 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1510 Inst.addOperand(MCOperand::CreateImm(Imm));
1511 }
1512
Jim Grosbach7ce05792011-08-03 23:50:40 +00001513 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 2 && "Invalid number of operands!");
1515 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001516 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1517 }
1518
1519 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1520 assert(N == 2 && "Invalid number of operands!");
1521 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1522 // The sign, shift type, and shift amount are encoded in a single operand
1523 // using the AM2 encoding helpers.
1524 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1525 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1526 PostIdxReg.ShiftTy);
1527 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001528 }
1529
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001530 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 1 && "Invalid number of operands!");
1532 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1533 }
1534
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001535 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1538 }
1539
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001540 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001541 assert(N == 1 && "Invalid number of operands!");
1542 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1543 }
1544
Jim Grosbach460a9052011-10-07 23:56:00 +00001545 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
1547 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1548 }
1549
1550 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1553 }
1554
1555 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1558 }
1559
Jim Grosbach0e387b22011-10-17 22:26:03 +00001560 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 // The immediate encodes the type of constant as well as the value.
1563 // Mask in that this is an i8 splat.
1564 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1565 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1566 }
1567
Jim Grosbachea461102011-10-17 23:09:09 +00001568 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1569 assert(N == 1 && "Invalid number of operands!");
1570 // The immediate encodes the type of constant as well as the value.
1571 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1572 unsigned Value = CE->getValue();
1573 if (Value >= 256)
1574 Value = (Value >> 8) | 0xa00;
1575 else
1576 Value |= 0x800;
1577 Inst.addOperand(MCOperand::CreateImm(Value));
1578 }
1579
Jim Grosbach6248a542011-10-18 00:22:00 +00001580 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 // The immediate encodes the type of constant as well as the value.
1583 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1584 unsigned Value = CE->getValue();
1585 if (Value >= 256 && Value <= 0xff00)
1586 Value = (Value >> 8) | 0x200;
1587 else if (Value > 0xffff && Value <= 0xff0000)
1588 Value = (Value >> 16) | 0x400;
1589 else if (Value > 0xffffff)
1590 Value = (Value >> 24) | 0x600;
1591 Inst.addOperand(MCOperand::CreateImm(Value));
1592 }
1593
1594 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 1 && "Invalid number of operands!");
1596 // The immediate encodes the type of constant as well as the value.
1597 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1598 unsigned Value = CE->getValue();
1599 if (Value >= 256 && Value <= 0xffff)
1600 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1601 else if (Value > 0xffff && Value <= 0xffffff)
1602 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1603 else if (Value > 0xffffff)
1604 Value = (Value >> 24) | 0x600;
1605 Inst.addOperand(MCOperand::CreateImm(Value));
1606 }
1607
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001608 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 // The immediate encodes the type of constant as well as the value.
1611 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1612 uint64_t Value = CE->getValue();
1613 unsigned Imm = 0;
1614 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1615 Imm |= (Value & 1) << i;
1616 }
1617 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1618 }
1619
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001620 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001621
Jim Grosbach89df9962011-08-26 21:43:41 +00001622 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001623 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001624 Op->ITMask.Mask = Mask;
1625 Op->StartLoc = S;
1626 Op->EndLoc = S;
1627 return Op;
1628 }
1629
Chris Lattner3a697562010-10-28 17:20:03 +00001630 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001631 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001632 Op->CC.Val = CC;
1633 Op->StartLoc = S;
1634 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001635 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001636 }
1637
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001638 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001639 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001640 Op->Cop.Val = CopVal;
1641 Op->StartLoc = S;
1642 Op->EndLoc = S;
1643 return Op;
1644 }
1645
1646 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001647 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001648 Op->Cop.Val = CopVal;
1649 Op->StartLoc = S;
1650 Op->EndLoc = S;
1651 return Op;
1652 }
1653
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001654 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1655 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1656 Op->Cop.Val = Val;
1657 Op->StartLoc = S;
1658 Op->EndLoc = E;
1659 return Op;
1660 }
1661
Jim Grosbachd67641b2010-12-06 18:21:12 +00001662 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001663 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001664 Op->Reg.RegNum = RegNum;
1665 Op->StartLoc = S;
1666 Op->EndLoc = S;
1667 return Op;
1668 }
1669
Chris Lattner3a697562010-10-28 17:20:03 +00001670 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001671 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001672 Op->Tok.Data = Str.data();
1673 Op->Tok.Length = Str.size();
1674 Op->StartLoc = S;
1675 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001676 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001677 }
1678
Bill Wendling50d0f582010-11-18 23:43:05 +00001679 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001680 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001681 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001682 Op->StartLoc = S;
1683 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001684 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001685 }
1686
Jim Grosbache8606dc2011-07-13 17:50:29 +00001687 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1688 unsigned SrcReg,
1689 unsigned ShiftReg,
1690 unsigned ShiftImm,
1691 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001692 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001693 Op->RegShiftedReg.ShiftTy = ShTy;
1694 Op->RegShiftedReg.SrcReg = SrcReg;
1695 Op->RegShiftedReg.ShiftReg = ShiftReg;
1696 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = E;
1699 return Op;
1700 }
1701
Owen Anderson92a20222011-07-21 18:54:16 +00001702 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1703 unsigned SrcReg,
1704 unsigned ShiftImm,
1705 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001706 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001707 Op->RegShiftedImm.ShiftTy = ShTy;
1708 Op->RegShiftedImm.SrcReg = SrcReg;
1709 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001710 Op->StartLoc = S;
1711 Op->EndLoc = E;
1712 return Op;
1713 }
1714
Jim Grosbach580f4a92011-07-25 22:20:28 +00001715 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001716 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001717 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001718 Op->ShifterImm.isASR = isASR;
1719 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001720 Op->StartLoc = S;
1721 Op->EndLoc = E;
1722 return Op;
1723 }
1724
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001725 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001726 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001727 Op->RotImm.Imm = Imm;
1728 Op->StartLoc = S;
1729 Op->EndLoc = E;
1730 return Op;
1731 }
1732
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001733 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1734 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001735 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001736 Op->Bitfield.LSB = LSB;
1737 Op->Bitfield.Width = Width;
1738 Op->StartLoc = S;
1739 Op->EndLoc = E;
1740 return Op;
1741 }
1742
Bill Wendling7729e062010-11-09 22:44:22 +00001743 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001744 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001745 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001746 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001747
Jim Grosbachd300b942011-09-13 22:56:44 +00001748 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001749 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001750 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001751 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001752 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001753
1754 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001755 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001756 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001757 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001758 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001759 Op->StartLoc = StartLoc;
1760 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001761 return Op;
1762 }
1763
Jim Grosbach862019c2011-10-18 23:02:30 +00001764 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1765 SMLoc S, SMLoc E) {
1766 ARMOperand *Op = new ARMOperand(k_VectorList);
1767 Op->VectorList.RegNum = RegNum;
1768 Op->VectorList.Count = Count;
1769 Op->StartLoc = S;
1770 Op->EndLoc = E;
1771 return Op;
1772 }
1773
Jim Grosbach98b05a52011-11-30 01:09:44 +00001774 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1775 SMLoc S, SMLoc E) {
1776 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1777 Op->VectorList.RegNum = RegNum;
1778 Op->VectorList.Count = Count;
1779 Op->StartLoc = S;
1780 Op->EndLoc = E;
1781 return Op;
1782 }
1783
Jim Grosbach460a9052011-10-07 23:56:00 +00001784 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1785 MCContext &Ctx) {
1786 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1787 Op->VectorIndex.Val = Idx;
1788 Op->StartLoc = S;
1789 Op->EndLoc = E;
1790 return Op;
1791 }
1792
Chris Lattner3a697562010-10-28 17:20:03 +00001793 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001794 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001795 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001796 Op->StartLoc = S;
1797 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001798 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001799 }
1800
Jim Grosbach9d390362011-10-03 23:38:36 +00001801 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001802 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001803 Op->FPImm.Val = Val;
1804 Op->StartLoc = S;
1805 Op->EndLoc = S;
1806 return Op;
1807 }
1808
Jim Grosbach7ce05792011-08-03 23:50:40 +00001809 static ARMOperand *CreateMem(unsigned BaseRegNum,
1810 const MCConstantExpr *OffsetImm,
1811 unsigned OffsetRegNum,
1812 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001813 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001814 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001815 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001816 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001817 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001818 Op->Memory.BaseRegNum = BaseRegNum;
1819 Op->Memory.OffsetImm = OffsetImm;
1820 Op->Memory.OffsetRegNum = OffsetRegNum;
1821 Op->Memory.ShiftType = ShiftType;
1822 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001823 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001824 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001825 Op->StartLoc = S;
1826 Op->EndLoc = E;
1827 return Op;
1828 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001829
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001830 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1831 ARM_AM::ShiftOpc ShiftTy,
1832 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001833 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001834 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001835 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001836 Op->PostIdxReg.isAdd = isAdd;
1837 Op->PostIdxReg.ShiftTy = ShiftTy;
1838 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001839 Op->StartLoc = S;
1840 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001841 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001842 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001843
1844 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001845 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001846 Op->MBOpt.Val = Opt;
1847 Op->StartLoc = S;
1848 Op->EndLoc = S;
1849 return Op;
1850 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001851
1852 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001853 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001854 Op->IFlags.Val = IFlags;
1855 Op->StartLoc = S;
1856 Op->EndLoc = S;
1857 return Op;
1858 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001859
1860 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001861 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001862 Op->MMask.Val = MMask;
1863 Op->StartLoc = S;
1864 Op->EndLoc = S;
1865 return Op;
1866 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001867};
1868
1869} // end anonymous namespace.
1870
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001871void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001872 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001873 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001874 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1875 << ") >";
1876 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001877 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001878 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001879 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001880 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001881 OS << "<ccout " << getReg() << ">";
1882 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001883 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001884 static const char *MaskStr[] = {
1885 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1886 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1887 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001888 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1889 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1890 break;
1891 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001892 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001893 OS << "<coprocessor number: " << getCoproc() << ">";
1894 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001895 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001896 OS << "<coprocessor register: " << getCoproc() << ">";
1897 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001898 case k_CoprocOption:
1899 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1900 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001901 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001902 OS << "<mask: " << getMSRMask() << ">";
1903 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001904 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001905 getImm()->print(OS);
1906 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001907 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001908 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1909 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001911 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001912 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001913 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001916 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1917 << PostIdxReg.RegNum;
1918 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1919 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1920 << PostIdxReg.ShiftImm;
1921 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001922 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001923 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001924 OS << "<ARM_PROC::";
1925 unsigned IFlags = getProcIFlags();
1926 for (int i=2; i >= 0; --i)
1927 if (IFlags & (1 << i))
1928 OS << ARM_PROC::IFlagsToString(1 << i);
1929 OS << ">";
1930 break;
1931 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001932 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001933 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001934 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001935 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001936 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1937 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001938 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001939 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001940 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001941 << RegShiftedReg.SrcReg << " "
1942 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
1943 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001944 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001945 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001946 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001947 << RegShiftedImm.SrcReg << " "
1948 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
1949 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00001950 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001951 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001952 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1953 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001954 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001955 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1956 << ", width: " << Bitfield.Width << ">";
1957 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001958 case k_RegisterList:
1959 case k_DPRRegisterList:
1960 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001961 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001962
Bill Wendling5fa22a12010-11-09 23:28:44 +00001963 const SmallVectorImpl<unsigned> &RegList = getRegList();
1964 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001965 I = RegList.begin(), E = RegList.end(); I != E; ) {
1966 OS << *I;
1967 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001968 }
1969
1970 OS << ">";
1971 break;
1972 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001973 case k_VectorList:
1974 OS << "<vector_list " << VectorList.Count << " * "
1975 << VectorList.RegNum << ">";
1976 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001977 case k_VectorListAllLanes:
1978 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
1979 << VectorList.RegNum << ">";
1980 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001981 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001982 OS << "'" << getToken() << "'";
1983 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001984 case k_VectorIndex:
1985 OS << "<vectorindex " << getVectorIndex() << ">";
1986 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001987 }
1988}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001989
1990/// @name Auto-generated Match Functions
1991/// {
1992
1993static unsigned MatchRegisterName(StringRef Name);
1994
1995/// }
1996
Bob Wilson69df7232011-02-03 21:46:10 +00001997bool ARMAsmParser::ParseRegister(unsigned &RegNo,
1998 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00001999 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002000
2001 return (RegNo == (unsigned)-1);
2002}
2003
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002004/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002005/// and if it is a register name the token is eaten and the register number is
2006/// returned. Otherwise return -1.
2007///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002008int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002009 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002010 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002011
Chris Lattnere5658fa2010-10-30 04:09:10 +00002012 // FIXME: Validate register for the current architecture; we have to do
2013 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002014 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002015 unsigned RegNum = MatchRegisterName(lowerCase);
2016 if (!RegNum) {
2017 RegNum = StringSwitch<unsigned>(lowerCase)
2018 .Case("r13", ARM::SP)
2019 .Case("r14", ARM::LR)
2020 .Case("r15", ARM::PC)
2021 .Case("ip", ARM::R12)
2022 .Default(0);
2023 }
2024 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002025
Chris Lattnere5658fa2010-10-30 04:09:10 +00002026 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002027
Chris Lattnere5658fa2010-10-30 04:09:10 +00002028 return RegNum;
2029}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002030
Jim Grosbach19906722011-07-13 18:49:30 +00002031// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2032// If a recoverable error occurs, return 1. If an irrecoverable error
2033// occurs, return -1. An irrecoverable error is one where tokens have been
2034// consumed in the process of trying to parse the shifter (i.e., when it is
2035// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002036int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002037 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2038 SMLoc S = Parser.getTok().getLoc();
2039 const AsmToken &Tok = Parser.getTok();
2040 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2041
Benjamin Kramer59085362011-11-06 20:37:06 +00002042 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002043 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2044 .Case("lsl", ARM_AM::lsl)
2045 .Case("lsr", ARM_AM::lsr)
2046 .Case("asr", ARM_AM::asr)
2047 .Case("ror", ARM_AM::ror)
2048 .Case("rrx", ARM_AM::rrx)
2049 .Default(ARM_AM::no_shift);
2050
2051 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002052 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002053
Jim Grosbache8606dc2011-07-13 17:50:29 +00002054 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002055
Jim Grosbache8606dc2011-07-13 17:50:29 +00002056 // The source register for the shift has already been added to the
2057 // operand list, so we need to pop it off and combine it into the shifted
2058 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002059 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002060 if (!PrevOp->isReg())
2061 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2062 int SrcReg = PrevOp->getReg();
2063 int64_t Imm = 0;
2064 int ShiftReg = 0;
2065 if (ShiftTy == ARM_AM::rrx) {
2066 // RRX Doesn't have an explicit shift amount. The encoder expects
2067 // the shift register to be the same as the source register. Seems odd,
2068 // but OK.
2069 ShiftReg = SrcReg;
2070 } else {
2071 // Figure out if this is shifted by a constant or a register (for non-RRX).
2072 if (Parser.getTok().is(AsmToken::Hash)) {
2073 Parser.Lex(); // Eat hash.
2074 SMLoc ImmLoc = Parser.getTok().getLoc();
2075 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002076 if (getParser().ParseExpression(ShiftExpr)) {
2077 Error(ImmLoc, "invalid immediate shift value");
2078 return -1;
2079 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002080 // The expression must be evaluatable as an immediate.
2081 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002082 if (!CE) {
2083 Error(ImmLoc, "invalid immediate shift value");
2084 return -1;
2085 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002086 // Range check the immediate.
2087 // lsl, ror: 0 <= imm <= 31
2088 // lsr, asr: 0 <= imm <= 32
2089 Imm = CE->getValue();
2090 if (Imm < 0 ||
2091 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2092 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002093 Error(ImmLoc, "immediate shift value out of range");
2094 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002095 }
2096 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002097 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002098 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002099 if (ShiftReg == -1) {
2100 Error (L, "expected immediate or register in shift operand");
2101 return -1;
2102 }
2103 } else {
2104 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002105 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002106 return -1;
2107 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002108 }
2109
Owen Anderson92a20222011-07-21 18:54:16 +00002110 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2111 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002112 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002113 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002114 else
2115 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2116 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002117
Jim Grosbach19906722011-07-13 18:49:30 +00002118 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002119}
2120
2121
Bill Wendling50d0f582010-11-18 23:43:05 +00002122/// Try to parse a register name. The token must be an Identifier when called.
2123/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2124/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002125///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002126/// TODO this is likely to change to allow different register types and or to
2127/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002128bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002129tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002130 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002131 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002132 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002133 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002134
Bill Wendling50d0f582010-11-18 23:43:05 +00002135 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002136
Chris Lattnere5658fa2010-10-30 04:09:10 +00002137 const AsmToken &ExclaimTok = Parser.getTok();
2138 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002139 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2140 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002141 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002142 return false;
2143 }
2144
2145 // Also check for an index operand. This is only legal for vector registers,
2146 // but that'll get caught OK in operand matching, so we don't need to
2147 // explicitly filter everything else out here.
2148 if (Parser.getTok().is(AsmToken::LBrac)) {
2149 SMLoc SIdx = Parser.getTok().getLoc();
2150 Parser.Lex(); // Eat left bracket token.
2151
2152 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002153 if (getParser().ParseExpression(ImmVal))
2154 return MatchOperand_ParseFail;
2155 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2156 if (!MCE) {
2157 TokError("immediate value expected for vector index");
2158 return MatchOperand_ParseFail;
2159 }
2160
2161 SMLoc E = Parser.getTok().getLoc();
2162 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2163 Error(E, "']' expected");
2164 return MatchOperand_ParseFail;
2165 }
2166
2167 Parser.Lex(); // Eat right bracket token.
2168
2169 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2170 SIdx, E,
2171 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002172 }
2173
Bill Wendling50d0f582010-11-18 23:43:05 +00002174 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002175}
2176
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002177/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2178/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2179/// "c5", ...
2180static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002181 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2182 // but efficient.
2183 switch (Name.size()) {
2184 default: break;
2185 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002186 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002187 return -1;
2188 switch (Name[1]) {
2189 default: return -1;
2190 case '0': return 0;
2191 case '1': return 1;
2192 case '2': return 2;
2193 case '3': return 3;
2194 case '4': return 4;
2195 case '5': return 5;
2196 case '6': return 6;
2197 case '7': return 7;
2198 case '8': return 8;
2199 case '9': return 9;
2200 }
2201 break;
2202 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002203 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002204 return -1;
2205 switch (Name[2]) {
2206 default: return -1;
2207 case '0': return 10;
2208 case '1': return 11;
2209 case '2': return 12;
2210 case '3': return 13;
2211 case '4': return 14;
2212 case '5': return 15;
2213 }
2214 break;
2215 }
2216
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002217 return -1;
2218}
2219
Jim Grosbach89df9962011-08-26 21:43:41 +00002220/// parseITCondCode - Try to parse a condition code for an IT instruction.
2221ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2222parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2223 SMLoc S = Parser.getTok().getLoc();
2224 const AsmToken &Tok = Parser.getTok();
2225 if (!Tok.is(AsmToken::Identifier))
2226 return MatchOperand_NoMatch;
2227 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2228 .Case("eq", ARMCC::EQ)
2229 .Case("ne", ARMCC::NE)
2230 .Case("hs", ARMCC::HS)
2231 .Case("cs", ARMCC::HS)
2232 .Case("lo", ARMCC::LO)
2233 .Case("cc", ARMCC::LO)
2234 .Case("mi", ARMCC::MI)
2235 .Case("pl", ARMCC::PL)
2236 .Case("vs", ARMCC::VS)
2237 .Case("vc", ARMCC::VC)
2238 .Case("hi", ARMCC::HI)
2239 .Case("ls", ARMCC::LS)
2240 .Case("ge", ARMCC::GE)
2241 .Case("lt", ARMCC::LT)
2242 .Case("gt", ARMCC::GT)
2243 .Case("le", ARMCC::LE)
2244 .Case("al", ARMCC::AL)
2245 .Default(~0U);
2246 if (CC == ~0U)
2247 return MatchOperand_NoMatch;
2248 Parser.Lex(); // Eat the token.
2249
2250 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2251
2252 return MatchOperand_Success;
2253}
2254
Jim Grosbach43904292011-07-25 20:14:50 +00002255/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002256/// token must be an Identifier when called, and if it is a coprocessor
2257/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002258ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002259parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002260 SMLoc S = Parser.getTok().getLoc();
2261 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002262 if (Tok.isNot(AsmToken::Identifier))
2263 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002264
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002265 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002266 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002267 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002268
2269 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002270 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002271 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002272}
2273
Jim Grosbach43904292011-07-25 20:14:50 +00002274/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002275/// token must be an Identifier when called, and if it is a coprocessor
2276/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002277ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002278parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002279 SMLoc S = Parser.getTok().getLoc();
2280 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002281 if (Tok.isNot(AsmToken::Identifier))
2282 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002283
2284 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2285 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002286 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002287
2288 Parser.Lex(); // Eat identifier token.
2289 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002290 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002291}
2292
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002293/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2294/// coproc_option : '{' imm0_255 '}'
2295ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2296parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2297 SMLoc S = Parser.getTok().getLoc();
2298
2299 // If this isn't a '{', this isn't a coprocessor immediate operand.
2300 if (Parser.getTok().isNot(AsmToken::LCurly))
2301 return MatchOperand_NoMatch;
2302 Parser.Lex(); // Eat the '{'
2303
2304 const MCExpr *Expr;
2305 SMLoc Loc = Parser.getTok().getLoc();
2306 if (getParser().ParseExpression(Expr)) {
2307 Error(Loc, "illegal expression");
2308 return MatchOperand_ParseFail;
2309 }
2310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2311 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2312 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2313 return MatchOperand_ParseFail;
2314 }
2315 int Val = CE->getValue();
2316
2317 // Check for and consume the closing '}'
2318 if (Parser.getTok().isNot(AsmToken::RCurly))
2319 return MatchOperand_ParseFail;
2320 SMLoc E = Parser.getTok().getLoc();
2321 Parser.Lex(); // Eat the '}'
2322
2323 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2324 return MatchOperand_Success;
2325}
2326
Jim Grosbachd0588e22011-09-14 18:08:35 +00002327// For register list parsing, we need to map from raw GPR register numbering
2328// to the enumeration values. The enumeration values aren't sorted by
2329// register number due to our using "sp", "lr" and "pc" as canonical names.
2330static unsigned getNextRegister(unsigned Reg) {
2331 // If this is a GPR, we need to do it manually, otherwise we can rely
2332 // on the sort ordering of the enumeration since the other reg-classes
2333 // are sane.
2334 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2335 return Reg + 1;
2336 switch(Reg) {
2337 default: assert(0 && "Invalid GPR number!");
2338 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2339 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2340 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2341 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2342 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2343 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2344 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2345 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2346 }
2347}
2348
Jim Grosbachce485e72011-11-11 21:27:40 +00002349// Return the low-subreg of a given Q register.
2350static unsigned getDRegFromQReg(unsigned QReg) {
2351 switch (QReg) {
2352 default: llvm_unreachable("expected a Q register!");
2353 case ARM::Q0: return ARM::D0;
2354 case ARM::Q1: return ARM::D2;
2355 case ARM::Q2: return ARM::D4;
2356 case ARM::Q3: return ARM::D6;
2357 case ARM::Q4: return ARM::D8;
2358 case ARM::Q5: return ARM::D10;
2359 case ARM::Q6: return ARM::D12;
2360 case ARM::Q7: return ARM::D14;
2361 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002362 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002363 case ARM::Q10: return ARM::D20;
2364 case ARM::Q11: return ARM::D22;
2365 case ARM::Q12: return ARM::D24;
2366 case ARM::Q13: return ARM::D26;
2367 case ARM::Q14: return ARM::D28;
2368 case ARM::Q15: return ARM::D30;
2369 }
2370}
2371
Jim Grosbachd0588e22011-09-14 18:08:35 +00002372/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002373bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002374parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002375 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002376 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002377 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002378 Parser.Lex(); // Eat '{' token.
2379 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002380
Jim Grosbachd0588e22011-09-14 18:08:35 +00002381 // Check the first register in the list to see what register class
2382 // this is a list of.
2383 int Reg = tryParseRegister();
2384 if (Reg == -1)
2385 return Error(RegLoc, "register expected");
2386
Jim Grosbachce485e72011-11-11 21:27:40 +00002387 // The reglist instructions have at most 16 registers, so reserve
2388 // space for that many.
2389 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2390
2391 // Allow Q regs and just interpret them as the two D sub-registers.
2392 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2393 Reg = getDRegFromQReg(Reg);
2394 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2395 ++Reg;
2396 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002397 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002398 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2399 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2400 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2401 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2402 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2403 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2404 else
2405 return Error(RegLoc, "invalid register in register list");
2406
Jim Grosbachce485e72011-11-11 21:27:40 +00002407 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002408 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002409
Jim Grosbachd0588e22011-09-14 18:08:35 +00002410 // This starts immediately after the first register token in the list,
2411 // so we can see either a comma or a minus (range separator) as a legal
2412 // next token.
2413 while (Parser.getTok().is(AsmToken::Comma) ||
2414 Parser.getTok().is(AsmToken::Minus)) {
2415 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002416 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002417 SMLoc EndLoc = Parser.getTok().getLoc();
2418 int EndReg = tryParseRegister();
2419 if (EndReg == -1)
2420 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002421 // Allow Q regs and just interpret them as the two D sub-registers.
2422 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2423 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002424 // If the register is the same as the start reg, there's nothing
2425 // more to do.
2426 if (Reg == EndReg)
2427 continue;
2428 // The register must be in the same register class as the first.
2429 if (!RC->contains(EndReg))
2430 return Error(EndLoc, "invalid register in register list");
2431 // Ranges must go from low to high.
2432 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2433 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002434
Jim Grosbachd0588e22011-09-14 18:08:35 +00002435 // Add all the registers in the range to the register list.
2436 while (Reg != EndReg) {
2437 Reg = getNextRegister(Reg);
2438 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2439 }
2440 continue;
2441 }
2442 Parser.Lex(); // Eat the comma.
2443 RegLoc = Parser.getTok().getLoc();
2444 int OldReg = Reg;
2445 Reg = tryParseRegister();
2446 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002447 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002448 // Allow Q regs and just interpret them as the two D sub-registers.
2449 bool isQReg = false;
2450 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2451 Reg = getDRegFromQReg(Reg);
2452 isQReg = true;
2453 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002454 // The register must be in the same register class as the first.
2455 if (!RC->contains(Reg))
2456 return Error(RegLoc, "invalid register in register list");
2457 // List must be monotonically increasing.
2458 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2459 return Error(RegLoc, "register list not in ascending order");
2460 // VFP register lists must also be contiguous.
2461 // It's OK to use the enumeration values directly here rather, as the
2462 // VFP register classes have the enum sorted properly.
2463 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2464 Reg != OldReg + 1)
2465 return Error(RegLoc, "non-contiguous register range");
2466 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002467 if (isQReg)
2468 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002469 }
2470
Jim Grosbachd0588e22011-09-14 18:08:35 +00002471 SMLoc E = Parser.getTok().getLoc();
2472 if (Parser.getTok().isNot(AsmToken::RCurly))
2473 return Error(E, "'}' expected");
2474 Parser.Lex(); // Eat '}' token.
2475
Bill Wendling50d0f582010-11-18 23:43:05 +00002476 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2477 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002478}
2479
Jim Grosbach98b05a52011-11-30 01:09:44 +00002480// Helper function to parse the lane index for vector lists.
2481ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2482parseVectorLane(VectorLaneTy &LaneKind) {
2483 if (Parser.getTok().is(AsmToken::LBrac)) {
2484 Parser.Lex(); // Eat the '['.
2485 if (Parser.getTok().is(AsmToken::RBrac)) {
2486 // "Dn[]" is the 'all lanes' syntax.
2487 LaneKind = AllLanes;
2488 Parser.Lex(); // Eat the ']'.
2489 return MatchOperand_Success;
2490 }
2491 // FIXME: Other lane kinds as we add them.
2492 Error(Parser.getTok().getLoc(), "FIXME: Unexpected lane kind.");
2493 return MatchOperand_ParseFail;
2494 }
2495 LaneKind = NoLanes;
2496 return MatchOperand_Success;
2497}
2498
Jim Grosbach862019c2011-10-18 23:02:30 +00002499// parse a vector register list
2500ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2501parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002502 VectorLaneTy LaneKind;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002503 SMLoc S = Parser.getTok().getLoc();
2504 // As an extension (to match gas), support a plain D register or Q register
2505 // (without encosing curly braces) as a single or double entry list,
2506 // respectively.
2507 if (Parser.getTok().is(AsmToken::Identifier)) {
2508 int Reg = tryParseRegister();
2509 if (Reg == -1)
2510 return MatchOperand_NoMatch;
2511 SMLoc E = Parser.getTok().getLoc();
2512 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002513 OperandMatchResultTy Res = parseVectorLane(LaneKind);
2514 if (Res != MatchOperand_Success)
2515 return Res;
2516 switch (LaneKind) {
2517 default:
2518 assert(0 && "unexpected lane kind!");
2519 case NoLanes:
2520 E = Parser.getTok().getLoc();
2521 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2522 break;
2523 case AllLanes:
2524 E = Parser.getTok().getLoc();
2525 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2526 break;
2527 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002528 return MatchOperand_Success;
2529 }
2530 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2531 Reg = getDRegFromQReg(Reg);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002532 OperandMatchResultTy Res = parseVectorLane(LaneKind);
2533 if (Res != MatchOperand_Success)
2534 return Res;
2535 switch (LaneKind) {
2536 default:
2537 assert(0 && "unexpected lane kind!");
2538 case NoLanes:
2539 E = Parser.getTok().getLoc();
2540 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2541 break;
2542 case AllLanes:
2543 E = Parser.getTok().getLoc();
2544 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2545 break;
2546 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002547 return MatchOperand_Success;
2548 }
2549 Error(S, "vector register expected");
2550 return MatchOperand_ParseFail;
2551 }
2552
2553 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002554 return MatchOperand_NoMatch;
2555
Jim Grosbach862019c2011-10-18 23:02:30 +00002556 Parser.Lex(); // Eat '{' token.
2557 SMLoc RegLoc = Parser.getTok().getLoc();
2558
2559 int Reg = tryParseRegister();
2560 if (Reg == -1) {
2561 Error(RegLoc, "register expected");
2562 return MatchOperand_ParseFail;
2563 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002564 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002565 unsigned FirstReg = Reg;
2566 // The list is of D registers, but we also allow Q regs and just interpret
2567 // them as the two D sub-registers.
2568 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2569 FirstReg = Reg = getDRegFromQReg(Reg);
2570 ++Reg;
2571 ++Count;
2572 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002573 if (parseVectorLane(LaneKind) != MatchOperand_Success)
2574 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002575
Jim Grosbache43862b2011-11-15 23:19:15 +00002576 while (Parser.getTok().is(AsmToken::Comma) ||
2577 Parser.getTok().is(AsmToken::Minus)) {
2578 if (Parser.getTok().is(AsmToken::Minus)) {
2579 Parser.Lex(); // Eat the minus.
2580 SMLoc EndLoc = Parser.getTok().getLoc();
2581 int EndReg = tryParseRegister();
2582 if (EndReg == -1) {
2583 Error(EndLoc, "register expected");
2584 return MatchOperand_ParseFail;
2585 }
2586 // Allow Q regs and just interpret them as the two D sub-registers.
2587 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2588 EndReg = getDRegFromQReg(EndReg) + 1;
2589 // If the register is the same as the start reg, there's nothing
2590 // more to do.
2591 if (Reg == EndReg)
2592 continue;
2593 // The register must be in the same register class as the first.
2594 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2595 Error(EndLoc, "invalid register in register list");
2596 return MatchOperand_ParseFail;
2597 }
2598 // Ranges must go from low to high.
2599 if (Reg > EndReg) {
2600 Error(EndLoc, "bad range in register list");
2601 return MatchOperand_ParseFail;
2602 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002603 // Parse the lane specifier if present.
2604 VectorLaneTy NextLaneKind;
2605 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2606 return MatchOperand_ParseFail;
2607 if (NextLaneKind != LaneKind) {
2608 Error(EndLoc, "mismatched lane index in register list");
2609 return MatchOperand_ParseFail;
2610 }
2611 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002612
2613 // Add all the registers in the range to the register list.
2614 Count += EndReg - Reg;
2615 Reg = EndReg;
2616 continue;
2617 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002618 Parser.Lex(); // Eat the comma.
2619 RegLoc = Parser.getTok().getLoc();
2620 int OldReg = Reg;
2621 Reg = tryParseRegister();
2622 if (Reg == -1) {
2623 Error(RegLoc, "register expected");
2624 return MatchOperand_ParseFail;
2625 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002626 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002627 // It's OK to use the enumeration values directly here rather, as the
2628 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002629 //
2630 // The list is of D registers, but we also allow Q regs and just interpret
2631 // them as the two D sub-registers.
2632 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2633 Reg = getDRegFromQReg(Reg);
2634 if (Reg != OldReg + 1) {
2635 Error(RegLoc, "non-contiguous register range");
2636 return MatchOperand_ParseFail;
2637 }
2638 ++Reg;
2639 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002640 // Parse the lane specifier if present.
2641 VectorLaneTy NextLaneKind;
2642 SMLoc EndLoc = Parser.getTok().getLoc();
2643 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2644 return MatchOperand_ParseFail;
2645 if (NextLaneKind != LaneKind) {
2646 Error(EndLoc, "mismatched lane index in register list");
2647 return MatchOperand_ParseFail;
2648 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002649 continue;
2650 }
2651 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002652 if (Reg != OldReg + 1) {
2653 Error(RegLoc, "non-contiguous register range");
2654 return MatchOperand_ParseFail;
2655 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002656 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002657 // Parse the lane specifier if present.
2658 VectorLaneTy NextLaneKind;
2659 SMLoc EndLoc = Parser.getTok().getLoc();
2660 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2661 return MatchOperand_ParseFail;
2662 if (NextLaneKind != LaneKind) {
2663 Error(EndLoc, "mismatched lane index in register list");
2664 return MatchOperand_ParseFail;
2665 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002666 }
2667
2668 SMLoc E = Parser.getTok().getLoc();
2669 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2670 Error(E, "'}' expected");
2671 return MatchOperand_ParseFail;
2672 }
2673 Parser.Lex(); // Eat '}' token.
2674
Jim Grosbach98b05a52011-11-30 01:09:44 +00002675 switch (LaneKind) {
2676 default:
2677 assert(0 && "unexpected lane kind in register list.");
2678 case NoLanes:
2679 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2680 break;
2681 case AllLanes:
2682 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2683 S, E));
2684 break;
2685 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002686 return MatchOperand_Success;
2687}
2688
Jim Grosbach43904292011-07-25 20:14:50 +00002689/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002690ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002691parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002692 SMLoc S = Parser.getTok().getLoc();
2693 const AsmToken &Tok = Parser.getTok();
2694 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2695 StringRef OptStr = Tok.getString();
2696
2697 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2698 .Case("sy", ARM_MB::SY)
2699 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002700 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002701 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002702 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002703 .Case("ishst", ARM_MB::ISHST)
2704 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002705 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002706 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002707 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002708 .Case("osh", ARM_MB::OSH)
2709 .Case("oshst", ARM_MB::OSHST)
2710 .Default(~0U);
2711
2712 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002713 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002714
2715 Parser.Lex(); // Eat identifier token.
2716 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002717 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002718}
2719
Jim Grosbach43904292011-07-25 20:14:50 +00002720/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002721ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002722parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002723 SMLoc S = Parser.getTok().getLoc();
2724 const AsmToken &Tok = Parser.getTok();
2725 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2726 StringRef IFlagsStr = Tok.getString();
2727
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002728 // An iflags string of "none" is interpreted to mean that none of the AIF
2729 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002730 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002731 if (IFlagsStr != "none") {
2732 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2733 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2734 .Case("a", ARM_PROC::A)
2735 .Case("i", ARM_PROC::I)
2736 .Case("f", ARM_PROC::F)
2737 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002738
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002739 // If some specific iflag is already set, it means that some letter is
2740 // present more than once, this is not acceptable.
2741 if (Flag == ~0U || (IFlags & Flag))
2742 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002743
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002744 IFlags |= Flag;
2745 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002746 }
2747
2748 Parser.Lex(); // Eat identifier token.
2749 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2750 return MatchOperand_Success;
2751}
2752
Jim Grosbach43904292011-07-25 20:14:50 +00002753/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002754ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002755parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002756 SMLoc S = Parser.getTok().getLoc();
2757 const AsmToken &Tok = Parser.getTok();
2758 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2759 StringRef Mask = Tok.getString();
2760
James Molloyacad68d2011-09-28 14:21:38 +00002761 if (isMClass()) {
2762 // See ARMv6-M 10.1.1
2763 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2764 .Case("apsr", 0)
2765 .Case("iapsr", 1)
2766 .Case("eapsr", 2)
2767 .Case("xpsr", 3)
2768 .Case("ipsr", 5)
2769 .Case("epsr", 6)
2770 .Case("iepsr", 7)
2771 .Case("msp", 8)
2772 .Case("psp", 9)
2773 .Case("primask", 16)
2774 .Case("basepri", 17)
2775 .Case("basepri_max", 18)
2776 .Case("faultmask", 19)
2777 .Case("control", 20)
2778 .Default(~0U);
2779
2780 if (FlagsVal == ~0U)
2781 return MatchOperand_NoMatch;
2782
2783 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2784 // basepri, basepri_max and faultmask only valid for V7m.
2785 return MatchOperand_NoMatch;
2786
2787 Parser.Lex(); // Eat identifier token.
2788 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2789 return MatchOperand_Success;
2790 }
2791
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002792 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2793 size_t Start = 0, Next = Mask.find('_');
2794 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002795 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002796 if (Next != StringRef::npos)
2797 Flags = Mask.slice(Next+1, Mask.size());
2798
2799 // FlagsVal contains the complete mask:
2800 // 3-0: Mask
2801 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2802 unsigned FlagsVal = 0;
2803
2804 if (SpecReg == "apsr") {
2805 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002806 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002807 .Case("g", 0x4) // same as CPSR_s
2808 .Case("nzcvqg", 0xc) // same as CPSR_fs
2809 .Default(~0U);
2810
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002811 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002812 if (!Flags.empty())
2813 return MatchOperand_NoMatch;
2814 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002815 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002816 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002817 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002818 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2819 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002820 for (int i = 0, e = Flags.size(); i != e; ++i) {
2821 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2822 .Case("c", 1)
2823 .Case("x", 2)
2824 .Case("s", 4)
2825 .Case("f", 8)
2826 .Default(~0U);
2827
2828 // If some specific flag is already set, it means that some letter is
2829 // present more than once, this is not acceptable.
2830 if (FlagsVal == ~0U || (FlagsVal & Flag))
2831 return MatchOperand_NoMatch;
2832 FlagsVal |= Flag;
2833 }
2834 } else // No match for special register.
2835 return MatchOperand_NoMatch;
2836
Owen Anderson7784f1d2011-10-21 18:43:28 +00002837 // Special register without flags is NOT equivalent to "fc" flags.
2838 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2839 // two lines would enable gas compatibility at the expense of breaking
2840 // round-tripping.
2841 //
2842 // if (!FlagsVal)
2843 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002844
2845 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2846 if (SpecReg == "spsr")
2847 FlagsVal |= 16;
2848
2849 Parser.Lex(); // Eat identifier token.
2850 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2851 return MatchOperand_Success;
2852}
2853
Jim Grosbachf6c05252011-07-21 17:23:04 +00002854ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2855parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2856 int Low, int High) {
2857 const AsmToken &Tok = Parser.getTok();
2858 if (Tok.isNot(AsmToken::Identifier)) {
2859 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2860 return MatchOperand_ParseFail;
2861 }
2862 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002863 std::string LowerOp = Op.lower();
2864 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002865 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2866 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2867 return MatchOperand_ParseFail;
2868 }
2869 Parser.Lex(); // Eat shift type token.
2870
2871 // There must be a '#' and a shift amount.
2872 if (Parser.getTok().isNot(AsmToken::Hash)) {
2873 Error(Parser.getTok().getLoc(), "'#' expected");
2874 return MatchOperand_ParseFail;
2875 }
2876 Parser.Lex(); // Eat hash token.
2877
2878 const MCExpr *ShiftAmount;
2879 SMLoc Loc = Parser.getTok().getLoc();
2880 if (getParser().ParseExpression(ShiftAmount)) {
2881 Error(Loc, "illegal expression");
2882 return MatchOperand_ParseFail;
2883 }
2884 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2885 if (!CE) {
2886 Error(Loc, "constant expression expected");
2887 return MatchOperand_ParseFail;
2888 }
2889 int Val = CE->getValue();
2890 if (Val < Low || Val > High) {
2891 Error(Loc, "immediate value out of range");
2892 return MatchOperand_ParseFail;
2893 }
2894
2895 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2896
2897 return MatchOperand_Success;
2898}
2899
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002900ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2901parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2902 const AsmToken &Tok = Parser.getTok();
2903 SMLoc S = Tok.getLoc();
2904 if (Tok.isNot(AsmToken::Identifier)) {
2905 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2906 return MatchOperand_ParseFail;
2907 }
2908 int Val = StringSwitch<int>(Tok.getString())
2909 .Case("be", 1)
2910 .Case("le", 0)
2911 .Default(-1);
2912 Parser.Lex(); // Eat the token.
2913
2914 if (Val == -1) {
2915 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2916 return MatchOperand_ParseFail;
2917 }
2918 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2919 getContext()),
2920 S, Parser.getTok().getLoc()));
2921 return MatchOperand_Success;
2922}
2923
Jim Grosbach580f4a92011-07-25 22:20:28 +00002924/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2925/// instructions. Legal values are:
2926/// lsl #n 'n' in [0,31]
2927/// asr #n 'n' in [1,32]
2928/// n == 32 encoded as n == 0.
2929ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2930parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2931 const AsmToken &Tok = Parser.getTok();
2932 SMLoc S = Tok.getLoc();
2933 if (Tok.isNot(AsmToken::Identifier)) {
2934 Error(S, "shift operator 'asr' or 'lsl' expected");
2935 return MatchOperand_ParseFail;
2936 }
2937 StringRef ShiftName = Tok.getString();
2938 bool isASR;
2939 if (ShiftName == "lsl" || ShiftName == "LSL")
2940 isASR = false;
2941 else if (ShiftName == "asr" || ShiftName == "ASR")
2942 isASR = true;
2943 else {
2944 Error(S, "shift operator 'asr' or 'lsl' expected");
2945 return MatchOperand_ParseFail;
2946 }
2947 Parser.Lex(); // Eat the operator.
2948
2949 // A '#' and a shift amount.
2950 if (Parser.getTok().isNot(AsmToken::Hash)) {
2951 Error(Parser.getTok().getLoc(), "'#' expected");
2952 return MatchOperand_ParseFail;
2953 }
2954 Parser.Lex(); // Eat hash token.
2955
2956 const MCExpr *ShiftAmount;
2957 SMLoc E = Parser.getTok().getLoc();
2958 if (getParser().ParseExpression(ShiftAmount)) {
2959 Error(E, "malformed shift expression");
2960 return MatchOperand_ParseFail;
2961 }
2962 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2963 if (!CE) {
2964 Error(E, "shift amount must be an immediate");
2965 return MatchOperand_ParseFail;
2966 }
2967
2968 int64_t Val = CE->getValue();
2969 if (isASR) {
2970 // Shift amount must be in [1,32]
2971 if (Val < 1 || Val > 32) {
2972 Error(E, "'asr' shift amount must be in range [1,32]");
2973 return MatchOperand_ParseFail;
2974 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002975 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2976 if (isThumb() && Val == 32) {
2977 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2978 return MatchOperand_ParseFail;
2979 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002980 if (Val == 32) Val = 0;
2981 } else {
2982 // Shift amount must be in [1,32]
2983 if (Val < 0 || Val > 31) {
2984 Error(E, "'lsr' shift amount must be in range [0,31]");
2985 return MatchOperand_ParseFail;
2986 }
2987 }
2988
2989 E = Parser.getTok().getLoc();
2990 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2991
2992 return MatchOperand_Success;
2993}
2994
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002995/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
2996/// of instructions. Legal values are:
2997/// ror #n 'n' in {0, 8, 16, 24}
2998ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2999parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3000 const AsmToken &Tok = Parser.getTok();
3001 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003002 if (Tok.isNot(AsmToken::Identifier))
3003 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003004 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003005 if (ShiftName != "ror" && ShiftName != "ROR")
3006 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003007 Parser.Lex(); // Eat the operator.
3008
3009 // A '#' and a rotate amount.
3010 if (Parser.getTok().isNot(AsmToken::Hash)) {
3011 Error(Parser.getTok().getLoc(), "'#' expected");
3012 return MatchOperand_ParseFail;
3013 }
3014 Parser.Lex(); // Eat hash token.
3015
3016 const MCExpr *ShiftAmount;
3017 SMLoc E = Parser.getTok().getLoc();
3018 if (getParser().ParseExpression(ShiftAmount)) {
3019 Error(E, "malformed rotate expression");
3020 return MatchOperand_ParseFail;
3021 }
3022 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3023 if (!CE) {
3024 Error(E, "rotate amount must be an immediate");
3025 return MatchOperand_ParseFail;
3026 }
3027
3028 int64_t Val = CE->getValue();
3029 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3030 // normally, zero is represented in asm by omitting the rotate operand
3031 // entirely.
3032 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3033 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3034 return MatchOperand_ParseFail;
3035 }
3036
3037 E = Parser.getTok().getLoc();
3038 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3039
3040 return MatchOperand_Success;
3041}
3042
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003043ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3044parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3045 SMLoc S = Parser.getTok().getLoc();
3046 // The bitfield descriptor is really two operands, the LSB and the width.
3047 if (Parser.getTok().isNot(AsmToken::Hash)) {
3048 Error(Parser.getTok().getLoc(), "'#' expected");
3049 return MatchOperand_ParseFail;
3050 }
3051 Parser.Lex(); // Eat hash token.
3052
3053 const MCExpr *LSBExpr;
3054 SMLoc E = Parser.getTok().getLoc();
3055 if (getParser().ParseExpression(LSBExpr)) {
3056 Error(E, "malformed immediate expression");
3057 return MatchOperand_ParseFail;
3058 }
3059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3060 if (!CE) {
3061 Error(E, "'lsb' operand must be an immediate");
3062 return MatchOperand_ParseFail;
3063 }
3064
3065 int64_t LSB = CE->getValue();
3066 // The LSB must be in the range [0,31]
3067 if (LSB < 0 || LSB > 31) {
3068 Error(E, "'lsb' operand must be in the range [0,31]");
3069 return MatchOperand_ParseFail;
3070 }
3071 E = Parser.getTok().getLoc();
3072
3073 // Expect another immediate operand.
3074 if (Parser.getTok().isNot(AsmToken::Comma)) {
3075 Error(Parser.getTok().getLoc(), "too few operands");
3076 return MatchOperand_ParseFail;
3077 }
3078 Parser.Lex(); // Eat hash token.
3079 if (Parser.getTok().isNot(AsmToken::Hash)) {
3080 Error(Parser.getTok().getLoc(), "'#' expected");
3081 return MatchOperand_ParseFail;
3082 }
3083 Parser.Lex(); // Eat hash token.
3084
3085 const MCExpr *WidthExpr;
3086 if (getParser().ParseExpression(WidthExpr)) {
3087 Error(E, "malformed immediate expression");
3088 return MatchOperand_ParseFail;
3089 }
3090 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3091 if (!CE) {
3092 Error(E, "'width' operand must be an immediate");
3093 return MatchOperand_ParseFail;
3094 }
3095
3096 int64_t Width = CE->getValue();
3097 // The LSB must be in the range [1,32-lsb]
3098 if (Width < 1 || Width > 32 - LSB) {
3099 Error(E, "'width' operand must be in the range [1,32-lsb]");
3100 return MatchOperand_ParseFail;
3101 }
3102 E = Parser.getTok().getLoc();
3103
3104 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3105
3106 return MatchOperand_Success;
3107}
3108
Jim Grosbach7ce05792011-08-03 23:50:40 +00003109ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3110parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3111 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003112 // postidx_reg := '+' register {, shift}
3113 // | '-' register {, shift}
3114 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003115
3116 // This method must return MatchOperand_NoMatch without consuming any tokens
3117 // in the case where there is no match, as other alternatives take other
3118 // parse methods.
3119 AsmToken Tok = Parser.getTok();
3120 SMLoc S = Tok.getLoc();
3121 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003122 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003123 int Reg = -1;
3124 if (Tok.is(AsmToken::Plus)) {
3125 Parser.Lex(); // Eat the '+' token.
3126 haveEaten = true;
3127 } else if (Tok.is(AsmToken::Minus)) {
3128 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003129 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003130 haveEaten = true;
3131 }
3132 if (Parser.getTok().is(AsmToken::Identifier))
3133 Reg = tryParseRegister();
3134 if (Reg == -1) {
3135 if (!haveEaten)
3136 return MatchOperand_NoMatch;
3137 Error(Parser.getTok().getLoc(), "register expected");
3138 return MatchOperand_ParseFail;
3139 }
3140 SMLoc E = Parser.getTok().getLoc();
3141
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003142 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3143 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003144 if (Parser.getTok().is(AsmToken::Comma)) {
3145 Parser.Lex(); // Eat the ','.
3146 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3147 return MatchOperand_ParseFail;
3148 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003149
3150 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3151 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003152
3153 return MatchOperand_Success;
3154}
3155
Jim Grosbach251bf252011-08-10 21:56:18 +00003156ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3157parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3158 // Check for a post-index addressing register operand. Specifically:
3159 // am3offset := '+' register
3160 // | '-' register
3161 // | register
3162 // | # imm
3163 // | # + imm
3164 // | # - imm
3165
3166 // This method must return MatchOperand_NoMatch without consuming any tokens
3167 // in the case where there is no match, as other alternatives take other
3168 // parse methods.
3169 AsmToken Tok = Parser.getTok();
3170 SMLoc S = Tok.getLoc();
3171
3172 // Do immediates first, as we always parse those if we have a '#'.
3173 if (Parser.getTok().is(AsmToken::Hash)) {
3174 Parser.Lex(); // Eat the '#'.
3175 // Explicitly look for a '-', as we need to encode negative zero
3176 // differently.
3177 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3178 const MCExpr *Offset;
3179 if (getParser().ParseExpression(Offset))
3180 return MatchOperand_ParseFail;
3181 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3182 if (!CE) {
3183 Error(S, "constant expression expected");
3184 return MatchOperand_ParseFail;
3185 }
3186 SMLoc E = Tok.getLoc();
3187 // Negative zero is encoded as the flag value INT32_MIN.
3188 int32_t Val = CE->getValue();
3189 if (isNegative && Val == 0)
3190 Val = INT32_MIN;
3191
3192 Operands.push_back(
3193 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3194
3195 return MatchOperand_Success;
3196 }
3197
3198
3199 bool haveEaten = false;
3200 bool isAdd = true;
3201 int Reg = -1;
3202 if (Tok.is(AsmToken::Plus)) {
3203 Parser.Lex(); // Eat the '+' token.
3204 haveEaten = true;
3205 } else if (Tok.is(AsmToken::Minus)) {
3206 Parser.Lex(); // Eat the '-' token.
3207 isAdd = false;
3208 haveEaten = true;
3209 }
3210 if (Parser.getTok().is(AsmToken::Identifier))
3211 Reg = tryParseRegister();
3212 if (Reg == -1) {
3213 if (!haveEaten)
3214 return MatchOperand_NoMatch;
3215 Error(Parser.getTok().getLoc(), "register expected");
3216 return MatchOperand_ParseFail;
3217 }
3218 SMLoc E = Parser.getTok().getLoc();
3219
3220 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3221 0, S, E));
3222
3223 return MatchOperand_Success;
3224}
3225
Jim Grosbacha77295d2011-09-08 22:07:06 +00003226/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3227/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3228/// when they refer multiple MIOperands inside a single one.
3229bool ARMAsmParser::
3230cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3231 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3232 // Rt, Rt2
3233 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3234 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3235 // Create a writeback register dummy placeholder.
3236 Inst.addOperand(MCOperand::CreateReg(0));
3237 // addr
3238 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3239 // pred
3240 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3241 return true;
3242}
3243
3244/// cvtT2StrdPre - Convert parsed operands to MCInst.
3245/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3246/// when they refer multiple MIOperands inside a single one.
3247bool ARMAsmParser::
3248cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3249 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3250 // Create a writeback register dummy placeholder.
3251 Inst.addOperand(MCOperand::CreateReg(0));
3252 // Rt, Rt2
3253 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3254 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3255 // addr
3256 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3257 // pred
3258 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3259 return true;
3260}
3261
Jim Grosbacheeec0252011-09-08 00:39:19 +00003262/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3263/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3264/// when they refer multiple MIOperands inside a single one.
3265bool ARMAsmParser::
3266cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3267 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3268 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3269
3270 // Create a writeback register dummy placeholder.
3271 Inst.addOperand(MCOperand::CreateImm(0));
3272
3273 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3274 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3275 return true;
3276}
3277
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003278/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3279/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3280/// when they refer multiple MIOperands inside a single one.
3281bool ARMAsmParser::
3282cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3283 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3284 // Create a writeback register dummy placeholder.
3285 Inst.addOperand(MCOperand::CreateImm(0));
3286 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3287 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3288 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3289 return true;
3290}
3291
Jim Grosbach1355cf12011-07-26 17:10:22 +00003292/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003293/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3294/// when they refer multiple MIOperands inside a single one.
3295bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003296cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003297 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3298 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3299
3300 // Create a writeback register dummy placeholder.
3301 Inst.addOperand(MCOperand::CreateImm(0));
3302
Jim Grosbach7ce05792011-08-03 23:50:40 +00003303 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003304 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3305 return true;
3306}
3307
Owen Anderson9ab0f252011-08-26 20:43:14 +00003308/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3309/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3310/// when they refer multiple MIOperands inside a single one.
3311bool ARMAsmParser::
3312cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3313 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3314 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3315
3316 // Create a writeback register dummy placeholder.
3317 Inst.addOperand(MCOperand::CreateImm(0));
3318
3319 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3320 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3321 return true;
3322}
3323
3324
Jim Grosbach548340c2011-08-11 19:22:40 +00003325/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3326/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3327/// when they refer multiple MIOperands inside a single one.
3328bool ARMAsmParser::
3329cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3330 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3331 // Create a writeback register dummy placeholder.
3332 Inst.addOperand(MCOperand::CreateImm(0));
3333 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3334 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3335 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3336 return true;
3337}
3338
Jim Grosbach1355cf12011-07-26 17:10:22 +00003339/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003340/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3341/// when they refer multiple MIOperands inside a single one.
3342bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003343cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003344 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3345 // Create a writeback register dummy placeholder.
3346 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003347 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3348 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3349 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003350 return true;
3351}
3352
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003353/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3354/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3355/// when they refer multiple MIOperands inside a single one.
3356bool ARMAsmParser::
3357cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3358 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3359 // Create a writeback register dummy placeholder.
3360 Inst.addOperand(MCOperand::CreateImm(0));
3361 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3362 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3363 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3364 return true;
3365}
3366
Jim Grosbach7ce05792011-08-03 23:50:40 +00003367/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3368/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3369/// when they refer multiple MIOperands inside a single one.
3370bool ARMAsmParser::
3371cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3372 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3373 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003374 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003375 // Create a writeback register dummy placeholder.
3376 Inst.addOperand(MCOperand::CreateImm(0));
3377 // addr
3378 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3379 // offset
3380 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3381 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003382 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3383 return true;
3384}
3385
Jim Grosbach7ce05792011-08-03 23:50:40 +00003386/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003387/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3388/// when they refer multiple MIOperands inside a single one.
3389bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003390cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3391 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3392 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003393 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003394 // Create a writeback register dummy placeholder.
3395 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003396 // addr
3397 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3398 // offset
3399 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3400 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003401 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3402 return true;
3403}
3404
Jim Grosbach7ce05792011-08-03 23:50:40 +00003405/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003406/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3407/// when they refer multiple MIOperands inside a single one.
3408bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003409cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3410 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003411 // Create a writeback register dummy placeholder.
3412 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003413 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003414 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003415 // addr
3416 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3417 // offset
3418 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3419 // pred
3420 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3421 return true;
3422}
3423
3424/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3425/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3426/// when they refer multiple MIOperands inside a single one.
3427bool ARMAsmParser::
3428cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3429 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3430 // Create a writeback register dummy placeholder.
3431 Inst.addOperand(MCOperand::CreateImm(0));
3432 // Rt
3433 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3434 // addr
3435 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3436 // offset
3437 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3438 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003439 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3440 return true;
3441}
3442
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003443/// cvtLdrdPre - Convert parsed operands to MCInst.
3444/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3445/// when they refer multiple MIOperands inside a single one.
3446bool ARMAsmParser::
3447cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3448 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3449 // Rt, Rt2
3450 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3451 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3452 // Create a writeback register dummy placeholder.
3453 Inst.addOperand(MCOperand::CreateImm(0));
3454 // addr
3455 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3456 // pred
3457 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3458 return true;
3459}
3460
Jim Grosbach14605d12011-08-11 20:28:23 +00003461/// cvtStrdPre - Convert parsed operands to MCInst.
3462/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3463/// when they refer multiple MIOperands inside a single one.
3464bool ARMAsmParser::
3465cvtStrdPre(MCInst &Inst, unsigned Opcode,
3466 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3467 // Create a writeback register dummy placeholder.
3468 Inst.addOperand(MCOperand::CreateImm(0));
3469 // Rt, Rt2
3470 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3471 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3472 // addr
3473 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3474 // pred
3475 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3476 return true;
3477}
3478
Jim Grosbach623a4542011-08-10 22:42:16 +00003479/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3480/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3481/// when they refer multiple MIOperands inside a single one.
3482bool ARMAsmParser::
3483cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3484 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3485 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3486 // Create a writeback register dummy placeholder.
3487 Inst.addOperand(MCOperand::CreateImm(0));
3488 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3489 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3490 return true;
3491}
3492
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003493/// cvtThumbMultiple- Convert parsed operands to MCInst.
3494/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3495/// when they refer multiple MIOperands inside a single one.
3496bool ARMAsmParser::
3497cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3498 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3499 // The second source operand must be the same register as the destination
3500 // operand.
3501 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003502 (((ARMOperand*)Operands[3])->getReg() !=
3503 ((ARMOperand*)Operands[5])->getReg()) &&
3504 (((ARMOperand*)Operands[3])->getReg() !=
3505 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003506 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003507 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003508 return false;
3509 }
3510 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3511 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003512 // If we have a three-operand form, make sure to set Rn to be the operand
3513 // that isn't the same as Rd.
3514 unsigned RegOp = 4;
3515 if (Operands.size() == 6 &&
3516 ((ARMOperand*)Operands[4])->getReg() ==
3517 ((ARMOperand*)Operands[3])->getReg())
3518 RegOp = 5;
3519 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3520 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003521 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3522
3523 return true;
3524}
Jim Grosbach623a4542011-08-10 22:42:16 +00003525
Jim Grosbach12431322011-10-24 22:16:58 +00003526bool ARMAsmParser::
3527cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3528 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3529 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003530 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003531 // Create a writeback register dummy placeholder.
3532 Inst.addOperand(MCOperand::CreateImm(0));
3533 // Vn
3534 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3535 // pred
3536 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3537 return true;
3538}
3539
3540bool ARMAsmParser::
3541cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3542 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3543 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003544 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003545 // Create a writeback register dummy placeholder.
3546 Inst.addOperand(MCOperand::CreateImm(0));
3547 // Vn
3548 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3549 // Vm
3550 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3551 // pred
3552 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3553 return true;
3554}
3555
Jim Grosbach4334e032011-10-31 21:50:31 +00003556bool ARMAsmParser::
3557cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3558 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3559 // Create a writeback register dummy placeholder.
3560 Inst.addOperand(MCOperand::CreateImm(0));
3561 // Vn
3562 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3563 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003564 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003565 // pred
3566 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3567 return true;
3568}
3569
3570bool ARMAsmParser::
3571cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3572 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3573 // Create a writeback register dummy placeholder.
3574 Inst.addOperand(MCOperand::CreateImm(0));
3575 // Vn
3576 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3577 // Vm
3578 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3579 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003580 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003581 // pred
3582 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3583 return true;
3584}
3585
Bill Wendlinge7176102010-11-06 22:36:58 +00003586/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003587/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003588bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003589parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003590 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003591 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003592 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003593 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003594 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003595
Sean Callanan18b83232010-01-19 21:44:56 +00003596 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003597 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003598 if (BaseRegNum == -1)
3599 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003600
Daniel Dunbar05710932011-01-18 05:34:17 +00003601 // The next token must either be a comma or a closing bracket.
3602 const AsmToken &Tok = Parser.getTok();
3603 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003604 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003605
Jim Grosbach7ce05792011-08-03 23:50:40 +00003606 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003607 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003608 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003609
Jim Grosbach7ce05792011-08-03 23:50:40 +00003610 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003611 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003612
Jim Grosbachfb12f352011-09-19 18:42:21 +00003613 // If there's a pre-indexing writeback marker, '!', just add it as a token
3614 // operand. It's rather odd, but syntactically valid.
3615 if (Parser.getTok().is(AsmToken::Exclaim)) {
3616 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3617 Parser.Lex(); // Eat the '!'.
3618 }
3619
Jim Grosbach7ce05792011-08-03 23:50:40 +00003620 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003621 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003622
Jim Grosbach7ce05792011-08-03 23:50:40 +00003623 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3624 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003625
Jim Grosbach57dcb852011-10-11 17:29:55 +00003626 // If we have a ':', it's an alignment specifier.
3627 if (Parser.getTok().is(AsmToken::Colon)) {
3628 Parser.Lex(); // Eat the ':'.
3629 E = Parser.getTok().getLoc();
3630
3631 const MCExpr *Expr;
3632 if (getParser().ParseExpression(Expr))
3633 return true;
3634
3635 // The expression has to be a constant. Memory references with relocations
3636 // don't come through here, as they use the <label> forms of the relevant
3637 // instructions.
3638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3639 if (!CE)
3640 return Error (E, "constant expression expected");
3641
3642 unsigned Align = 0;
3643 switch (CE->getValue()) {
3644 default:
3645 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3646 case 64: Align = 8; break;
3647 case 128: Align = 16; break;
3648 case 256: Align = 32; break;
3649 }
3650
3651 // Now we should have the closing ']'
3652 E = Parser.getTok().getLoc();
3653 if (Parser.getTok().isNot(AsmToken::RBrac))
3654 return Error(E, "']' expected");
3655 Parser.Lex(); // Eat right bracket token.
3656
3657 // Don't worry about range checking the value here. That's handled by
3658 // the is*() predicates.
3659 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3660 ARM_AM::no_shift, 0, Align,
3661 false, S, E));
3662
3663 // If there's a pre-indexing writeback marker, '!', just add it as a token
3664 // operand.
3665 if (Parser.getTok().is(AsmToken::Exclaim)) {
3666 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3667 Parser.Lex(); // Eat the '!'.
3668 }
3669
3670 return false;
3671 }
3672
3673 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003674 // offset. Be friendly and also accept a plain integer (without a leading
3675 // hash) for gas compatibility.
3676 if (Parser.getTok().is(AsmToken::Hash) ||
3677 Parser.getTok().is(AsmToken::Integer)) {
3678 if (Parser.getTok().is(AsmToken::Hash))
3679 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003680 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003681
Owen Anderson0da10cf2011-08-29 19:36:44 +00003682 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003683 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003684 if (getParser().ParseExpression(Offset))
3685 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003686
3687 // The expression has to be a constant. Memory references with relocations
3688 // don't come through here, as they use the <label> forms of the relevant
3689 // instructions.
3690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3691 if (!CE)
3692 return Error (E, "constant expression expected");
3693
Owen Anderson0da10cf2011-08-29 19:36:44 +00003694 // If the constant was #-0, represent it as INT32_MIN.
3695 int32_t Val = CE->getValue();
3696 if (isNegative && Val == 0)
3697 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3698
Jim Grosbach7ce05792011-08-03 23:50:40 +00003699 // Now we should have the closing ']'
3700 E = Parser.getTok().getLoc();
3701 if (Parser.getTok().isNot(AsmToken::RBrac))
3702 return Error(E, "']' expected");
3703 Parser.Lex(); // Eat right bracket token.
3704
3705 // Don't worry about range checking the value here. That's handled by
3706 // the is*() predicates.
3707 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003708 ARM_AM::no_shift, 0, 0,
3709 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003710
3711 // If there's a pre-indexing writeback marker, '!', just add it as a token
3712 // operand.
3713 if (Parser.getTok().is(AsmToken::Exclaim)) {
3714 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3715 Parser.Lex(); // Eat the '!'.
3716 }
3717
3718 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003719 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003720
3721 // The register offset is optionally preceded by a '+' or '-'
3722 bool isNegative = false;
3723 if (Parser.getTok().is(AsmToken::Minus)) {
3724 isNegative = true;
3725 Parser.Lex(); // Eat the '-'.
3726 } else if (Parser.getTok().is(AsmToken::Plus)) {
3727 // Nothing to do.
3728 Parser.Lex(); // Eat the '+'.
3729 }
3730
3731 E = Parser.getTok().getLoc();
3732 int OffsetRegNum = tryParseRegister();
3733 if (OffsetRegNum == -1)
3734 return Error(E, "register expected");
3735
3736 // If there's a shift operator, handle it.
3737 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003738 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003739 if (Parser.getTok().is(AsmToken::Comma)) {
3740 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003741 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003742 return true;
3743 }
3744
3745 // Now we should have the closing ']'
3746 E = Parser.getTok().getLoc();
3747 if (Parser.getTok().isNot(AsmToken::RBrac))
3748 return Error(E, "']' expected");
3749 Parser.Lex(); // Eat right bracket token.
3750
3751 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003752 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003753 S, E));
3754
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003755 // If there's a pre-indexing writeback marker, '!', just add it as a token
3756 // operand.
3757 if (Parser.getTok().is(AsmToken::Exclaim)) {
3758 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3759 Parser.Lex(); // Eat the '!'.
3760 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003761
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003762 return false;
3763}
3764
Jim Grosbach7ce05792011-08-03 23:50:40 +00003765/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003766/// ( lsl | lsr | asr | ror ) , # shift_amount
3767/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003768/// return true if it parses a shift otherwise it returns false.
3769bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3770 unsigned &Amount) {
3771 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003772 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003773 if (Tok.isNot(AsmToken::Identifier))
3774 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003775 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003776 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003777 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003778 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003779 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003780 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003781 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003782 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003783 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003784 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003785 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003786 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003787 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003788 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003789
Jim Grosbach7ce05792011-08-03 23:50:40 +00003790 // rrx stands alone.
3791 Amount = 0;
3792 if (St != ARM_AM::rrx) {
3793 Loc = Parser.getTok().getLoc();
3794 // A '#' and a shift amount.
3795 const AsmToken &HashTok = Parser.getTok();
3796 if (HashTok.isNot(AsmToken::Hash))
3797 return Error(HashTok.getLoc(), "'#' expected");
3798 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003799
Jim Grosbach7ce05792011-08-03 23:50:40 +00003800 const MCExpr *Expr;
3801 if (getParser().ParseExpression(Expr))
3802 return true;
3803 // Range check the immediate.
3804 // lsl, ror: 0 <= imm <= 31
3805 // lsr, asr: 0 <= imm <= 32
3806 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3807 if (!CE)
3808 return Error(Loc, "shift amount must be an immediate");
3809 int64_t Imm = CE->getValue();
3810 if (Imm < 0 ||
3811 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3812 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3813 return Error(Loc, "immediate shift value out of range");
3814 Amount = Imm;
3815 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003816
3817 return false;
3818}
3819
Jim Grosbach9d390362011-10-03 23:38:36 +00003820/// parseFPImm - A floating point immediate expression operand.
3821ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3822parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3823 SMLoc S = Parser.getTok().getLoc();
3824
3825 if (Parser.getTok().isNot(AsmToken::Hash))
3826 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003827
3828 // Disambiguate the VMOV forms that can accept an FP immediate.
3829 // vmov.f32 <sreg>, #imm
3830 // vmov.f64 <dreg>, #imm
3831 // vmov.f32 <dreg>, #imm @ vector f32x2
3832 // vmov.f32 <qreg>, #imm @ vector f32x4
3833 //
3834 // There are also the NEON VMOV instructions which expect an
3835 // integer constant. Make sure we don't try to parse an FPImm
3836 // for these:
3837 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3838 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3839 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3840 TyOp->getToken() != ".f64"))
3841 return MatchOperand_NoMatch;
3842
Jim Grosbach9d390362011-10-03 23:38:36 +00003843 Parser.Lex(); // Eat the '#'.
3844
3845 // Handle negation, as that still comes through as a separate token.
3846 bool isNegative = false;
3847 if (Parser.getTok().is(AsmToken::Minus)) {
3848 isNegative = true;
3849 Parser.Lex();
3850 }
3851 const AsmToken &Tok = Parser.getTok();
3852 if (Tok.is(AsmToken::Real)) {
3853 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3854 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3855 // If we had a '-' in front, toggle the sign bit.
3856 IntVal ^= (uint64_t)isNegative << 63;
3857 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3858 Parser.Lex(); // Eat the token.
3859 if (Val == -1) {
3860 TokError("floating point value out of range");
3861 return MatchOperand_ParseFail;
3862 }
3863 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3864 return MatchOperand_Success;
3865 }
3866 if (Tok.is(AsmToken::Integer)) {
3867 int64_t Val = Tok.getIntVal();
3868 Parser.Lex(); // Eat the token.
3869 if (Val > 255 || Val < 0) {
3870 TokError("encoded floating point value out of range");
3871 return MatchOperand_ParseFail;
3872 }
3873 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3874 return MatchOperand_Success;
3875 }
3876
3877 TokError("invalid floating point immediate");
3878 return MatchOperand_ParseFail;
3879}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003880/// Parse a arm instruction operand. For now this parses the operand regardless
3881/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003882bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003883 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003884 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003885
3886 // Check if the current operand has a custom associated parser, if so, try to
3887 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003888 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3889 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003890 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003891 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3892 // there was a match, but an error occurred, in which case, just return that
3893 // the operand parsing failed.
3894 if (ResTy == MatchOperand_ParseFail)
3895 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003896
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003897 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003898 default:
3899 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003900 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003901 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003902 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003903 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003904 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003905 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003906 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003907 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003908 else if (Res == -1) // irrecoverable error
3909 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003910 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3911 S = Parser.getTok().getLoc();
3912 Parser.Lex();
3913 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3914 return false;
3915 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003916
3917 // Fall though for the Identifier case that is not a register or a
3918 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003919 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003920 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003921 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003922 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003923 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003924 // This was not a register so parse other operands that start with an
3925 // identifier (like labels) as expressions and create them as immediates.
3926 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003927 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003928 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003929 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003930 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003931 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3932 return false;
3933 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003934 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003935 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003936 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003937 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003938 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003939 // #42 -> immediate.
3940 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003941 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003942 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003943 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003944 const MCExpr *ImmVal;
3945 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003946 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003947 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003948 if (CE) {
3949 int32_t Val = CE->getValue();
3950 if (isNegative && Val == 0)
3951 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003952 }
Sean Callanan76264762010-04-02 22:27:05 +00003953 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003954 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3955 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003956 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003957 case AsmToken::Colon: {
3958 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003959 // FIXME: Check it's an expression prefix,
3960 // e.g. (FOO - :lower16:BAR) isn't legal.
3961 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003962 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003963 return true;
3964
Evan Cheng75972122011-01-13 07:58:56 +00003965 const MCExpr *SubExprVal;
3966 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003967 return true;
3968
Evan Cheng75972122011-01-13 07:58:56 +00003969 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3970 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003971 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003972 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003973 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003974 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003975 }
3976}
3977
Jim Grosbach1355cf12011-07-26 17:10:22 +00003978// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003979// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003980bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003981 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003982
3983 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003984 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003985 Parser.Lex(); // Eat ':'
3986
3987 if (getLexer().isNot(AsmToken::Identifier)) {
3988 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3989 return true;
3990 }
3991
3992 StringRef IDVal = Parser.getTok().getIdentifier();
3993 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003994 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003995 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00003996 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003997 } else {
3998 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
3999 return true;
4000 }
4001 Parser.Lex();
4002
4003 if (getLexer().isNot(AsmToken::Colon)) {
4004 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4005 return true;
4006 }
4007 Parser.Lex(); // Eat the last ':'
4008 return false;
4009}
4010
Daniel Dunbar352e1482011-01-11 15:59:50 +00004011/// \brief Given a mnemonic, split out possible predication code and carry
4012/// setting letters to form a canonical mnemonic and flags.
4013//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004014// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004015// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004016StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004017 unsigned &PredicationCode,
4018 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004019 unsigned &ProcessorIMod,
4020 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004021 PredicationCode = ARMCC::AL;
4022 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004023 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004024
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004025 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004026 //
4027 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004028 if ((Mnemonic == "movs" && isThumb()) ||
4029 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4030 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4031 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4032 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4033 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4034 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4035 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004036 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004037
Jim Grosbach3f00e312011-07-11 17:09:57 +00004038 // First, split out any predication code. Ignore mnemonics we know aren't
4039 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004040 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004041 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004042 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004043 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004044 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4045 .Case("eq", ARMCC::EQ)
4046 .Case("ne", ARMCC::NE)
4047 .Case("hs", ARMCC::HS)
4048 .Case("cs", ARMCC::HS)
4049 .Case("lo", ARMCC::LO)
4050 .Case("cc", ARMCC::LO)
4051 .Case("mi", ARMCC::MI)
4052 .Case("pl", ARMCC::PL)
4053 .Case("vs", ARMCC::VS)
4054 .Case("vc", ARMCC::VC)
4055 .Case("hi", ARMCC::HI)
4056 .Case("ls", ARMCC::LS)
4057 .Case("ge", ARMCC::GE)
4058 .Case("lt", ARMCC::LT)
4059 .Case("gt", ARMCC::GT)
4060 .Case("le", ARMCC::LE)
4061 .Case("al", ARMCC::AL)
4062 .Default(~0U);
4063 if (CC != ~0U) {
4064 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4065 PredicationCode = CC;
4066 }
Bill Wendling52925b62010-10-29 23:50:21 +00004067 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004068
Daniel Dunbar352e1482011-01-11 15:59:50 +00004069 // Next, determine if we have a carry setting bit. We explicitly ignore all
4070 // the instructions we know end in 's'.
4071 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004072 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004073 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4074 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4075 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004076 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
4077 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004078 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4079 CarrySetting = true;
4080 }
4081
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004082 // The "cps" instruction can have a interrupt mode operand which is glued into
4083 // the mnemonic. Check if this is the case, split it and parse the imod op
4084 if (Mnemonic.startswith("cps")) {
4085 // Split out any imod code.
4086 unsigned IMod =
4087 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4088 .Case("ie", ARM_PROC::IE)
4089 .Case("id", ARM_PROC::ID)
4090 .Default(~0U);
4091 if (IMod != ~0U) {
4092 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4093 ProcessorIMod = IMod;
4094 }
4095 }
4096
Jim Grosbach89df9962011-08-26 21:43:41 +00004097 // The "it" instruction has the condition mask on the end of the mnemonic.
4098 if (Mnemonic.startswith("it")) {
4099 ITMask = Mnemonic.slice(2, Mnemonic.size());
4100 Mnemonic = Mnemonic.slice(0, 2);
4101 }
4102
Daniel Dunbar352e1482011-01-11 15:59:50 +00004103 return Mnemonic;
4104}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004105
4106/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4107/// inclusion of carry set or predication code operands.
4108//
4109// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004110void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004111getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004112 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004113 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4114 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004115 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004116 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004117 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004118 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004119 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004120 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004121 Mnemonic == "mla" || Mnemonic == "smlal" ||
4122 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004123 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004124 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004125 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004126
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004127 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4128 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4129 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4130 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004131 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4132 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004133 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004134 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4135 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4136 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004137 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4138 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004139 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004140 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004141 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004142 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004143
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004144 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004145 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004146 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004147 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004148 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004149}
4150
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004151bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4152 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004153 // FIXME: This is all horribly hacky. We really need a better way to deal
4154 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004155
4156 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4157 // another does not. Specifically, the MOVW instruction does not. So we
4158 // special case it here and remove the defaulted (non-setting) cc_out
4159 // operand if that's the instruction we're trying to match.
4160 //
4161 // We do this as post-processing of the explicit operands rather than just
4162 // conditionally adding the cc_out in the first place because we need
4163 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004164 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004165 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4166 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4167 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4168 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004169
4170 // Register-register 'add' for thumb does not have a cc_out operand
4171 // when there are only two register operands.
4172 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4173 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4174 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4175 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4176 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004177 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004178 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4179 // have to check the immediate range here since Thumb2 has a variant
4180 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004181 if (((isThumb() && Mnemonic == "add") ||
4182 (isThumbTwo() && Mnemonic == "sub")) &&
4183 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004184 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4185 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4186 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004187 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4188 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4189 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004190 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004191 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4192 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004193 // selecting via the generic "add" mnemonic, so to know that we
4194 // should remove the cc_out operand, we have to explicitly check that
4195 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004196 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4197 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004198 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4199 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4200 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4201 // Nest conditions rather than one big 'if' statement for readability.
4202 //
4203 // If either register is a high reg, it's either one of the SP
4204 // variants (handled above) or a 32-bit encoding, so we just
4205 // check against T3.
4206 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4207 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4208 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4209 return false;
4210 // If both registers are low, we're in an IT block, and the immediate is
4211 // in range, we should use encoding T1 instead, which has a cc_out.
4212 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004213 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004214 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4215 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4216 return false;
4217
4218 // Otherwise, we use encoding T4, which does not have a cc_out
4219 // operand.
4220 return true;
4221 }
4222
Jim Grosbach64944f42011-09-14 21:00:40 +00004223 // The thumb2 multiply instruction doesn't have a CCOut register, so
4224 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4225 // use the 16-bit encoding or not.
4226 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4227 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4228 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4229 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4230 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4231 // If the registers aren't low regs, the destination reg isn't the
4232 // same as one of the source regs, or the cc_out operand is zero
4233 // outside of an IT block, we have to use the 32-bit encoding, so
4234 // remove the cc_out operand.
4235 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4236 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004237 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004238 !inITBlock() ||
4239 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4240 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4241 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4242 static_cast<ARMOperand*>(Operands[4])->getReg())))
4243 return true;
4244
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004245 // Also check the 'mul' syntax variant that doesn't specify an explicit
4246 // destination register.
4247 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4248 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4249 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4250 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4251 // If the registers aren't low regs or the cc_out operand is zero
4252 // outside of an IT block, we have to use the 32-bit encoding, so
4253 // remove the cc_out operand.
4254 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4255 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4256 !inITBlock()))
4257 return true;
4258
Jim Grosbach64944f42011-09-14 21:00:40 +00004259
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004260
Jim Grosbachf69c8042011-08-24 21:42:27 +00004261 // Register-register 'add/sub' for thumb does not have a cc_out operand
4262 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4263 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4264 // right, this will result in better diagnostics (which operand is off)
4265 // anyway.
4266 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4267 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004268 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4269 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4270 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4271 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004272
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004273 return false;
4274}
4275
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004276static bool isDataTypeToken(StringRef Tok) {
4277 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4278 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4279 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4280 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4281 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4282 Tok == ".f" || Tok == ".d";
4283}
4284
4285// FIXME: This bit should probably be handled via an explicit match class
4286// in the .td files that matches the suffix instead of having it be
4287// a literal string token the way it is now.
4288static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4289 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4290}
4291
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004292/// Parse an arm instruction mnemonic followed by its operands.
4293bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4294 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4295 // Create the leading tokens for the mnemonic, split by '.' characters.
4296 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004297 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004298
Daniel Dunbar352e1482011-01-11 15:59:50 +00004299 // Split out the predication code and carry setting flag from the mnemonic.
4300 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004301 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004302 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004303 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004304 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004305 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004306
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004307 // In Thumb1, only the branch (B) instruction can be predicated.
4308 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4309 Parser.EatToEndOfStatement();
4310 return Error(NameLoc, "conditional execution not supported in Thumb1");
4311 }
4312
Jim Grosbachffa32252011-07-19 19:13:28 +00004313 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4314
Jim Grosbach89df9962011-08-26 21:43:41 +00004315 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4316 // is the mask as it will be for the IT encoding if the conditional
4317 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4318 // where the conditional bit0 is zero, the instruction post-processing
4319 // will adjust the mask accordingly.
4320 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004321 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4322 if (ITMask.size() > 3) {
4323 Parser.EatToEndOfStatement();
4324 return Error(Loc, "too many conditions on IT instruction");
4325 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004326 unsigned Mask = 8;
4327 for (unsigned i = ITMask.size(); i != 0; --i) {
4328 char pos = ITMask[i - 1];
4329 if (pos != 't' && pos != 'e') {
4330 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004331 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004332 }
4333 Mask >>= 1;
4334 if (ITMask[i - 1] == 't')
4335 Mask |= 8;
4336 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004337 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004338 }
4339
Jim Grosbachffa32252011-07-19 19:13:28 +00004340 // FIXME: This is all a pretty gross hack. We should automatically handle
4341 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004342
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004343 // Next, add the CCOut and ConditionCode operands, if needed.
4344 //
4345 // For mnemonics which can ever incorporate a carry setting bit or predication
4346 // code, our matching model involves us always generating CCOut and
4347 // ConditionCode operands to match the mnemonic "as written" and then we let
4348 // the matcher deal with finding the right instruction or generating an
4349 // appropriate error.
4350 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004351 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004352
Jim Grosbach33c16a22011-07-14 22:04:21 +00004353 // If we had a carry-set on an instruction that can't do that, issue an
4354 // error.
4355 if (!CanAcceptCarrySet && CarrySetting) {
4356 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004357 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004358 "' can not set flags, but 's' suffix specified");
4359 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004360 // If we had a predication code on an instruction that can't do that, issue an
4361 // error.
4362 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4363 Parser.EatToEndOfStatement();
4364 return Error(NameLoc, "instruction '" + Mnemonic +
4365 "' is not predicable, but condition code specified");
4366 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004367
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004368 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004369 if (CanAcceptCarrySet) {
4370 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004371 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004372 Loc));
4373 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004374
4375 // Add the predication code operand, if necessary.
4376 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004377 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4378 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004379 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004380 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004381 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004382
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004383 // Add the processor imod operand, if necessary.
4384 if (ProcessorIMod) {
4385 Operands.push_back(ARMOperand::CreateImm(
4386 MCConstantExpr::Create(ProcessorIMod, getContext()),
4387 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004388 }
4389
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004390 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004391 while (Next != StringRef::npos) {
4392 Start = Next;
4393 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004394 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004395
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004396 // Some NEON instructions have an optional datatype suffix that is
4397 // completely ignored. Check for that.
4398 if (isDataTypeToken(ExtraToken) &&
4399 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4400 continue;
4401
Jim Grosbach81d2e392011-09-07 16:06:04 +00004402 if (ExtraToken != ".n") {
4403 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4404 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4405 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004406 }
4407
4408 // Read the remaining operands.
4409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004410 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004411 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004412 Parser.EatToEndOfStatement();
4413 return true;
4414 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004415
4416 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004417 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004418
4419 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004420 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004421 Parser.EatToEndOfStatement();
4422 return true;
4423 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004424 }
4425 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004426
Chris Lattnercbf8a982010-09-11 16:18:25 +00004427 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004428 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004429 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004430 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004431 }
Bill Wendling146018f2010-11-06 21:42:12 +00004432
Chris Lattner34e53142010-09-08 05:10:46 +00004433 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004434
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004435 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4436 // do and don't have a cc_out optional-def operand. With some spot-checks
4437 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004438 // parse and adjust accordingly before actually matching. We shouldn't ever
4439 // try to remove a cc_out operand that was explicitly set on the the
4440 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4441 // table driven matcher doesn't fit well with the ARM instruction set.
4442 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004443 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4444 Operands.erase(Operands.begin() + 1);
4445 delete Op;
4446 }
4447
Jim Grosbachcf121c32011-07-28 21:57:55 +00004448 // ARM mode 'blx' need special handling, as the register operand version
4449 // is predicable, but the label operand version is not. So, we can't rely
4450 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004451 // a k_CondCode operand in the list. If we're trying to match the label
4452 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004453 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4454 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4455 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4456 Operands.erase(Operands.begin() + 1);
4457 delete Op;
4458 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004459
4460 // The vector-compare-to-zero instructions have a literal token "#0" at
4461 // the end that comes to here as an immediate operand. Convert it to a
4462 // token to play nicely with the matcher.
4463 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4464 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4465 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4466 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4467 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4468 if (CE && CE->getValue() == 0) {
4469 Operands.erase(Operands.begin() + 5);
4470 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4471 delete Op;
4472 }
4473 }
Jim Grosbach68259142011-10-03 22:30:24 +00004474 // VCMP{E} does the same thing, but with a different operand count.
4475 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4476 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4477 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4478 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4479 if (CE && CE->getValue() == 0) {
4480 Operands.erase(Operands.begin() + 4);
4481 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4482 delete Op;
4483 }
4484 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004485 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4486 // end. Convert it to a token here.
4487 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4488 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4489 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4490 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4491 if (CE && CE->getValue() == 0) {
4492 Operands.erase(Operands.begin() + 5);
4493 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4494 delete Op;
4495 }
4496 }
4497
Chris Lattner98986712010-01-14 22:21:20 +00004498 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004499}
4500
Jim Grosbach189610f2011-07-26 18:25:39 +00004501// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004502
4503// return 'true' if register list contains non-low GPR registers,
4504// 'false' otherwise. If Reg is in the register list or is HiReg, set
4505// 'containsReg' to true.
4506static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4507 unsigned HiReg, bool &containsReg) {
4508 containsReg = false;
4509 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4510 unsigned OpReg = Inst.getOperand(i).getReg();
4511 if (OpReg == Reg)
4512 containsReg = true;
4513 // Anything other than a low register isn't legal here.
4514 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4515 return true;
4516 }
4517 return false;
4518}
4519
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004520// Check if the specified regisgter is in the register list of the inst,
4521// starting at the indicated operand number.
4522static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4523 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4524 unsigned OpReg = Inst.getOperand(i).getReg();
4525 if (OpReg == Reg)
4526 return true;
4527 }
4528 return false;
4529}
4530
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004531// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4532// the ARMInsts array) instead. Getting that here requires awkward
4533// API changes, though. Better way?
4534namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004535extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004536}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004537static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004538 return ARMInsts[Opcode];
4539}
4540
Jim Grosbach189610f2011-07-26 18:25:39 +00004541// FIXME: We would really like to be able to tablegen'erate this.
4542bool ARMAsmParser::
4543validateInstruction(MCInst &Inst,
4544 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004545 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004546 SMLoc Loc = Operands[0]->getStartLoc();
4547 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004548 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4549 // being allowed in IT blocks, but not being predicable. It just always
4550 // executes.
4551 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004552 unsigned bit = 1;
4553 if (ITState.FirstCond)
4554 ITState.FirstCond = false;
4555 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004556 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004557 // The instruction must be predicable.
4558 if (!MCID.isPredicable())
4559 return Error(Loc, "instructions in IT block must be predicable");
4560 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4561 unsigned ITCond = bit ? ITState.Cond :
4562 ARMCC::getOppositeCondition(ITState.Cond);
4563 if (Cond != ITCond) {
4564 // Find the condition code Operand to get its SMLoc information.
4565 SMLoc CondLoc;
4566 for (unsigned i = 1; i < Operands.size(); ++i)
4567 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4568 CondLoc = Operands[i]->getStartLoc();
4569 return Error(CondLoc, "incorrect condition in IT block; got '" +
4570 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4571 "', but expected '" +
4572 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4573 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004574 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004575 } else if (isThumbTwo() && MCID.isPredicable() &&
4576 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004577 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4578 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004579 return Error(Loc, "predicated instructions must be in IT block");
4580
Jim Grosbach189610f2011-07-26 18:25:39 +00004581 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004582 case ARM::LDRD:
4583 case ARM::LDRD_PRE:
4584 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004585 case ARM::LDREXD: {
4586 // Rt2 must be Rt + 1.
4587 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4588 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4589 if (Rt2 != Rt + 1)
4590 return Error(Operands[3]->getStartLoc(),
4591 "destination operands must be sequential");
4592 return false;
4593 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004594 case ARM::STRD: {
4595 // Rt2 must be Rt + 1.
4596 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4597 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4598 if (Rt2 != Rt + 1)
4599 return Error(Operands[3]->getStartLoc(),
4600 "source operands must be sequential");
4601 return false;
4602 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004603 case ARM::STRD_PRE:
4604 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004605 case ARM::STREXD: {
4606 // Rt2 must be Rt + 1.
4607 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4608 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4609 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004610 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004611 "source operands must be sequential");
4612 return false;
4613 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004614 case ARM::SBFX:
4615 case ARM::UBFX: {
4616 // width must be in range [1, 32-lsb]
4617 unsigned lsb = Inst.getOperand(2).getImm();
4618 unsigned widthm1 = Inst.getOperand(3).getImm();
4619 if (widthm1 >= 32 - lsb)
4620 return Error(Operands[5]->getStartLoc(),
4621 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004622 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004623 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004624 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004625 // If we're parsing Thumb2, the .w variant is available and handles
4626 // most cases that are normally illegal for a Thumb1 LDM
4627 // instruction. We'll make the transformation in processInstruction()
4628 // if necessary.
4629 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004630 // Thumb LDM instructions are writeback iff the base register is not
4631 // in the register list.
4632 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004633 bool hasWritebackToken =
4634 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4635 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004636 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004637 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004638 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4639 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004640 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004641 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004642 return Error(Operands[2]->getStartLoc(),
4643 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004644 // If we should not have writeback, there must not be a '!'. This is
4645 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004646 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004647 return Error(Operands[3]->getStartLoc(),
4648 "writeback operator '!' not allowed when base register "
4649 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004650
4651 break;
4652 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004653 case ARM::t2LDMIA_UPD: {
4654 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4655 return Error(Operands[4]->getStartLoc(),
4656 "writeback operator '!' not allowed when base register "
4657 "in register list");
4658 break;
4659 }
Jim Grosbach54026372011-11-10 23:17:11 +00004660 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4661 // so only issue a diagnostic for thumb1. The instructions will be
4662 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004663 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004664 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004665 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4666 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004667 return Error(Operands[2]->getStartLoc(),
4668 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004669 break;
4670 }
4671 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004672 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004673 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4674 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004675 return Error(Operands[2]->getStartLoc(),
4676 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004677 break;
4678 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004679 case ARM::tSTMIA_UPD: {
4680 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004681 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004682 return Error(Operands[4]->getStartLoc(),
4683 "registers must be in range r0-r7");
4684 break;
4685 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004686 }
4687
4688 return false;
4689}
4690
Jim Grosbach83ec8772011-11-10 23:42:14 +00004691bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004692processInstruction(MCInst &Inst,
4693 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4694 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004695 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00004696 case ARM::ASRr:
4697 case ARM::LSRr:
4698 case ARM::LSLr:
4699 case ARM::RORr: {
4700 ARM_AM::ShiftOpc ShiftTy;
4701 switch(Inst.getOpcode()) {
4702 default: llvm_unreachable("unexpected opcode!");
4703 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4704 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4705 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4706 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4707 }
4708 // A shift by zero is a plain MOVr, not a MOVsi.
4709 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4710 MCInst TmpInst;
4711 TmpInst.setOpcode(ARM::MOVsr);
4712 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4713 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4714 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4715 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4716 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4717 TmpInst.addOperand(Inst.getOperand(4));
4718 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4719 Inst = TmpInst;
4720 return true;
4721 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00004722 case ARM::ASRi:
4723 case ARM::LSRi:
4724 case ARM::LSLi:
4725 case ARM::RORi: {
4726 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004727 switch(Inst.getOpcode()) {
4728 default: llvm_unreachable("unexpected opcode!");
4729 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4730 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4731 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4732 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4733 }
4734 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00004735 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00004736 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4737 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004738 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004739 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004740 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4741 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004742 if (Opc == ARM::MOVsi)
4743 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004744 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4745 TmpInst.addOperand(Inst.getOperand(4));
4746 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4747 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004748 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004749 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00004750 case ARM::RRXi: {
4751 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4752 MCInst TmpInst;
4753 TmpInst.setOpcode(ARM::MOVsi);
4754 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4755 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4756 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4757 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4758 TmpInst.addOperand(Inst.getOperand(3));
4759 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4760 Inst = TmpInst;
4761 return true;
4762 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004763 case ARM::t2LDMIA_UPD: {
4764 // If this is a load of a single register, then we should use
4765 // a post-indexed LDR instruction instead, per the ARM ARM.
4766 if (Inst.getNumOperands() != 5)
4767 return false;
4768 MCInst TmpInst;
4769 TmpInst.setOpcode(ARM::t2LDR_POST);
4770 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4771 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4772 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4773 TmpInst.addOperand(MCOperand::CreateImm(4));
4774 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4775 TmpInst.addOperand(Inst.getOperand(3));
4776 Inst = TmpInst;
4777 return true;
4778 }
4779 case ARM::t2STMDB_UPD: {
4780 // If this is a store of a single register, then we should use
4781 // a pre-indexed STR instruction instead, per the ARM ARM.
4782 if (Inst.getNumOperands() != 5)
4783 return false;
4784 MCInst TmpInst;
4785 TmpInst.setOpcode(ARM::t2STR_PRE);
4786 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4787 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4788 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4789 TmpInst.addOperand(MCOperand::CreateImm(-4));
4790 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4791 TmpInst.addOperand(Inst.getOperand(3));
4792 Inst = TmpInst;
4793 return true;
4794 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004795 case ARM::LDMIA_UPD:
4796 // If this is a load of a single register via a 'pop', then we should use
4797 // a post-indexed LDR instruction instead, per the ARM ARM.
4798 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4799 Inst.getNumOperands() == 5) {
4800 MCInst TmpInst;
4801 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4802 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4803 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4804 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4805 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4806 TmpInst.addOperand(MCOperand::CreateImm(4));
4807 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4808 TmpInst.addOperand(Inst.getOperand(3));
4809 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004810 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004811 }
4812 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004813 case ARM::STMDB_UPD:
4814 // If this is a store of a single register via a 'push', then we should use
4815 // a pre-indexed STR instruction instead, per the ARM ARM.
4816 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4817 Inst.getNumOperands() == 5) {
4818 MCInst TmpInst;
4819 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4820 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4821 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4822 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4823 TmpInst.addOperand(MCOperand::CreateImm(-4));
4824 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4825 TmpInst.addOperand(Inst.getOperand(3));
4826 Inst = TmpInst;
4827 }
4828 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004829 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004830 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4831 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4832 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4833 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004834 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004835 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004836 return true;
4837 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004838 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004839 case ARM::tSUBi8:
4840 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4841 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4842 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4843 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004844 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004845 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004846 return true;
4847 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004848 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004849 case ARM::tB:
4850 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004851 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004852 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004853 return true;
4854 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004855 break;
4856 case ARM::t2B:
4857 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004858 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004859 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004860 return true;
4861 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004862 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004863 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004864 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004865 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004866 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004867 return true;
4868 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004869 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004870 case ARM::tBcc:
4871 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004872 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004873 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004874 return true;
4875 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004876 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004877 case ARM::tLDMIA: {
4878 // If the register list contains any high registers, or if the writeback
4879 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4880 // instead if we're in Thumb2. Otherwise, this should have generated
4881 // an error in validateInstruction().
4882 unsigned Rn = Inst.getOperand(0).getReg();
4883 bool hasWritebackToken =
4884 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4885 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4886 bool listContainsBase;
4887 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4888 (!listContainsBase && !hasWritebackToken) ||
4889 (listContainsBase && hasWritebackToken)) {
4890 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4891 assert (isThumbTwo());
4892 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4893 // If we're switching to the updating version, we need to insert
4894 // the writeback tied operand.
4895 if (hasWritebackToken)
4896 Inst.insert(Inst.begin(),
4897 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004898 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004899 }
4900 break;
4901 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004902 case ARM::tSTMIA_UPD: {
4903 // If the register list contains any high registers, we need to use
4904 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4905 // should have generated an error in validateInstruction().
4906 unsigned Rn = Inst.getOperand(0).getReg();
4907 bool listContainsBase;
4908 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4909 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4910 assert (isThumbTwo());
4911 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004912 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004913 }
4914 break;
4915 }
Jim Grosbach54026372011-11-10 23:17:11 +00004916 case ARM::tPOP: {
4917 bool listContainsBase;
4918 // If the register list contains any high registers, we need to use
4919 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4920 // should have generated an error in validateInstruction().
4921 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004922 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004923 assert (isThumbTwo());
4924 Inst.setOpcode(ARM::t2LDMIA_UPD);
4925 // Add the base register and writeback operands.
4926 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4927 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004928 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004929 }
4930 case ARM::tPUSH: {
4931 bool listContainsBase;
4932 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004933 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004934 assert (isThumbTwo());
4935 Inst.setOpcode(ARM::t2STMDB_UPD);
4936 // Add the base register and writeback operands.
4937 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4938 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004939 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004940 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004941 case ARM::t2MOVi: {
4942 // If we can use the 16-bit encoding and the user didn't explicitly
4943 // request the 32-bit variant, transform it here.
4944 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4945 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004946 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4947 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4948 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004949 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4950 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4951 // The operands aren't in the same order for tMOVi8...
4952 MCInst TmpInst;
4953 TmpInst.setOpcode(ARM::tMOVi8);
4954 TmpInst.addOperand(Inst.getOperand(0));
4955 TmpInst.addOperand(Inst.getOperand(4));
4956 TmpInst.addOperand(Inst.getOperand(1));
4957 TmpInst.addOperand(Inst.getOperand(2));
4958 TmpInst.addOperand(Inst.getOperand(3));
4959 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004960 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004961 }
4962 break;
4963 }
4964 case ARM::t2MOVr: {
4965 // If we can use the 16-bit encoding and the user didn't explicitly
4966 // request the 32-bit variant, transform it here.
4967 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4968 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4969 Inst.getOperand(2).getImm() == ARMCC::AL &&
4970 Inst.getOperand(4).getReg() == ARM::CPSR &&
4971 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4972 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4973 // The operands aren't the same for tMOV[S]r... (no cc_out)
4974 MCInst TmpInst;
4975 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4976 TmpInst.addOperand(Inst.getOperand(0));
4977 TmpInst.addOperand(Inst.getOperand(1));
4978 TmpInst.addOperand(Inst.getOperand(2));
4979 TmpInst.addOperand(Inst.getOperand(3));
4980 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004981 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004982 }
4983 break;
4984 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004985 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004986 case ARM::t2SXTB:
4987 case ARM::t2UXTH:
4988 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004989 // If we can use the 16-bit encoding and the user didn't explicitly
4990 // request the 32-bit variant, transform it here.
4991 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4992 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4993 Inst.getOperand(2).getImm() == 0 &&
4994 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4995 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00004996 unsigned NewOpc;
4997 switch (Inst.getOpcode()) {
4998 default: llvm_unreachable("Illegal opcode!");
4999 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5000 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5001 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5002 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5003 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005004 // The operands aren't the same for thumb1 (no rotate operand).
5005 MCInst TmpInst;
5006 TmpInst.setOpcode(NewOpc);
5007 TmpInst.addOperand(Inst.getOperand(0));
5008 TmpInst.addOperand(Inst.getOperand(1));
5009 TmpInst.addOperand(Inst.getOperand(3));
5010 TmpInst.addOperand(Inst.getOperand(4));
5011 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005012 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005013 }
5014 break;
5015 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005016 case ARM::t2IT: {
5017 // The mask bits for all but the first condition are represented as
5018 // the low bit of the condition code value implies 't'. We currently
5019 // always have 1 implies 't', so XOR toggle the bits if the low bit
5020 // of the condition code is zero. The encoding also expects the low
5021 // bit of the condition to be encoded as bit 4 of the mask operand,
5022 // so mask that in if needed
5023 MCOperand &MO = Inst.getOperand(1);
5024 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005025 unsigned OrigMask = Mask;
5026 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005027 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005028 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5029 for (unsigned i = 3; i != TZ; --i)
5030 Mask ^= 1 << i;
5031 } else
5032 Mask |= 0x10;
5033 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005034
5035 // Set up the IT block state according to the IT instruction we just
5036 // matched.
5037 assert(!inITBlock() && "nested IT blocks?!");
5038 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5039 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5040 ITState.CurPosition = 0;
5041 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005042 break;
5043 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005044 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005045 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005046}
5047
Jim Grosbach47a0d522011-08-16 20:45:50 +00005048unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5049 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5050 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005051 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005052 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005053 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5054 assert(MCID.hasOptionalDef() &&
5055 "optionally flag setting instruction missing optional def operand");
5056 assert(MCID.NumOperands == Inst.getNumOperands() &&
5057 "operand count mismatch!");
5058 // Find the optional-def operand (cc_out).
5059 unsigned OpNo;
5060 for (OpNo = 0;
5061 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5062 ++OpNo)
5063 ;
5064 // If we're parsing Thumb1, reject it completely.
5065 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5066 return Match_MnemonicFail;
5067 // If we're parsing Thumb2, which form is legal depends on whether we're
5068 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005069 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5070 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005071 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005072 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5073 inITBlock())
5074 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005075 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005076 // Some high-register supporting Thumb1 encodings only allow both registers
5077 // to be from r0-r7 when in Thumb2.
5078 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5079 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5080 isARMLowRegister(Inst.getOperand(2).getReg()))
5081 return Match_RequiresThumb2;
5082 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005083 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005084 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5085 isARMLowRegister(Inst.getOperand(1).getReg()))
5086 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005087 return Match_Success;
5088}
5089
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005090bool ARMAsmParser::
5091MatchAndEmitInstruction(SMLoc IDLoc,
5092 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5093 MCStreamer &Out) {
5094 MCInst Inst;
5095 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005096 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005097 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005098 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005099 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005100 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005101 // Context sensitive operand constraints aren't handled by the matcher,
5102 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005103 if (validateInstruction(Inst, Operands)) {
5104 // Still progress the IT block, otherwise one wrong condition causes
5105 // nasty cascading errors.
5106 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005107 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005108 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005109
Jim Grosbachf8fce712011-08-11 17:35:48 +00005110 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005111 // encoding is selected. Loop on it while changes happen so the
5112 // individual transformations can chain off each other. E.g.,
5113 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5114 while (processInstruction(Inst, Operands))
5115 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005116
Jim Grosbacha1109882011-09-02 23:22:08 +00005117 // Only move forward at the very end so that everything in validate
5118 // and process gets a consistent answer about whether we're in an IT
5119 // block.
5120 forwardITPosition();
5121
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005122 Out.EmitInstruction(Inst);
5123 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005124 case Match_MissingFeature:
5125 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5126 return true;
5127 case Match_InvalidOperand: {
5128 SMLoc ErrorLoc = IDLoc;
5129 if (ErrorInfo != ~0U) {
5130 if (ErrorInfo >= Operands.size())
5131 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005132
Chris Lattnere73d4f82010-10-28 21:41:58 +00005133 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5134 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5135 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005136
Chris Lattnere73d4f82010-10-28 21:41:58 +00005137 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005138 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005139 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005140 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005141 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005142 // The converter function will have already emited a diagnostic.
5143 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005144 case Match_RequiresNotITBlock:
5145 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005146 case Match_RequiresITBlock:
5147 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005148 case Match_RequiresV6:
5149 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5150 case Match_RequiresThumb2:
5151 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005152 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005153
Eric Christopherc223e2b2010-10-29 09:26:59 +00005154 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005155 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005156}
5157
Jim Grosbach1355cf12011-07-26 17:10:22 +00005158/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005159bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5160 StringRef IDVal = DirectiveID.getIdentifier();
5161 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005162 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005163 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005164 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005165 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005166 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005167 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005168 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005169 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005170 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005171 return true;
5172}
5173
Jim Grosbach1355cf12011-07-26 17:10:22 +00005174/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005175/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005176bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005177 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5178 for (;;) {
5179 const MCExpr *Value;
5180 if (getParser().ParseExpression(Value))
5181 return true;
5182
Chris Lattneraaec2052010-01-19 19:46:13 +00005183 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005184
5185 if (getLexer().is(AsmToken::EndOfStatement))
5186 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005187
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005188 // FIXME: Improve diagnostic.
5189 if (getLexer().isNot(AsmToken::Comma))
5190 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005191 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005192 }
5193 }
5194
Sean Callananb9a25b72010-01-19 20:27:46 +00005195 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005196 return false;
5197}
5198
Jim Grosbach1355cf12011-07-26 17:10:22 +00005199/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005200/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005201bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005202 if (getLexer().isNot(AsmToken::EndOfStatement))
5203 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005204 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005205
5206 // TODO: set thumb mode
5207 // TODO: tell the MC streamer the mode
5208 // getParser().getStreamer().Emit???();
5209 return false;
5210}
5211
Jim Grosbach1355cf12011-07-26 17:10:22 +00005212/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005213/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005214bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005215 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5216 bool isMachO = MAI.hasSubsectionsViaSymbols();
5217 StringRef Name;
5218
5219 // Darwin asm has function name after .thumb_func direction
5220 // ELF doesn't
5221 if (isMachO) {
5222 const AsmToken &Tok = Parser.getTok();
5223 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5224 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005225 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005226 Parser.Lex(); // Consume the identifier token.
5227 }
5228
Jim Grosbachd475f862011-11-10 20:48:53 +00005229 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005230 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005231 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005232
Rafael Espindola64695402011-05-16 16:17:21 +00005233 // FIXME: assuming function name will be the line following .thumb_func
5234 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005235 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005236 }
5237
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005238 // Mark symbol as a thumb symbol.
5239 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5240 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005241 return false;
5242}
5243
Jim Grosbach1355cf12011-07-26 17:10:22 +00005244/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005245/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005246bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005247 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005248 if (Tok.isNot(AsmToken::Identifier))
5249 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005250 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005251 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005252 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005253 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005254 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005255 else
5256 return Error(L, "unrecognized syntax mode in .syntax directive");
5257
5258 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005259 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005260 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005261
5262 // TODO tell the MC streamer the mode
5263 // getParser().getStreamer().Emit???();
5264 return false;
5265}
5266
Jim Grosbach1355cf12011-07-26 17:10:22 +00005267/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005268/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005269bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005270 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005271 if (Tok.isNot(AsmToken::Integer))
5272 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005273 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005274 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005275 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005276 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005277 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005278 else
5279 return Error(L, "invalid operand to .code directive");
5280
5281 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005282 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005283 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005284
Evan Cheng32869202011-07-08 22:36:29 +00005285 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005286 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005287 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005288 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005289 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005290 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005291 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005292 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005293 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005294
Kevin Enderby515d5092009-10-15 20:48:48 +00005295 return false;
5296}
5297
Sean Callanan90b70972010-04-07 20:29:34 +00005298extern "C" void LLVMInitializeARMAsmLexer();
5299
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005300/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005301extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005302 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5303 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005304 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005305}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005306
Chris Lattner0692ee62010-09-06 19:11:01 +00005307#define GET_REGISTER_MATCHER
5308#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005309#include "ARMGenAsmMatcher.inc"