blob: c24335ca353c26a8bd24a10acdfdf80e492d9413 [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 Grosbach13af2222011-11-30 18:21:25 +0000980 bool isVecListTwoDAllLanes() const {
981 if (Kind != k_VectorListAllLanes) return false;
982 return VectorList.Count == 2;
983 }
984
Jim Grosbach460a9052011-10-07 23:56:00 +0000985 bool isVectorIndex8() const {
986 if (Kind != k_VectorIndex) return false;
987 return VectorIndex.Val < 8;
988 }
989 bool isVectorIndex16() const {
990 if (Kind != k_VectorIndex) return false;
991 return VectorIndex.Val < 4;
992 }
993 bool isVectorIndex32() const {
994 if (Kind != k_VectorIndex) return false;
995 return VectorIndex.Val < 2;
996 }
997
Jim Grosbach0e387b22011-10-17 22:26:03 +0000998 bool isNEONi8splat() const {
999 if (Kind != k_Immediate)
1000 return false;
1001 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1002 // Must be a constant.
1003 if (!CE) return false;
1004 int64_t Value = CE->getValue();
1005 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1006 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001007 return Value >= 0 && Value < 256;
1008 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001009
Jim Grosbachea461102011-10-17 23:09:09 +00001010 bool isNEONi16splat() const {
1011 if (Kind != k_Immediate)
1012 return false;
1013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1014 // Must be a constant.
1015 if (!CE) return false;
1016 int64_t Value = CE->getValue();
1017 // i16 value in the range [0,255] or [0x0100, 0xff00]
1018 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1019 }
1020
Jim Grosbach6248a542011-10-18 00:22:00 +00001021 bool isNEONi32splat() const {
1022 if (Kind != k_Immediate)
1023 return false;
1024 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1025 // Must be a constant.
1026 if (!CE) return false;
1027 int64_t Value = CE->getValue();
1028 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1029 return (Value >= 0 && Value < 256) ||
1030 (Value >= 0x0100 && Value <= 0xff00) ||
1031 (Value >= 0x010000 && Value <= 0xff0000) ||
1032 (Value >= 0x01000000 && Value <= 0xff000000);
1033 }
1034
1035 bool isNEONi32vmov() const {
1036 if (Kind != k_Immediate)
1037 return false;
1038 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1039 // Must be a constant.
1040 if (!CE) return false;
1041 int64_t Value = CE->getValue();
1042 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1043 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1044 return (Value >= 0 && Value < 256) ||
1045 (Value >= 0x0100 && Value <= 0xff00) ||
1046 (Value >= 0x010000 && Value <= 0xff0000) ||
1047 (Value >= 0x01000000 && Value <= 0xff000000) ||
1048 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1049 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1050 }
1051
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001052 bool isNEONi64splat() const {
1053 if (Kind != k_Immediate)
1054 return false;
1055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1056 // Must be a constant.
1057 if (!CE) return false;
1058 uint64_t Value = CE->getValue();
1059 // i64 value with each byte being either 0 or 0xff.
1060 for (unsigned i = 0; i < 8; ++i)
1061 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1062 return true;
1063 }
1064
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001065 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001066 // Add as immediates when possible. Null MCExpr = 0.
1067 if (Expr == 0)
1068 Inst.addOperand(MCOperand::CreateImm(0));
1069 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001070 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1071 else
1072 Inst.addOperand(MCOperand::CreateExpr(Expr));
1073 }
1074
Daniel Dunbar8462b302010-08-11 06:36:53 +00001075 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001076 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001077 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001078 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1079 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001080 }
1081
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001082 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1083 assert(N == 1 && "Invalid number of operands!");
1084 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1085 }
1086
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001087 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1088 assert(N == 1 && "Invalid number of operands!");
1089 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1090 }
1091
1092 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1093 assert(N == 1 && "Invalid number of operands!");
1094 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1095 }
1096
Jim Grosbach89df9962011-08-26 21:43:41 +00001097 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1098 assert(N == 1 && "Invalid number of operands!");
1099 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1100 }
1101
1102 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1103 assert(N == 1 && "Invalid number of operands!");
1104 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1105 }
1106
Jim Grosbachd67641b2010-12-06 18:21:12 +00001107 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1108 assert(N == 1 && "Invalid number of operands!");
1109 Inst.addOperand(MCOperand::CreateReg(getReg()));
1110 }
1111
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001112 void addRegOperands(MCInst &Inst, unsigned N) const {
1113 assert(N == 1 && "Invalid number of operands!");
1114 Inst.addOperand(MCOperand::CreateReg(getReg()));
1115 }
1116
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001117 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001118 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001119 assert(isRegShiftedReg() &&
1120 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001121 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1122 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001123 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001124 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001125 }
1126
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001127 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001128 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001129 assert(isRegShiftedImm() &&
1130 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001131 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001132 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001133 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001134 }
1135
Jim Grosbach580f4a92011-07-25 22:20:28 +00001136 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001137 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001138 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1139 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001140 }
1141
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001142 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001143 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001144 const SmallVectorImpl<unsigned> &RegList = getRegList();
1145 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001146 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1147 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001148 }
1149
Bill Wendling0f630752010-11-17 04:32:08 +00001150 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1151 addRegListOperands(Inst, N);
1152 }
1153
1154 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1155 addRegListOperands(Inst, N);
1156 }
1157
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001158 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1159 assert(N == 1 && "Invalid number of operands!");
1160 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1161 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1162 }
1163
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001164 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1165 assert(N == 1 && "Invalid number of operands!");
1166 // Munge the lsb/width into a bitfield mask.
1167 unsigned lsb = Bitfield.LSB;
1168 unsigned width = Bitfield.Width;
1169 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1170 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1171 (32 - (lsb + width)));
1172 Inst.addOperand(MCOperand::CreateImm(Mask));
1173 }
1174
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001175 void addImmOperands(MCInst &Inst, unsigned N) const {
1176 assert(N == 1 && "Invalid number of operands!");
1177 addExpr(Inst, getImm());
1178 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001179
Jim Grosbach9d390362011-10-03 23:38:36 +00001180 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1181 assert(N == 1 && "Invalid number of operands!");
1182 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1183 }
1184
Jim Grosbacha77295d2011-09-08 22:07:06 +00001185 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1186 assert(N == 1 && "Invalid number of operands!");
1187 // FIXME: We really want to scale the value here, but the LDRD/STRD
1188 // instruction don't encode operands that way yet.
1189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1190 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1191 }
1192
Jim Grosbach72f39f82011-08-24 21:22:15 +00001193 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1194 assert(N == 1 && "Invalid number of operands!");
1195 // The immediate is scaled by four in the encoding and is stored
1196 // in the MCInst as such. Lop off the low two bits here.
1197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1199 }
1200
1201 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
1203 // The immediate is scaled by four in the encoding and is stored
1204 // in the MCInst as such. Lop off the low two bits here.
1205 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1206 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1207 }
1208
Jim Grosbachf4943352011-07-25 23:09:14 +00001209 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
1211 // The constant encodes as the immediate-1, and we store in the instruction
1212 // the bits as encoded, so subtract off one here.
1213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1214 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1215 }
1216
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001217 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1218 assert(N == 1 && "Invalid number of operands!");
1219 // The constant encodes as the immediate-1, and we store in the instruction
1220 // the bits as encoded, so subtract off one here.
1221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1222 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1223 }
1224
Jim Grosbach70939ee2011-08-17 21:51:27 +00001225 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
1227 // The constant encodes as the immediate, except for 32, which encodes as
1228 // zero.
1229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1230 unsigned Imm = CE->getValue();
1231 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1232 }
1233
Jim Grosbachf6c05252011-07-21 17:23:04 +00001234 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1235 assert(N == 1 && "Invalid number of operands!");
1236 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1237 // the instruction as well.
1238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1239 int Val = CE->getValue();
1240 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1241 }
1242
Jim Grosbach89a63372011-10-28 22:36:30 +00001243 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1244 assert(N == 1 && "Invalid number of operands!");
1245 // The operand is actually a t2_so_imm, but we have its bitwise
1246 // negation in the assembly source, so twiddle it here.
1247 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1248 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1249 }
1250
Jim Grosbache70ec842011-10-28 22:50:54 +00001251 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1252 assert(N == 1 && "Invalid number of operands!");
1253 // The operand is actually a so_imm, but we have its bitwise
1254 // negation in the assembly source, so twiddle it here.
1255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1256 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1257 }
1258
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001259 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1260 assert(N == 1 && "Invalid number of operands!");
1261 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1262 }
1263
Jim Grosbach7ce05792011-08-03 23:50:40 +00001264 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001266 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001267 }
1268
Jim Grosbach57dcb852011-10-11 17:29:55 +00001269 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 2 && "Invalid number of operands!");
1271 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1272 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1273 }
1274
Jim Grosbach7ce05792011-08-03 23:50:40 +00001275 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1276 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001277 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1278 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001279 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1280 // Special case for #-0
1281 if (Val == INT32_MIN) Val = 0;
1282 if (Val < 0) Val = -Val;
1283 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1284 } else {
1285 // For register offset, we encode the shift type and negation flag
1286 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001287 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1288 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001289 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001290 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1291 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001292 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001293 }
1294
Jim Grosbach039c2e12011-08-04 23:01:30 +00001295 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 2 && "Invalid number of operands!");
1297 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1298 assert(CE && "non-constant AM2OffsetImm operand!");
1299 int32_t Val = CE->getValue();
1300 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1301 // Special case for #-0
1302 if (Val == INT32_MIN) Val = 0;
1303 if (Val < 0) Val = -Val;
1304 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1305 Inst.addOperand(MCOperand::CreateReg(0));
1306 Inst.addOperand(MCOperand::CreateImm(Val));
1307 }
1308
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001309 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001311 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1312 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001313 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1314 // Special case for #-0
1315 if (Val == INT32_MIN) Val = 0;
1316 if (Val < 0) Val = -Val;
1317 Val = ARM_AM::getAM3Opc(AddSub, Val);
1318 } else {
1319 // For register offset, we encode the shift type and negation flag
1320 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001321 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001322 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001323 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1324 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001325 Inst.addOperand(MCOperand::CreateImm(Val));
1326 }
1327
1328 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1329 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001330 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001331 int32_t Val =
1332 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1333 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1334 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001335 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001336 }
1337
1338 // Constant offset.
1339 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1340 int32_t Val = CE->getValue();
1341 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1342 // Special case for #-0
1343 if (Val == INT32_MIN) Val = 0;
1344 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001345 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001346 Inst.addOperand(MCOperand::CreateReg(0));
1347 Inst.addOperand(MCOperand::CreateImm(Val));
1348 }
1349
Jim Grosbach7ce05792011-08-03 23:50:40 +00001350 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1351 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001352 // If we have an immediate that's not a constant, treat it as a label
1353 // reference needing a fixup. If it is a constant, it's something else
1354 // and we reject it.
1355 if (isImm()) {
1356 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1357 Inst.addOperand(MCOperand::CreateImm(0));
1358 return;
1359 }
1360
Jim Grosbach7ce05792011-08-03 23:50:40 +00001361 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001362 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001363 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1364 // Special case for #-0
1365 if (Val == INT32_MIN) Val = 0;
1366 if (Val < 0) Val = -Val;
1367 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001368 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001369 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001370 }
1371
Jim Grosbacha77295d2011-09-08 22:07:06 +00001372 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001374 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1375 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001376 Inst.addOperand(MCOperand::CreateImm(Val));
1377 }
1378
Jim Grosbachb6aed502011-09-09 18:37:27 +00001379 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1380 assert(N == 2 && "Invalid number of operands!");
1381 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001382 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1383 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001384 Inst.addOperand(MCOperand::CreateImm(Val));
1385 }
1386
Jim Grosbach7ce05792011-08-03 23:50:40 +00001387 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1388 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001389 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1390 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001391 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001392 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001393
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001394 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1395 addMemImm8OffsetOperands(Inst, N);
1396 }
1397
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001398 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001399 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001400 }
1401
1402 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1403 assert(N == 2 && "Invalid number of operands!");
1404 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001405 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001406 addExpr(Inst, getImm());
1407 Inst.addOperand(MCOperand::CreateImm(0));
1408 return;
1409 }
1410
1411 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001412 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1413 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001414 Inst.addOperand(MCOperand::CreateImm(Val));
1415 }
1416
Jim Grosbach7ce05792011-08-03 23:50:40 +00001417 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1418 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001419 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001420 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001421 addExpr(Inst, getImm());
1422 Inst.addOperand(MCOperand::CreateImm(0));
1423 return;
1424 }
1425
1426 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001427 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1428 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001429 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001430 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001431
Jim Grosbach7f739be2011-09-19 22:21:13 +00001432 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1433 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1435 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001436 }
1437
1438 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1439 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001440 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1441 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001442 }
1443
Jim Grosbach7ce05792011-08-03 23:50:40 +00001444 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1445 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001446 unsigned Val =
1447 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1448 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001449 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1450 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001451 Inst.addOperand(MCOperand::CreateImm(Val));
1452 }
1453
Jim Grosbachab899c12011-09-07 23:10:15 +00001454 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1455 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001456 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1457 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1458 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001459 }
1460
Jim Grosbach7ce05792011-08-03 23:50:40 +00001461 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1462 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001463 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1464 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001465 }
1466
Jim Grosbach60f91a32011-08-19 17:55:24 +00001467 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1468 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001469 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1470 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001471 Inst.addOperand(MCOperand::CreateImm(Val));
1472 }
1473
Jim Grosbach38466302011-08-19 18:55:51 +00001474 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1475 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001476 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1477 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001478 Inst.addOperand(MCOperand::CreateImm(Val));
1479 }
1480
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001481 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1482 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001483 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1484 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001485 Inst.addOperand(MCOperand::CreateImm(Val));
1486 }
1487
Jim Grosbachecd85892011-08-19 18:13:48 +00001488 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001490 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1491 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001492 Inst.addOperand(MCOperand::CreateImm(Val));
1493 }
1494
Jim Grosbach7ce05792011-08-03 23:50:40 +00001495 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1496 assert(N == 1 && "Invalid number of operands!");
1497 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1498 assert(CE && "non-constant post-idx-imm8 operand!");
1499 int Imm = CE->getValue();
1500 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001501 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001502 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1503 Inst.addOperand(MCOperand::CreateImm(Imm));
1504 }
1505
Jim Grosbach2bd01182011-10-11 21:55:36 +00001506 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1509 assert(CE && "non-constant post-idx-imm8s4 operand!");
1510 int Imm = CE->getValue();
1511 bool isAdd = Imm >= 0;
1512 if (Imm == INT32_MIN) Imm = 0;
1513 // Immediate is scaled by 4.
1514 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1515 Inst.addOperand(MCOperand::CreateImm(Imm));
1516 }
1517
Jim Grosbach7ce05792011-08-03 23:50:40 +00001518 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1519 assert(N == 2 && "Invalid number of operands!");
1520 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001521 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1522 }
1523
1524 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1525 assert(N == 2 && "Invalid number of operands!");
1526 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1527 // The sign, shift type, and shift amount are encoded in a single operand
1528 // using the AM2 encoding helpers.
1529 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1530 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1531 PostIdxReg.ShiftTy);
1532 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001533 }
1534
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001535 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1536 assert(N == 1 && "Invalid number of operands!");
1537 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1538 }
1539
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001540 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1543 }
1544
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001545 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001546 assert(N == 1 && "Invalid number of operands!");
1547 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1548 }
1549
Jim Grosbach460a9052011-10-07 23:56:00 +00001550 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1553 }
1554
1555 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1558 }
1559
1560 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1563 }
1564
Jim Grosbach0e387b22011-10-17 22:26:03 +00001565 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 // The immediate encodes the type of constant as well as the value.
1568 // Mask in that this is an i8 splat.
1569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1570 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1571 }
1572
Jim Grosbachea461102011-10-17 23:09:09 +00001573 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 // The immediate encodes the type of constant as well as the value.
1576 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1577 unsigned Value = CE->getValue();
1578 if (Value >= 256)
1579 Value = (Value >> 8) | 0xa00;
1580 else
1581 Value |= 0x800;
1582 Inst.addOperand(MCOperand::CreateImm(Value));
1583 }
1584
Jim Grosbach6248a542011-10-18 00:22:00 +00001585 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1586 assert(N == 1 && "Invalid number of operands!");
1587 // The immediate encodes the type of constant as well as the value.
1588 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1589 unsigned Value = CE->getValue();
1590 if (Value >= 256 && Value <= 0xff00)
1591 Value = (Value >> 8) | 0x200;
1592 else if (Value > 0xffff && Value <= 0xff0000)
1593 Value = (Value >> 16) | 0x400;
1594 else if (Value > 0xffffff)
1595 Value = (Value >> 24) | 0x600;
1596 Inst.addOperand(MCOperand::CreateImm(Value));
1597 }
1598
1599 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1600 assert(N == 1 && "Invalid number of operands!");
1601 // The immediate encodes the type of constant as well as the value.
1602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1603 unsigned Value = CE->getValue();
1604 if (Value >= 256 && Value <= 0xffff)
1605 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1606 else if (Value > 0xffff && Value <= 0xffffff)
1607 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1608 else if (Value > 0xffffff)
1609 Value = (Value >> 24) | 0x600;
1610 Inst.addOperand(MCOperand::CreateImm(Value));
1611 }
1612
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001613 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The immediate encodes the type of constant as well as the value.
1616 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1617 uint64_t Value = CE->getValue();
1618 unsigned Imm = 0;
1619 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1620 Imm |= (Value & 1) << i;
1621 }
1622 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1623 }
1624
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001625 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001626
Jim Grosbach89df9962011-08-26 21:43:41 +00001627 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001628 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001629 Op->ITMask.Mask = Mask;
1630 Op->StartLoc = S;
1631 Op->EndLoc = S;
1632 return Op;
1633 }
1634
Chris Lattner3a697562010-10-28 17:20:03 +00001635 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001636 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001637 Op->CC.Val = CC;
1638 Op->StartLoc = S;
1639 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001640 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001641 }
1642
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001643 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001644 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001645 Op->Cop.Val = CopVal;
1646 Op->StartLoc = S;
1647 Op->EndLoc = S;
1648 return Op;
1649 }
1650
1651 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001652 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001653 Op->Cop.Val = CopVal;
1654 Op->StartLoc = S;
1655 Op->EndLoc = S;
1656 return Op;
1657 }
1658
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001659 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1660 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1661 Op->Cop.Val = Val;
1662 Op->StartLoc = S;
1663 Op->EndLoc = E;
1664 return Op;
1665 }
1666
Jim Grosbachd67641b2010-12-06 18:21:12 +00001667 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001668 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001669 Op->Reg.RegNum = RegNum;
1670 Op->StartLoc = S;
1671 Op->EndLoc = S;
1672 return Op;
1673 }
1674
Chris Lattner3a697562010-10-28 17:20:03 +00001675 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001676 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001677 Op->Tok.Data = Str.data();
1678 Op->Tok.Length = Str.size();
1679 Op->StartLoc = S;
1680 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001681 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001682 }
1683
Bill Wendling50d0f582010-11-18 23:43:05 +00001684 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001685 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001686 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001687 Op->StartLoc = S;
1688 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001689 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001690 }
1691
Jim Grosbache8606dc2011-07-13 17:50:29 +00001692 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1693 unsigned SrcReg,
1694 unsigned ShiftReg,
1695 unsigned ShiftImm,
1696 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001697 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001698 Op->RegShiftedReg.ShiftTy = ShTy;
1699 Op->RegShiftedReg.SrcReg = SrcReg;
1700 Op->RegShiftedReg.ShiftReg = ShiftReg;
1701 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001702 Op->StartLoc = S;
1703 Op->EndLoc = E;
1704 return Op;
1705 }
1706
Owen Anderson92a20222011-07-21 18:54:16 +00001707 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1708 unsigned SrcReg,
1709 unsigned ShiftImm,
1710 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001711 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001712 Op->RegShiftedImm.ShiftTy = ShTy;
1713 Op->RegShiftedImm.SrcReg = SrcReg;
1714 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001715 Op->StartLoc = S;
1716 Op->EndLoc = E;
1717 return Op;
1718 }
1719
Jim Grosbach580f4a92011-07-25 22:20:28 +00001720 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001721 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001722 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001723 Op->ShifterImm.isASR = isASR;
1724 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001725 Op->StartLoc = S;
1726 Op->EndLoc = E;
1727 return Op;
1728 }
1729
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001730 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001731 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001732 Op->RotImm.Imm = Imm;
1733 Op->StartLoc = S;
1734 Op->EndLoc = E;
1735 return Op;
1736 }
1737
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001738 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1739 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001740 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001741 Op->Bitfield.LSB = LSB;
1742 Op->Bitfield.Width = Width;
1743 Op->StartLoc = S;
1744 Op->EndLoc = E;
1745 return Op;
1746 }
1747
Bill Wendling7729e062010-11-09 22:44:22 +00001748 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001749 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001750 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001751 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001752
Jim Grosbachd300b942011-09-13 22:56:44 +00001753 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001754 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001755 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001756 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001757 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001758
1759 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001760 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001761 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001762 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001763 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001764 Op->StartLoc = StartLoc;
1765 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001766 return Op;
1767 }
1768
Jim Grosbach862019c2011-10-18 23:02:30 +00001769 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1770 SMLoc S, SMLoc E) {
1771 ARMOperand *Op = new ARMOperand(k_VectorList);
1772 Op->VectorList.RegNum = RegNum;
1773 Op->VectorList.Count = Count;
1774 Op->StartLoc = S;
1775 Op->EndLoc = E;
1776 return Op;
1777 }
1778
Jim Grosbach98b05a52011-11-30 01:09:44 +00001779 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1780 SMLoc S, SMLoc E) {
1781 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1782 Op->VectorList.RegNum = RegNum;
1783 Op->VectorList.Count = Count;
1784 Op->StartLoc = S;
1785 Op->EndLoc = E;
1786 return Op;
1787 }
1788
Jim Grosbach460a9052011-10-07 23:56:00 +00001789 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1790 MCContext &Ctx) {
1791 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1792 Op->VectorIndex.Val = Idx;
1793 Op->StartLoc = S;
1794 Op->EndLoc = E;
1795 return Op;
1796 }
1797
Chris Lattner3a697562010-10-28 17:20:03 +00001798 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001799 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001800 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001801 Op->StartLoc = S;
1802 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001803 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001804 }
1805
Jim Grosbach9d390362011-10-03 23:38:36 +00001806 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001807 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001808 Op->FPImm.Val = Val;
1809 Op->StartLoc = S;
1810 Op->EndLoc = S;
1811 return Op;
1812 }
1813
Jim Grosbach7ce05792011-08-03 23:50:40 +00001814 static ARMOperand *CreateMem(unsigned BaseRegNum,
1815 const MCConstantExpr *OffsetImm,
1816 unsigned OffsetRegNum,
1817 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001818 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001819 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001820 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001821 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001822 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001823 Op->Memory.BaseRegNum = BaseRegNum;
1824 Op->Memory.OffsetImm = OffsetImm;
1825 Op->Memory.OffsetRegNum = OffsetRegNum;
1826 Op->Memory.ShiftType = ShiftType;
1827 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001828 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001829 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001830 Op->StartLoc = S;
1831 Op->EndLoc = E;
1832 return Op;
1833 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001834
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001835 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1836 ARM_AM::ShiftOpc ShiftTy,
1837 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001838 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001839 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001840 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001841 Op->PostIdxReg.isAdd = isAdd;
1842 Op->PostIdxReg.ShiftTy = ShiftTy;
1843 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001844 Op->StartLoc = S;
1845 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001846 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001847 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001848
1849 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001850 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001851 Op->MBOpt.Val = Opt;
1852 Op->StartLoc = S;
1853 Op->EndLoc = S;
1854 return Op;
1855 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001856
1857 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001858 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001859 Op->IFlags.Val = IFlags;
1860 Op->StartLoc = S;
1861 Op->EndLoc = S;
1862 return Op;
1863 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001864
1865 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001866 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001867 Op->MMask.Val = MMask;
1868 Op->StartLoc = S;
1869 Op->EndLoc = S;
1870 return Op;
1871 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001872};
1873
1874} // end anonymous namespace.
1875
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001876void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001877 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001878 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00001879 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
1880 << ") >";
1881 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001882 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00001883 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001884 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001885 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00001886 OS << "<ccout " << getReg() << ">";
1887 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001888 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00001889 static const char *MaskStr[] = {
1890 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
1891 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
1892 };
Jim Grosbach89df9962011-08-26 21:43:41 +00001893 assert((ITMask.Mask & 0xf) == ITMask.Mask);
1894 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
1895 break;
1896 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001897 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001898 OS << "<coprocessor number: " << getCoproc() << ">";
1899 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001900 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001901 OS << "<coprocessor register: " << getCoproc() << ">";
1902 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001903 case k_CoprocOption:
1904 OS << "<coprocessor option: " << CoprocOption.Val << ">";
1905 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001906 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001907 OS << "<mask: " << getMSRMask() << ">";
1908 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001909 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001910 getImm()->print(OS);
1911 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001912 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001913 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
1914 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001916 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00001917 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00001918 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001919 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001920 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001921 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
1922 << PostIdxReg.RegNum;
1923 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
1924 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
1925 << PostIdxReg.ShiftImm;
1926 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00001927 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001928 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001929 OS << "<ARM_PROC::";
1930 unsigned IFlags = getProcIFlags();
1931 for (int i=2; i >= 0; --i)
1932 if (IFlags & (1 << i))
1933 OS << ARM_PROC::IFlagsToString(1 << i);
1934 OS << ">";
1935 break;
1936 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001937 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00001938 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001939 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001940 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00001941 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
1942 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00001943 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00001945 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001946 << RegShiftedReg.SrcReg << " "
1947 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
1948 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00001949 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001950 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00001951 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00001952 << RegShiftedImm.SrcReg << " "
1953 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
1954 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00001955 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001956 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001957 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
1958 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001959 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001960 OS << "<bitfield " << "lsb: " << Bitfield.LSB
1961 << ", width: " << Bitfield.Width << ">";
1962 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001963 case k_RegisterList:
1964 case k_DPRRegisterList:
1965 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00001966 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001967
Bill Wendling5fa22a12010-11-09 23:28:44 +00001968 const SmallVectorImpl<unsigned> &RegList = getRegList();
1969 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001970 I = RegList.begin(), E = RegList.end(); I != E; ) {
1971 OS << *I;
1972 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00001973 }
1974
1975 OS << ">";
1976 break;
1977 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001978 case k_VectorList:
1979 OS << "<vector_list " << VectorList.Count << " * "
1980 << VectorList.RegNum << ">";
1981 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001982 case k_VectorListAllLanes:
1983 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
1984 << VectorList.RegNum << ">";
1985 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001986 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001987 OS << "'" << getToken() << "'";
1988 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00001989 case k_VectorIndex:
1990 OS << "<vectorindex " << getVectorIndex() << ">";
1991 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001992 }
1993}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001994
1995/// @name Auto-generated Match Functions
1996/// {
1997
1998static unsigned MatchRegisterName(StringRef Name);
1999
2000/// }
2001
Bob Wilson69df7232011-02-03 21:46:10 +00002002bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2003 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002004 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002005
2006 return (RegNo == (unsigned)-1);
2007}
2008
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002009/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002010/// and if it is a register name the token is eaten and the register number is
2011/// returned. Otherwise return -1.
2012///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002013int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002014 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002015 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002016
Chris Lattnere5658fa2010-10-30 04:09:10 +00002017 // FIXME: Validate register for the current architecture; we have to do
2018 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002019 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002020 unsigned RegNum = MatchRegisterName(lowerCase);
2021 if (!RegNum) {
2022 RegNum = StringSwitch<unsigned>(lowerCase)
2023 .Case("r13", ARM::SP)
2024 .Case("r14", ARM::LR)
2025 .Case("r15", ARM::PC)
2026 .Case("ip", ARM::R12)
2027 .Default(0);
2028 }
2029 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002030
Chris Lattnere5658fa2010-10-30 04:09:10 +00002031 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002032
Chris Lattnere5658fa2010-10-30 04:09:10 +00002033 return RegNum;
2034}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002035
Jim Grosbach19906722011-07-13 18:49:30 +00002036// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2037// If a recoverable error occurs, return 1. If an irrecoverable error
2038// occurs, return -1. An irrecoverable error is one where tokens have been
2039// consumed in the process of trying to parse the shifter (i.e., when it is
2040// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002041int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002042 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2043 SMLoc S = Parser.getTok().getLoc();
2044 const AsmToken &Tok = Parser.getTok();
2045 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2046
Benjamin Kramer59085362011-11-06 20:37:06 +00002047 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002048 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2049 .Case("lsl", ARM_AM::lsl)
2050 .Case("lsr", ARM_AM::lsr)
2051 .Case("asr", ARM_AM::asr)
2052 .Case("ror", ARM_AM::ror)
2053 .Case("rrx", ARM_AM::rrx)
2054 .Default(ARM_AM::no_shift);
2055
2056 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002057 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002058
Jim Grosbache8606dc2011-07-13 17:50:29 +00002059 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002060
Jim Grosbache8606dc2011-07-13 17:50:29 +00002061 // The source register for the shift has already been added to the
2062 // operand list, so we need to pop it off and combine it into the shifted
2063 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002064 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002065 if (!PrevOp->isReg())
2066 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2067 int SrcReg = PrevOp->getReg();
2068 int64_t Imm = 0;
2069 int ShiftReg = 0;
2070 if (ShiftTy == ARM_AM::rrx) {
2071 // RRX Doesn't have an explicit shift amount. The encoder expects
2072 // the shift register to be the same as the source register. Seems odd,
2073 // but OK.
2074 ShiftReg = SrcReg;
2075 } else {
2076 // Figure out if this is shifted by a constant or a register (for non-RRX).
2077 if (Parser.getTok().is(AsmToken::Hash)) {
2078 Parser.Lex(); // Eat hash.
2079 SMLoc ImmLoc = Parser.getTok().getLoc();
2080 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002081 if (getParser().ParseExpression(ShiftExpr)) {
2082 Error(ImmLoc, "invalid immediate shift value");
2083 return -1;
2084 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002085 // The expression must be evaluatable as an immediate.
2086 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002087 if (!CE) {
2088 Error(ImmLoc, "invalid immediate shift value");
2089 return -1;
2090 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002091 // Range check the immediate.
2092 // lsl, ror: 0 <= imm <= 31
2093 // lsr, asr: 0 <= imm <= 32
2094 Imm = CE->getValue();
2095 if (Imm < 0 ||
2096 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2097 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002098 Error(ImmLoc, "immediate shift value out of range");
2099 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002100 }
2101 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002102 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002103 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002104 if (ShiftReg == -1) {
2105 Error (L, "expected immediate or register in shift operand");
2106 return -1;
2107 }
2108 } else {
2109 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002110 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002111 return -1;
2112 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002113 }
2114
Owen Anderson92a20222011-07-21 18:54:16 +00002115 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2116 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002117 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002118 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002119 else
2120 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2121 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002122
Jim Grosbach19906722011-07-13 18:49:30 +00002123 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002124}
2125
2126
Bill Wendling50d0f582010-11-18 23:43:05 +00002127/// Try to parse a register name. The token must be an Identifier when called.
2128/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2129/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002130///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002131/// TODO this is likely to change to allow different register types and or to
2132/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002133bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002134tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002135 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002136 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002137 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002138 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002139
Bill Wendling50d0f582010-11-18 23:43:05 +00002140 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002141
Chris Lattnere5658fa2010-10-30 04:09:10 +00002142 const AsmToken &ExclaimTok = Parser.getTok();
2143 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002144 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2145 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002146 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002147 return false;
2148 }
2149
2150 // Also check for an index operand. This is only legal for vector registers,
2151 // but that'll get caught OK in operand matching, so we don't need to
2152 // explicitly filter everything else out here.
2153 if (Parser.getTok().is(AsmToken::LBrac)) {
2154 SMLoc SIdx = Parser.getTok().getLoc();
2155 Parser.Lex(); // Eat left bracket token.
2156
2157 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002158 if (getParser().ParseExpression(ImmVal))
2159 return MatchOperand_ParseFail;
2160 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2161 if (!MCE) {
2162 TokError("immediate value expected for vector index");
2163 return MatchOperand_ParseFail;
2164 }
2165
2166 SMLoc E = Parser.getTok().getLoc();
2167 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2168 Error(E, "']' expected");
2169 return MatchOperand_ParseFail;
2170 }
2171
2172 Parser.Lex(); // Eat right bracket token.
2173
2174 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2175 SIdx, E,
2176 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002177 }
2178
Bill Wendling50d0f582010-11-18 23:43:05 +00002179 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002180}
2181
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002182/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2183/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2184/// "c5", ...
2185static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002186 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2187 // but efficient.
2188 switch (Name.size()) {
2189 default: break;
2190 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002191 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002192 return -1;
2193 switch (Name[1]) {
2194 default: return -1;
2195 case '0': return 0;
2196 case '1': return 1;
2197 case '2': return 2;
2198 case '3': return 3;
2199 case '4': return 4;
2200 case '5': return 5;
2201 case '6': return 6;
2202 case '7': return 7;
2203 case '8': return 8;
2204 case '9': return 9;
2205 }
2206 break;
2207 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002208 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002209 return -1;
2210 switch (Name[2]) {
2211 default: return -1;
2212 case '0': return 10;
2213 case '1': return 11;
2214 case '2': return 12;
2215 case '3': return 13;
2216 case '4': return 14;
2217 case '5': return 15;
2218 }
2219 break;
2220 }
2221
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002222 return -1;
2223}
2224
Jim Grosbach89df9962011-08-26 21:43:41 +00002225/// parseITCondCode - Try to parse a condition code for an IT instruction.
2226ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2227parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2228 SMLoc S = Parser.getTok().getLoc();
2229 const AsmToken &Tok = Parser.getTok();
2230 if (!Tok.is(AsmToken::Identifier))
2231 return MatchOperand_NoMatch;
2232 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2233 .Case("eq", ARMCC::EQ)
2234 .Case("ne", ARMCC::NE)
2235 .Case("hs", ARMCC::HS)
2236 .Case("cs", ARMCC::HS)
2237 .Case("lo", ARMCC::LO)
2238 .Case("cc", ARMCC::LO)
2239 .Case("mi", ARMCC::MI)
2240 .Case("pl", ARMCC::PL)
2241 .Case("vs", ARMCC::VS)
2242 .Case("vc", ARMCC::VC)
2243 .Case("hi", ARMCC::HI)
2244 .Case("ls", ARMCC::LS)
2245 .Case("ge", ARMCC::GE)
2246 .Case("lt", ARMCC::LT)
2247 .Case("gt", ARMCC::GT)
2248 .Case("le", ARMCC::LE)
2249 .Case("al", ARMCC::AL)
2250 .Default(~0U);
2251 if (CC == ~0U)
2252 return MatchOperand_NoMatch;
2253 Parser.Lex(); // Eat the token.
2254
2255 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2256
2257 return MatchOperand_Success;
2258}
2259
Jim Grosbach43904292011-07-25 20:14:50 +00002260/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002261/// token must be an Identifier when called, and if it is a coprocessor
2262/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002263ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002264parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002265 SMLoc S = Parser.getTok().getLoc();
2266 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002267 if (Tok.isNot(AsmToken::Identifier))
2268 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002269
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002270 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002271 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002272 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002273
2274 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002275 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002276 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002277}
2278
Jim Grosbach43904292011-07-25 20:14:50 +00002279/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002280/// token must be an Identifier when called, and if it is a coprocessor
2281/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002282ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002283parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002284 SMLoc S = Parser.getTok().getLoc();
2285 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002286 if (Tok.isNot(AsmToken::Identifier))
2287 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002288
2289 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2290 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002291 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002292
2293 Parser.Lex(); // Eat identifier token.
2294 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002295 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002296}
2297
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002298/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2299/// coproc_option : '{' imm0_255 '}'
2300ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2301parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2302 SMLoc S = Parser.getTok().getLoc();
2303
2304 // If this isn't a '{', this isn't a coprocessor immediate operand.
2305 if (Parser.getTok().isNot(AsmToken::LCurly))
2306 return MatchOperand_NoMatch;
2307 Parser.Lex(); // Eat the '{'
2308
2309 const MCExpr *Expr;
2310 SMLoc Loc = Parser.getTok().getLoc();
2311 if (getParser().ParseExpression(Expr)) {
2312 Error(Loc, "illegal expression");
2313 return MatchOperand_ParseFail;
2314 }
2315 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2316 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2317 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2318 return MatchOperand_ParseFail;
2319 }
2320 int Val = CE->getValue();
2321
2322 // Check for and consume the closing '}'
2323 if (Parser.getTok().isNot(AsmToken::RCurly))
2324 return MatchOperand_ParseFail;
2325 SMLoc E = Parser.getTok().getLoc();
2326 Parser.Lex(); // Eat the '}'
2327
2328 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2329 return MatchOperand_Success;
2330}
2331
Jim Grosbachd0588e22011-09-14 18:08:35 +00002332// For register list parsing, we need to map from raw GPR register numbering
2333// to the enumeration values. The enumeration values aren't sorted by
2334// register number due to our using "sp", "lr" and "pc" as canonical names.
2335static unsigned getNextRegister(unsigned Reg) {
2336 // If this is a GPR, we need to do it manually, otherwise we can rely
2337 // on the sort ordering of the enumeration since the other reg-classes
2338 // are sane.
2339 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2340 return Reg + 1;
2341 switch(Reg) {
2342 default: assert(0 && "Invalid GPR number!");
2343 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2344 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2345 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2346 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2347 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2348 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2349 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2350 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2351 }
2352}
2353
Jim Grosbachce485e72011-11-11 21:27:40 +00002354// Return the low-subreg of a given Q register.
2355static unsigned getDRegFromQReg(unsigned QReg) {
2356 switch (QReg) {
2357 default: llvm_unreachable("expected a Q register!");
2358 case ARM::Q0: return ARM::D0;
2359 case ARM::Q1: return ARM::D2;
2360 case ARM::Q2: return ARM::D4;
2361 case ARM::Q3: return ARM::D6;
2362 case ARM::Q4: return ARM::D8;
2363 case ARM::Q5: return ARM::D10;
2364 case ARM::Q6: return ARM::D12;
2365 case ARM::Q7: return ARM::D14;
2366 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002367 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002368 case ARM::Q10: return ARM::D20;
2369 case ARM::Q11: return ARM::D22;
2370 case ARM::Q12: return ARM::D24;
2371 case ARM::Q13: return ARM::D26;
2372 case ARM::Q14: return ARM::D28;
2373 case ARM::Q15: return ARM::D30;
2374 }
2375}
2376
Jim Grosbachd0588e22011-09-14 18:08:35 +00002377/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002378bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002379parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002380 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002381 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002382 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002383 Parser.Lex(); // Eat '{' token.
2384 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002385
Jim Grosbachd0588e22011-09-14 18:08:35 +00002386 // Check the first register in the list to see what register class
2387 // this is a list of.
2388 int Reg = tryParseRegister();
2389 if (Reg == -1)
2390 return Error(RegLoc, "register expected");
2391
Jim Grosbachce485e72011-11-11 21:27:40 +00002392 // The reglist instructions have at most 16 registers, so reserve
2393 // space for that many.
2394 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2395
2396 // Allow Q regs and just interpret them as the two D sub-registers.
2397 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2398 Reg = getDRegFromQReg(Reg);
2399 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2400 ++Reg;
2401 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002402 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002403 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2404 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2405 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2406 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2407 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2408 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2409 else
2410 return Error(RegLoc, "invalid register in register list");
2411
Jim Grosbachce485e72011-11-11 21:27:40 +00002412 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002413 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002414
Jim Grosbachd0588e22011-09-14 18:08:35 +00002415 // This starts immediately after the first register token in the list,
2416 // so we can see either a comma or a minus (range separator) as a legal
2417 // next token.
2418 while (Parser.getTok().is(AsmToken::Comma) ||
2419 Parser.getTok().is(AsmToken::Minus)) {
2420 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002421 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002422 SMLoc EndLoc = Parser.getTok().getLoc();
2423 int EndReg = tryParseRegister();
2424 if (EndReg == -1)
2425 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002426 // Allow Q regs and just interpret them as the two D sub-registers.
2427 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2428 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002429 // If the register is the same as the start reg, there's nothing
2430 // more to do.
2431 if (Reg == EndReg)
2432 continue;
2433 // The register must be in the same register class as the first.
2434 if (!RC->contains(EndReg))
2435 return Error(EndLoc, "invalid register in register list");
2436 // Ranges must go from low to high.
2437 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2438 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002439
Jim Grosbachd0588e22011-09-14 18:08:35 +00002440 // Add all the registers in the range to the register list.
2441 while (Reg != EndReg) {
2442 Reg = getNextRegister(Reg);
2443 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2444 }
2445 continue;
2446 }
2447 Parser.Lex(); // Eat the comma.
2448 RegLoc = Parser.getTok().getLoc();
2449 int OldReg = Reg;
2450 Reg = tryParseRegister();
2451 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002452 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002453 // Allow Q regs and just interpret them as the two D sub-registers.
2454 bool isQReg = false;
2455 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2456 Reg = getDRegFromQReg(Reg);
2457 isQReg = true;
2458 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002459 // The register must be in the same register class as the first.
2460 if (!RC->contains(Reg))
2461 return Error(RegLoc, "invalid register in register list");
2462 // List must be monotonically increasing.
2463 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2464 return Error(RegLoc, "register list not in ascending order");
2465 // VFP register lists must also be contiguous.
2466 // It's OK to use the enumeration values directly here rather, as the
2467 // VFP register classes have the enum sorted properly.
2468 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2469 Reg != OldReg + 1)
2470 return Error(RegLoc, "non-contiguous register range");
2471 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002472 if (isQReg)
2473 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002474 }
2475
Jim Grosbachd0588e22011-09-14 18:08:35 +00002476 SMLoc E = Parser.getTok().getLoc();
2477 if (Parser.getTok().isNot(AsmToken::RCurly))
2478 return Error(E, "'}' expected");
2479 Parser.Lex(); // Eat '}' token.
2480
Bill Wendling50d0f582010-11-18 23:43:05 +00002481 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2482 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002483}
2484
Jim Grosbach98b05a52011-11-30 01:09:44 +00002485// Helper function to parse the lane index for vector lists.
2486ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2487parseVectorLane(VectorLaneTy &LaneKind) {
2488 if (Parser.getTok().is(AsmToken::LBrac)) {
2489 Parser.Lex(); // Eat the '['.
2490 if (Parser.getTok().is(AsmToken::RBrac)) {
2491 // "Dn[]" is the 'all lanes' syntax.
2492 LaneKind = AllLanes;
2493 Parser.Lex(); // Eat the ']'.
2494 return MatchOperand_Success;
2495 }
2496 // FIXME: Other lane kinds as we add them.
2497 Error(Parser.getTok().getLoc(), "FIXME: Unexpected lane kind.");
2498 return MatchOperand_ParseFail;
2499 }
2500 LaneKind = NoLanes;
2501 return MatchOperand_Success;
2502}
2503
Jim Grosbach862019c2011-10-18 23:02:30 +00002504// parse a vector register list
2505ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2506parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002507 VectorLaneTy LaneKind;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002508 SMLoc S = Parser.getTok().getLoc();
2509 // As an extension (to match gas), support a plain D register or Q register
2510 // (without encosing curly braces) as a single or double entry list,
2511 // respectively.
2512 if (Parser.getTok().is(AsmToken::Identifier)) {
2513 int Reg = tryParseRegister();
2514 if (Reg == -1)
2515 return MatchOperand_NoMatch;
2516 SMLoc E = Parser.getTok().getLoc();
2517 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002518 OperandMatchResultTy Res = parseVectorLane(LaneKind);
2519 if (Res != MatchOperand_Success)
2520 return Res;
2521 switch (LaneKind) {
2522 default:
2523 assert(0 && "unexpected lane kind!");
2524 case NoLanes:
2525 E = Parser.getTok().getLoc();
2526 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2527 break;
2528 case AllLanes:
2529 E = Parser.getTok().getLoc();
2530 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2531 break;
2532 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002533 return MatchOperand_Success;
2534 }
2535 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2536 Reg = getDRegFromQReg(Reg);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002537 OperandMatchResultTy Res = parseVectorLane(LaneKind);
2538 if (Res != MatchOperand_Success)
2539 return Res;
2540 switch (LaneKind) {
2541 default:
2542 assert(0 && "unexpected lane kind!");
2543 case NoLanes:
2544 E = Parser.getTok().getLoc();
2545 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2546 break;
2547 case AllLanes:
2548 E = Parser.getTok().getLoc();
2549 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2550 break;
2551 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002552 return MatchOperand_Success;
2553 }
2554 Error(S, "vector register expected");
2555 return MatchOperand_ParseFail;
2556 }
2557
2558 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002559 return MatchOperand_NoMatch;
2560
Jim Grosbach862019c2011-10-18 23:02:30 +00002561 Parser.Lex(); // Eat '{' token.
2562 SMLoc RegLoc = Parser.getTok().getLoc();
2563
2564 int Reg = tryParseRegister();
2565 if (Reg == -1) {
2566 Error(RegLoc, "register expected");
2567 return MatchOperand_ParseFail;
2568 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002569 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002570 unsigned FirstReg = Reg;
2571 // The list is of D registers, but we also allow Q regs and just interpret
2572 // them as the two D sub-registers.
2573 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2574 FirstReg = Reg = getDRegFromQReg(Reg);
2575 ++Reg;
2576 ++Count;
2577 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002578 if (parseVectorLane(LaneKind) != MatchOperand_Success)
2579 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002580
Jim Grosbache43862b2011-11-15 23:19:15 +00002581 while (Parser.getTok().is(AsmToken::Comma) ||
2582 Parser.getTok().is(AsmToken::Minus)) {
2583 if (Parser.getTok().is(AsmToken::Minus)) {
2584 Parser.Lex(); // Eat the minus.
2585 SMLoc EndLoc = Parser.getTok().getLoc();
2586 int EndReg = tryParseRegister();
2587 if (EndReg == -1) {
2588 Error(EndLoc, "register expected");
2589 return MatchOperand_ParseFail;
2590 }
2591 // Allow Q regs and just interpret them as the two D sub-registers.
2592 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2593 EndReg = getDRegFromQReg(EndReg) + 1;
2594 // If the register is the same as the start reg, there's nothing
2595 // more to do.
2596 if (Reg == EndReg)
2597 continue;
2598 // The register must be in the same register class as the first.
2599 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2600 Error(EndLoc, "invalid register in register list");
2601 return MatchOperand_ParseFail;
2602 }
2603 // Ranges must go from low to high.
2604 if (Reg > EndReg) {
2605 Error(EndLoc, "bad range in register list");
2606 return MatchOperand_ParseFail;
2607 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002608 // Parse the lane specifier if present.
2609 VectorLaneTy NextLaneKind;
2610 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2611 return MatchOperand_ParseFail;
2612 if (NextLaneKind != LaneKind) {
2613 Error(EndLoc, "mismatched lane index in register list");
2614 return MatchOperand_ParseFail;
2615 }
2616 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002617
2618 // Add all the registers in the range to the register list.
2619 Count += EndReg - Reg;
2620 Reg = EndReg;
2621 continue;
2622 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002623 Parser.Lex(); // Eat the comma.
2624 RegLoc = Parser.getTok().getLoc();
2625 int OldReg = Reg;
2626 Reg = tryParseRegister();
2627 if (Reg == -1) {
2628 Error(RegLoc, "register expected");
2629 return MatchOperand_ParseFail;
2630 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002631 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002632 // It's OK to use the enumeration values directly here rather, as the
2633 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002634 //
2635 // The list is of D registers, but we also allow Q regs and just interpret
2636 // them as the two D sub-registers.
2637 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2638 Reg = getDRegFromQReg(Reg);
2639 if (Reg != OldReg + 1) {
2640 Error(RegLoc, "non-contiguous register range");
2641 return MatchOperand_ParseFail;
2642 }
2643 ++Reg;
2644 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002645 // Parse the lane specifier if present.
2646 VectorLaneTy NextLaneKind;
2647 SMLoc EndLoc = Parser.getTok().getLoc();
2648 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2649 return MatchOperand_ParseFail;
2650 if (NextLaneKind != LaneKind) {
2651 Error(EndLoc, "mismatched lane index in register list");
2652 return MatchOperand_ParseFail;
2653 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002654 continue;
2655 }
2656 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002657 if (Reg != OldReg + 1) {
2658 Error(RegLoc, "non-contiguous register range");
2659 return MatchOperand_ParseFail;
2660 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002661 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002662 // Parse the lane specifier if present.
2663 VectorLaneTy NextLaneKind;
2664 SMLoc EndLoc = Parser.getTok().getLoc();
2665 if (parseVectorLane(NextLaneKind) != MatchOperand_Success)
2666 return MatchOperand_ParseFail;
2667 if (NextLaneKind != LaneKind) {
2668 Error(EndLoc, "mismatched lane index in register list");
2669 return MatchOperand_ParseFail;
2670 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002671 }
2672
2673 SMLoc E = Parser.getTok().getLoc();
2674 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2675 Error(E, "'}' expected");
2676 return MatchOperand_ParseFail;
2677 }
2678 Parser.Lex(); // Eat '}' token.
2679
Jim Grosbach98b05a52011-11-30 01:09:44 +00002680 switch (LaneKind) {
2681 default:
2682 assert(0 && "unexpected lane kind in register list.");
2683 case NoLanes:
2684 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2685 break;
2686 case AllLanes:
2687 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2688 S, E));
2689 break;
2690 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002691 return MatchOperand_Success;
2692}
2693
Jim Grosbach43904292011-07-25 20:14:50 +00002694/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002695ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002696parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002697 SMLoc S = Parser.getTok().getLoc();
2698 const AsmToken &Tok = Parser.getTok();
2699 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2700 StringRef OptStr = Tok.getString();
2701
2702 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2703 .Case("sy", ARM_MB::SY)
2704 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002705 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002706 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002707 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002708 .Case("ishst", ARM_MB::ISHST)
2709 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002710 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002711 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002712 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002713 .Case("osh", ARM_MB::OSH)
2714 .Case("oshst", ARM_MB::OSHST)
2715 .Default(~0U);
2716
2717 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002718 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002719
2720 Parser.Lex(); // Eat identifier token.
2721 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002722 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002723}
2724
Jim Grosbach43904292011-07-25 20:14:50 +00002725/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002726ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002727parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002728 SMLoc S = Parser.getTok().getLoc();
2729 const AsmToken &Tok = Parser.getTok();
2730 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2731 StringRef IFlagsStr = Tok.getString();
2732
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002733 // An iflags string of "none" is interpreted to mean that none of the AIF
2734 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002735 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002736 if (IFlagsStr != "none") {
2737 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2738 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2739 .Case("a", ARM_PROC::A)
2740 .Case("i", ARM_PROC::I)
2741 .Case("f", ARM_PROC::F)
2742 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002743
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002744 // If some specific iflag is already set, it means that some letter is
2745 // present more than once, this is not acceptable.
2746 if (Flag == ~0U || (IFlags & Flag))
2747 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002748
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002749 IFlags |= Flag;
2750 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002751 }
2752
2753 Parser.Lex(); // Eat identifier token.
2754 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2755 return MatchOperand_Success;
2756}
2757
Jim Grosbach43904292011-07-25 20:14:50 +00002758/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002759ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002760parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002761 SMLoc S = Parser.getTok().getLoc();
2762 const AsmToken &Tok = Parser.getTok();
2763 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2764 StringRef Mask = Tok.getString();
2765
James Molloyacad68d2011-09-28 14:21:38 +00002766 if (isMClass()) {
2767 // See ARMv6-M 10.1.1
2768 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2769 .Case("apsr", 0)
2770 .Case("iapsr", 1)
2771 .Case("eapsr", 2)
2772 .Case("xpsr", 3)
2773 .Case("ipsr", 5)
2774 .Case("epsr", 6)
2775 .Case("iepsr", 7)
2776 .Case("msp", 8)
2777 .Case("psp", 9)
2778 .Case("primask", 16)
2779 .Case("basepri", 17)
2780 .Case("basepri_max", 18)
2781 .Case("faultmask", 19)
2782 .Case("control", 20)
2783 .Default(~0U);
2784
2785 if (FlagsVal == ~0U)
2786 return MatchOperand_NoMatch;
2787
2788 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2789 // basepri, basepri_max and faultmask only valid for V7m.
2790 return MatchOperand_NoMatch;
2791
2792 Parser.Lex(); // Eat identifier token.
2793 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2794 return MatchOperand_Success;
2795 }
2796
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002797 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2798 size_t Start = 0, Next = Mask.find('_');
2799 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002800 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002801 if (Next != StringRef::npos)
2802 Flags = Mask.slice(Next+1, Mask.size());
2803
2804 // FlagsVal contains the complete mask:
2805 // 3-0: Mask
2806 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2807 unsigned FlagsVal = 0;
2808
2809 if (SpecReg == "apsr") {
2810 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002811 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002812 .Case("g", 0x4) // same as CPSR_s
2813 .Case("nzcvqg", 0xc) // same as CPSR_fs
2814 .Default(~0U);
2815
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002816 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002817 if (!Flags.empty())
2818 return MatchOperand_NoMatch;
2819 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002820 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002821 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002822 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002823 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2824 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002825 for (int i = 0, e = Flags.size(); i != e; ++i) {
2826 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2827 .Case("c", 1)
2828 .Case("x", 2)
2829 .Case("s", 4)
2830 .Case("f", 8)
2831 .Default(~0U);
2832
2833 // If some specific flag is already set, it means that some letter is
2834 // present more than once, this is not acceptable.
2835 if (FlagsVal == ~0U || (FlagsVal & Flag))
2836 return MatchOperand_NoMatch;
2837 FlagsVal |= Flag;
2838 }
2839 } else // No match for special register.
2840 return MatchOperand_NoMatch;
2841
Owen Anderson7784f1d2011-10-21 18:43:28 +00002842 // Special register without flags is NOT equivalent to "fc" flags.
2843 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
2844 // two lines would enable gas compatibility at the expense of breaking
2845 // round-tripping.
2846 //
2847 // if (!FlagsVal)
2848 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002849
2850 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2851 if (SpecReg == "spsr")
2852 FlagsVal |= 16;
2853
2854 Parser.Lex(); // Eat identifier token.
2855 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2856 return MatchOperand_Success;
2857}
2858
Jim Grosbachf6c05252011-07-21 17:23:04 +00002859ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2860parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
2861 int Low, int High) {
2862 const AsmToken &Tok = Parser.getTok();
2863 if (Tok.isNot(AsmToken::Identifier)) {
2864 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2865 return MatchOperand_ParseFail;
2866 }
2867 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00002868 std::string LowerOp = Op.lower();
2869 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00002870 if (ShiftName != LowerOp && ShiftName != UpperOp) {
2871 Error(Parser.getTok().getLoc(), Op + " operand expected.");
2872 return MatchOperand_ParseFail;
2873 }
2874 Parser.Lex(); // Eat shift type token.
2875
2876 // There must be a '#' and a shift amount.
2877 if (Parser.getTok().isNot(AsmToken::Hash)) {
2878 Error(Parser.getTok().getLoc(), "'#' expected");
2879 return MatchOperand_ParseFail;
2880 }
2881 Parser.Lex(); // Eat hash token.
2882
2883 const MCExpr *ShiftAmount;
2884 SMLoc Loc = Parser.getTok().getLoc();
2885 if (getParser().ParseExpression(ShiftAmount)) {
2886 Error(Loc, "illegal expression");
2887 return MatchOperand_ParseFail;
2888 }
2889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2890 if (!CE) {
2891 Error(Loc, "constant expression expected");
2892 return MatchOperand_ParseFail;
2893 }
2894 int Val = CE->getValue();
2895 if (Val < Low || Val > High) {
2896 Error(Loc, "immediate value out of range");
2897 return MatchOperand_ParseFail;
2898 }
2899
2900 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
2901
2902 return MatchOperand_Success;
2903}
2904
Jim Grosbachc27d4f92011-07-22 17:44:50 +00002905ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2906parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2907 const AsmToken &Tok = Parser.getTok();
2908 SMLoc S = Tok.getLoc();
2909 if (Tok.isNot(AsmToken::Identifier)) {
2910 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2911 return MatchOperand_ParseFail;
2912 }
2913 int Val = StringSwitch<int>(Tok.getString())
2914 .Case("be", 1)
2915 .Case("le", 0)
2916 .Default(-1);
2917 Parser.Lex(); // Eat the token.
2918
2919 if (Val == -1) {
2920 Error(Tok.getLoc(), "'be' or 'le' operand expected");
2921 return MatchOperand_ParseFail;
2922 }
2923 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
2924 getContext()),
2925 S, Parser.getTok().getLoc()));
2926 return MatchOperand_Success;
2927}
2928
Jim Grosbach580f4a92011-07-25 22:20:28 +00002929/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
2930/// instructions. Legal values are:
2931/// lsl #n 'n' in [0,31]
2932/// asr #n 'n' in [1,32]
2933/// n == 32 encoded as n == 0.
2934ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2935parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2936 const AsmToken &Tok = Parser.getTok();
2937 SMLoc S = Tok.getLoc();
2938 if (Tok.isNot(AsmToken::Identifier)) {
2939 Error(S, "shift operator 'asr' or 'lsl' expected");
2940 return MatchOperand_ParseFail;
2941 }
2942 StringRef ShiftName = Tok.getString();
2943 bool isASR;
2944 if (ShiftName == "lsl" || ShiftName == "LSL")
2945 isASR = false;
2946 else if (ShiftName == "asr" || ShiftName == "ASR")
2947 isASR = true;
2948 else {
2949 Error(S, "shift operator 'asr' or 'lsl' expected");
2950 return MatchOperand_ParseFail;
2951 }
2952 Parser.Lex(); // Eat the operator.
2953
2954 // A '#' and a shift amount.
2955 if (Parser.getTok().isNot(AsmToken::Hash)) {
2956 Error(Parser.getTok().getLoc(), "'#' expected");
2957 return MatchOperand_ParseFail;
2958 }
2959 Parser.Lex(); // Eat hash token.
2960
2961 const MCExpr *ShiftAmount;
2962 SMLoc E = Parser.getTok().getLoc();
2963 if (getParser().ParseExpression(ShiftAmount)) {
2964 Error(E, "malformed shift expression");
2965 return MatchOperand_ParseFail;
2966 }
2967 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
2968 if (!CE) {
2969 Error(E, "shift amount must be an immediate");
2970 return MatchOperand_ParseFail;
2971 }
2972
2973 int64_t Val = CE->getValue();
2974 if (isASR) {
2975 // Shift amount must be in [1,32]
2976 if (Val < 1 || Val > 32) {
2977 Error(E, "'asr' shift amount must be in range [1,32]");
2978 return MatchOperand_ParseFail;
2979 }
Owen Anderson0afa0092011-09-26 21:06:22 +00002980 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
2981 if (isThumb() && Val == 32) {
2982 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
2983 return MatchOperand_ParseFail;
2984 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00002985 if (Val == 32) Val = 0;
2986 } else {
2987 // Shift amount must be in [1,32]
2988 if (Val < 0 || Val > 31) {
2989 Error(E, "'lsr' shift amount must be in range [0,31]");
2990 return MatchOperand_ParseFail;
2991 }
2992 }
2993
2994 E = Parser.getTok().getLoc();
2995 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
2996
2997 return MatchOperand_Success;
2998}
2999
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003000/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3001/// of instructions. Legal values are:
3002/// ror #n 'n' in {0, 8, 16, 24}
3003ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3004parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3005 const AsmToken &Tok = Parser.getTok();
3006 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003007 if (Tok.isNot(AsmToken::Identifier))
3008 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003009 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003010 if (ShiftName != "ror" && ShiftName != "ROR")
3011 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003012 Parser.Lex(); // Eat the operator.
3013
3014 // A '#' and a rotate amount.
3015 if (Parser.getTok().isNot(AsmToken::Hash)) {
3016 Error(Parser.getTok().getLoc(), "'#' expected");
3017 return MatchOperand_ParseFail;
3018 }
3019 Parser.Lex(); // Eat hash token.
3020
3021 const MCExpr *ShiftAmount;
3022 SMLoc E = Parser.getTok().getLoc();
3023 if (getParser().ParseExpression(ShiftAmount)) {
3024 Error(E, "malformed rotate expression");
3025 return MatchOperand_ParseFail;
3026 }
3027 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3028 if (!CE) {
3029 Error(E, "rotate amount must be an immediate");
3030 return MatchOperand_ParseFail;
3031 }
3032
3033 int64_t Val = CE->getValue();
3034 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3035 // normally, zero is represented in asm by omitting the rotate operand
3036 // entirely.
3037 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3038 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3039 return MatchOperand_ParseFail;
3040 }
3041
3042 E = Parser.getTok().getLoc();
3043 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3044
3045 return MatchOperand_Success;
3046}
3047
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003048ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3049parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3050 SMLoc S = Parser.getTok().getLoc();
3051 // The bitfield descriptor is really two operands, the LSB and the width.
3052 if (Parser.getTok().isNot(AsmToken::Hash)) {
3053 Error(Parser.getTok().getLoc(), "'#' expected");
3054 return MatchOperand_ParseFail;
3055 }
3056 Parser.Lex(); // Eat hash token.
3057
3058 const MCExpr *LSBExpr;
3059 SMLoc E = Parser.getTok().getLoc();
3060 if (getParser().ParseExpression(LSBExpr)) {
3061 Error(E, "malformed immediate expression");
3062 return MatchOperand_ParseFail;
3063 }
3064 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3065 if (!CE) {
3066 Error(E, "'lsb' operand must be an immediate");
3067 return MatchOperand_ParseFail;
3068 }
3069
3070 int64_t LSB = CE->getValue();
3071 // The LSB must be in the range [0,31]
3072 if (LSB < 0 || LSB > 31) {
3073 Error(E, "'lsb' operand must be in the range [0,31]");
3074 return MatchOperand_ParseFail;
3075 }
3076 E = Parser.getTok().getLoc();
3077
3078 // Expect another immediate operand.
3079 if (Parser.getTok().isNot(AsmToken::Comma)) {
3080 Error(Parser.getTok().getLoc(), "too few operands");
3081 return MatchOperand_ParseFail;
3082 }
3083 Parser.Lex(); // Eat hash token.
3084 if (Parser.getTok().isNot(AsmToken::Hash)) {
3085 Error(Parser.getTok().getLoc(), "'#' expected");
3086 return MatchOperand_ParseFail;
3087 }
3088 Parser.Lex(); // Eat hash token.
3089
3090 const MCExpr *WidthExpr;
3091 if (getParser().ParseExpression(WidthExpr)) {
3092 Error(E, "malformed immediate expression");
3093 return MatchOperand_ParseFail;
3094 }
3095 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3096 if (!CE) {
3097 Error(E, "'width' operand must be an immediate");
3098 return MatchOperand_ParseFail;
3099 }
3100
3101 int64_t Width = CE->getValue();
3102 // The LSB must be in the range [1,32-lsb]
3103 if (Width < 1 || Width > 32 - LSB) {
3104 Error(E, "'width' operand must be in the range [1,32-lsb]");
3105 return MatchOperand_ParseFail;
3106 }
3107 E = Parser.getTok().getLoc();
3108
3109 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3110
3111 return MatchOperand_Success;
3112}
3113
Jim Grosbach7ce05792011-08-03 23:50:40 +00003114ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3115parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3116 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003117 // postidx_reg := '+' register {, shift}
3118 // | '-' register {, shift}
3119 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003120
3121 // This method must return MatchOperand_NoMatch without consuming any tokens
3122 // in the case where there is no match, as other alternatives take other
3123 // parse methods.
3124 AsmToken Tok = Parser.getTok();
3125 SMLoc S = Tok.getLoc();
3126 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003127 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003128 int Reg = -1;
3129 if (Tok.is(AsmToken::Plus)) {
3130 Parser.Lex(); // Eat the '+' token.
3131 haveEaten = true;
3132 } else if (Tok.is(AsmToken::Minus)) {
3133 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003134 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003135 haveEaten = true;
3136 }
3137 if (Parser.getTok().is(AsmToken::Identifier))
3138 Reg = tryParseRegister();
3139 if (Reg == -1) {
3140 if (!haveEaten)
3141 return MatchOperand_NoMatch;
3142 Error(Parser.getTok().getLoc(), "register expected");
3143 return MatchOperand_ParseFail;
3144 }
3145 SMLoc E = Parser.getTok().getLoc();
3146
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003147 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3148 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003149 if (Parser.getTok().is(AsmToken::Comma)) {
3150 Parser.Lex(); // Eat the ','.
3151 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3152 return MatchOperand_ParseFail;
3153 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003154
3155 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3156 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003157
3158 return MatchOperand_Success;
3159}
3160
Jim Grosbach251bf252011-08-10 21:56:18 +00003161ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3162parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3163 // Check for a post-index addressing register operand. Specifically:
3164 // am3offset := '+' register
3165 // | '-' register
3166 // | register
3167 // | # imm
3168 // | # + imm
3169 // | # - imm
3170
3171 // This method must return MatchOperand_NoMatch without consuming any tokens
3172 // in the case where there is no match, as other alternatives take other
3173 // parse methods.
3174 AsmToken Tok = Parser.getTok();
3175 SMLoc S = Tok.getLoc();
3176
3177 // Do immediates first, as we always parse those if we have a '#'.
3178 if (Parser.getTok().is(AsmToken::Hash)) {
3179 Parser.Lex(); // Eat the '#'.
3180 // Explicitly look for a '-', as we need to encode negative zero
3181 // differently.
3182 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3183 const MCExpr *Offset;
3184 if (getParser().ParseExpression(Offset))
3185 return MatchOperand_ParseFail;
3186 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3187 if (!CE) {
3188 Error(S, "constant expression expected");
3189 return MatchOperand_ParseFail;
3190 }
3191 SMLoc E = Tok.getLoc();
3192 // Negative zero is encoded as the flag value INT32_MIN.
3193 int32_t Val = CE->getValue();
3194 if (isNegative && Val == 0)
3195 Val = INT32_MIN;
3196
3197 Operands.push_back(
3198 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3199
3200 return MatchOperand_Success;
3201 }
3202
3203
3204 bool haveEaten = false;
3205 bool isAdd = true;
3206 int Reg = -1;
3207 if (Tok.is(AsmToken::Plus)) {
3208 Parser.Lex(); // Eat the '+' token.
3209 haveEaten = true;
3210 } else if (Tok.is(AsmToken::Minus)) {
3211 Parser.Lex(); // Eat the '-' token.
3212 isAdd = false;
3213 haveEaten = true;
3214 }
3215 if (Parser.getTok().is(AsmToken::Identifier))
3216 Reg = tryParseRegister();
3217 if (Reg == -1) {
3218 if (!haveEaten)
3219 return MatchOperand_NoMatch;
3220 Error(Parser.getTok().getLoc(), "register expected");
3221 return MatchOperand_ParseFail;
3222 }
3223 SMLoc E = Parser.getTok().getLoc();
3224
3225 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3226 0, S, E));
3227
3228 return MatchOperand_Success;
3229}
3230
Jim Grosbacha77295d2011-09-08 22:07:06 +00003231/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3232/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3233/// when they refer multiple MIOperands inside a single one.
3234bool ARMAsmParser::
3235cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3236 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3237 // Rt, Rt2
3238 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3239 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3240 // Create a writeback register dummy placeholder.
3241 Inst.addOperand(MCOperand::CreateReg(0));
3242 // addr
3243 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3244 // pred
3245 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3246 return true;
3247}
3248
3249/// cvtT2StrdPre - Convert parsed operands to MCInst.
3250/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3251/// when they refer multiple MIOperands inside a single one.
3252bool ARMAsmParser::
3253cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3254 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3255 // Create a writeback register dummy placeholder.
3256 Inst.addOperand(MCOperand::CreateReg(0));
3257 // Rt, Rt2
3258 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3259 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3260 // addr
3261 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3262 // pred
3263 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3264 return true;
3265}
3266
Jim Grosbacheeec0252011-09-08 00:39:19 +00003267/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3268/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3269/// when they refer multiple MIOperands inside a single one.
3270bool ARMAsmParser::
3271cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3272 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3273 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3274
3275 // Create a writeback register dummy placeholder.
3276 Inst.addOperand(MCOperand::CreateImm(0));
3277
3278 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3279 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3280 return true;
3281}
3282
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003283/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3284/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3285/// when they refer multiple MIOperands inside a single one.
3286bool ARMAsmParser::
3287cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3288 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3289 // Create a writeback register dummy placeholder.
3290 Inst.addOperand(MCOperand::CreateImm(0));
3291 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3292 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3293 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3294 return true;
3295}
3296
Jim Grosbach1355cf12011-07-26 17:10:22 +00003297/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003298/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3299/// when they refer multiple MIOperands inside a single one.
3300bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003301cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003302 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3303 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3304
3305 // Create a writeback register dummy placeholder.
3306 Inst.addOperand(MCOperand::CreateImm(0));
3307
Jim Grosbach7ce05792011-08-03 23:50:40 +00003308 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003309 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3310 return true;
3311}
3312
Owen Anderson9ab0f252011-08-26 20:43:14 +00003313/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3314/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3315/// when they refer multiple MIOperands inside a single one.
3316bool ARMAsmParser::
3317cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3318 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3319 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3320
3321 // Create a writeback register dummy placeholder.
3322 Inst.addOperand(MCOperand::CreateImm(0));
3323
3324 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3325 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3326 return true;
3327}
3328
3329
Jim Grosbach548340c2011-08-11 19:22:40 +00003330/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3331/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3332/// when they refer multiple MIOperands inside a single one.
3333bool ARMAsmParser::
3334cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3335 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3336 // Create a writeback register dummy placeholder.
3337 Inst.addOperand(MCOperand::CreateImm(0));
3338 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3339 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3340 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3341 return true;
3342}
3343
Jim Grosbach1355cf12011-07-26 17:10:22 +00003344/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003345/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3346/// when they refer multiple MIOperands inside a single one.
3347bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003348cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003349 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3350 // Create a writeback register dummy placeholder.
3351 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003352 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3353 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3354 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003355 return true;
3356}
3357
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003358/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3359/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3360/// when they refer multiple MIOperands inside a single one.
3361bool ARMAsmParser::
3362cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3363 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3364 // Create a writeback register dummy placeholder.
3365 Inst.addOperand(MCOperand::CreateImm(0));
3366 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3367 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3368 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3369 return true;
3370}
3371
Jim Grosbach7ce05792011-08-03 23:50:40 +00003372/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3373/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3374/// when they refer multiple MIOperands inside a single one.
3375bool ARMAsmParser::
3376cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3377 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3378 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003379 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003380 // Create a writeback register dummy placeholder.
3381 Inst.addOperand(MCOperand::CreateImm(0));
3382 // addr
3383 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3384 // offset
3385 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3386 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003387 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3388 return true;
3389}
3390
Jim Grosbach7ce05792011-08-03 23:50:40 +00003391/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003392/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3393/// when they refer multiple MIOperands inside a single one.
3394bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003395cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3396 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3397 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003398 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003399 // Create a writeback register dummy placeholder.
3400 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003401 // addr
3402 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3403 // offset
3404 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3405 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003406 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3407 return true;
3408}
3409
Jim Grosbach7ce05792011-08-03 23:50:40 +00003410/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003411/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3412/// when they refer multiple MIOperands inside a single one.
3413bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003414cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3415 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003416 // Create a writeback register dummy placeholder.
3417 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003418 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003419 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003420 // addr
3421 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3422 // offset
3423 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3424 // pred
3425 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3426 return true;
3427}
3428
3429/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3430/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3431/// when they refer multiple MIOperands inside a single one.
3432bool ARMAsmParser::
3433cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3434 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3435 // Create a writeback register dummy placeholder.
3436 Inst.addOperand(MCOperand::CreateImm(0));
3437 // Rt
3438 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3439 // addr
3440 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3441 // offset
3442 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3443 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003444 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3445 return true;
3446}
3447
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003448/// cvtLdrdPre - Convert parsed operands to MCInst.
3449/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3450/// when they refer multiple MIOperands inside a single one.
3451bool ARMAsmParser::
3452cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3453 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3454 // Rt, Rt2
3455 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3456 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3457 // Create a writeback register dummy placeholder.
3458 Inst.addOperand(MCOperand::CreateImm(0));
3459 // addr
3460 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3461 // pred
3462 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3463 return true;
3464}
3465
Jim Grosbach14605d12011-08-11 20:28:23 +00003466/// cvtStrdPre - Convert parsed operands to MCInst.
3467/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3468/// when they refer multiple MIOperands inside a single one.
3469bool ARMAsmParser::
3470cvtStrdPre(MCInst &Inst, unsigned Opcode,
3471 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3472 // Create a writeback register dummy placeholder.
3473 Inst.addOperand(MCOperand::CreateImm(0));
3474 // Rt, Rt2
3475 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3476 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3477 // addr
3478 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3479 // pred
3480 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3481 return true;
3482}
3483
Jim Grosbach623a4542011-08-10 22:42:16 +00003484/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3485/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3486/// when they refer multiple MIOperands inside a single one.
3487bool ARMAsmParser::
3488cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3489 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3490 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3491 // Create a writeback register dummy placeholder.
3492 Inst.addOperand(MCOperand::CreateImm(0));
3493 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3494 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3495 return true;
3496}
3497
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003498/// cvtThumbMultiple- Convert parsed operands to MCInst.
3499/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3500/// when they refer multiple MIOperands inside a single one.
3501bool ARMAsmParser::
3502cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3503 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3504 // The second source operand must be the same register as the destination
3505 // operand.
3506 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003507 (((ARMOperand*)Operands[3])->getReg() !=
3508 ((ARMOperand*)Operands[5])->getReg()) &&
3509 (((ARMOperand*)Operands[3])->getReg() !=
3510 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003511 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003512 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003513 return false;
3514 }
3515 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3516 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003517 // If we have a three-operand form, make sure to set Rn to be the operand
3518 // that isn't the same as Rd.
3519 unsigned RegOp = 4;
3520 if (Operands.size() == 6 &&
3521 ((ARMOperand*)Operands[4])->getReg() ==
3522 ((ARMOperand*)Operands[3])->getReg())
3523 RegOp = 5;
3524 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3525 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003526 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3527
3528 return true;
3529}
Jim Grosbach623a4542011-08-10 22:42:16 +00003530
Jim Grosbach12431322011-10-24 22:16:58 +00003531bool ARMAsmParser::
3532cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3533 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3534 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003535 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003536 // Create a writeback register dummy placeholder.
3537 Inst.addOperand(MCOperand::CreateImm(0));
3538 // Vn
3539 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3540 // pred
3541 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3542 return true;
3543}
3544
3545bool ARMAsmParser::
3546cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3547 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3548 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003549 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003550 // Create a writeback register dummy placeholder.
3551 Inst.addOperand(MCOperand::CreateImm(0));
3552 // Vn
3553 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3554 // Vm
3555 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3556 // pred
3557 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3558 return true;
3559}
3560
Jim Grosbach4334e032011-10-31 21:50:31 +00003561bool ARMAsmParser::
3562cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3563 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3564 // Create a writeback register dummy placeholder.
3565 Inst.addOperand(MCOperand::CreateImm(0));
3566 // Vn
3567 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3568 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003569 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003570 // pred
3571 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3572 return true;
3573}
3574
3575bool ARMAsmParser::
3576cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3577 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3578 // Create a writeback register dummy placeholder.
3579 Inst.addOperand(MCOperand::CreateImm(0));
3580 // Vn
3581 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3582 // Vm
3583 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3584 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003585 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003586 // pred
3587 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3588 return true;
3589}
3590
Bill Wendlinge7176102010-11-06 22:36:58 +00003591/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003592/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003593bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003594parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003595 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003596 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003597 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003598 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003599 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003600
Sean Callanan18b83232010-01-19 21:44:56 +00003601 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003602 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003603 if (BaseRegNum == -1)
3604 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003605
Daniel Dunbar05710932011-01-18 05:34:17 +00003606 // The next token must either be a comma or a closing bracket.
3607 const AsmToken &Tok = Parser.getTok();
3608 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003609 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003610
Jim Grosbach7ce05792011-08-03 23:50:40 +00003611 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003612 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003613 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003614
Jim Grosbach7ce05792011-08-03 23:50:40 +00003615 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003616 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003617
Jim Grosbachfb12f352011-09-19 18:42:21 +00003618 // If there's a pre-indexing writeback marker, '!', just add it as a token
3619 // operand. It's rather odd, but syntactically valid.
3620 if (Parser.getTok().is(AsmToken::Exclaim)) {
3621 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3622 Parser.Lex(); // Eat the '!'.
3623 }
3624
Jim Grosbach7ce05792011-08-03 23:50:40 +00003625 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003626 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003627
Jim Grosbach7ce05792011-08-03 23:50:40 +00003628 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3629 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003630
Jim Grosbach57dcb852011-10-11 17:29:55 +00003631 // If we have a ':', it's an alignment specifier.
3632 if (Parser.getTok().is(AsmToken::Colon)) {
3633 Parser.Lex(); // Eat the ':'.
3634 E = Parser.getTok().getLoc();
3635
3636 const MCExpr *Expr;
3637 if (getParser().ParseExpression(Expr))
3638 return true;
3639
3640 // The expression has to be a constant. Memory references with relocations
3641 // don't come through here, as they use the <label> forms of the relevant
3642 // instructions.
3643 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3644 if (!CE)
3645 return Error (E, "constant expression expected");
3646
3647 unsigned Align = 0;
3648 switch (CE->getValue()) {
3649 default:
3650 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3651 case 64: Align = 8; break;
3652 case 128: Align = 16; break;
3653 case 256: Align = 32; break;
3654 }
3655
3656 // Now we should have the closing ']'
3657 E = Parser.getTok().getLoc();
3658 if (Parser.getTok().isNot(AsmToken::RBrac))
3659 return Error(E, "']' expected");
3660 Parser.Lex(); // Eat right bracket token.
3661
3662 // Don't worry about range checking the value here. That's handled by
3663 // the is*() predicates.
3664 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3665 ARM_AM::no_shift, 0, Align,
3666 false, S, E));
3667
3668 // If there's a pre-indexing writeback marker, '!', just add it as a token
3669 // operand.
3670 if (Parser.getTok().is(AsmToken::Exclaim)) {
3671 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3672 Parser.Lex(); // Eat the '!'.
3673 }
3674
3675 return false;
3676 }
3677
3678 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003679 // offset. Be friendly and also accept a plain integer (without a leading
3680 // hash) for gas compatibility.
3681 if (Parser.getTok().is(AsmToken::Hash) ||
3682 Parser.getTok().is(AsmToken::Integer)) {
3683 if (Parser.getTok().is(AsmToken::Hash))
3684 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003685 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003686
Owen Anderson0da10cf2011-08-29 19:36:44 +00003687 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003688 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003689 if (getParser().ParseExpression(Offset))
3690 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003691
3692 // The expression has to be a constant. Memory references with relocations
3693 // don't come through here, as they use the <label> forms of the relevant
3694 // instructions.
3695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3696 if (!CE)
3697 return Error (E, "constant expression expected");
3698
Owen Anderson0da10cf2011-08-29 19:36:44 +00003699 // If the constant was #-0, represent it as INT32_MIN.
3700 int32_t Val = CE->getValue();
3701 if (isNegative && Val == 0)
3702 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3703
Jim Grosbach7ce05792011-08-03 23:50:40 +00003704 // Now we should have the closing ']'
3705 E = Parser.getTok().getLoc();
3706 if (Parser.getTok().isNot(AsmToken::RBrac))
3707 return Error(E, "']' expected");
3708 Parser.Lex(); // Eat right bracket token.
3709
3710 // Don't worry about range checking the value here. That's handled by
3711 // the is*() predicates.
3712 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003713 ARM_AM::no_shift, 0, 0,
3714 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003715
3716 // If there's a pre-indexing writeback marker, '!', just add it as a token
3717 // operand.
3718 if (Parser.getTok().is(AsmToken::Exclaim)) {
3719 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3720 Parser.Lex(); // Eat the '!'.
3721 }
3722
3723 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003724 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003725
3726 // The register offset is optionally preceded by a '+' or '-'
3727 bool isNegative = false;
3728 if (Parser.getTok().is(AsmToken::Minus)) {
3729 isNegative = true;
3730 Parser.Lex(); // Eat the '-'.
3731 } else if (Parser.getTok().is(AsmToken::Plus)) {
3732 // Nothing to do.
3733 Parser.Lex(); // Eat the '+'.
3734 }
3735
3736 E = Parser.getTok().getLoc();
3737 int OffsetRegNum = tryParseRegister();
3738 if (OffsetRegNum == -1)
3739 return Error(E, "register expected");
3740
3741 // If there's a shift operator, handle it.
3742 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003743 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003744 if (Parser.getTok().is(AsmToken::Comma)) {
3745 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003746 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003747 return true;
3748 }
3749
3750 // Now we should have the closing ']'
3751 E = Parser.getTok().getLoc();
3752 if (Parser.getTok().isNot(AsmToken::RBrac))
3753 return Error(E, "']' expected");
3754 Parser.Lex(); // Eat right bracket token.
3755
3756 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003757 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003758 S, E));
3759
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003760 // If there's a pre-indexing writeback marker, '!', just add it as a token
3761 // operand.
3762 if (Parser.getTok().is(AsmToken::Exclaim)) {
3763 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3764 Parser.Lex(); // Eat the '!'.
3765 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003766
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003767 return false;
3768}
3769
Jim Grosbach7ce05792011-08-03 23:50:40 +00003770/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003771/// ( lsl | lsr | asr | ror ) , # shift_amount
3772/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003773/// return true if it parses a shift otherwise it returns false.
3774bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3775 unsigned &Amount) {
3776 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003777 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003778 if (Tok.isNot(AsmToken::Identifier))
3779 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003780 StringRef ShiftName = Tok.getString();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003781 if (ShiftName == "lsl" || ShiftName == "LSL")
Owen Anderson00828302011-03-18 22:50:18 +00003782 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003783 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003784 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003785 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003786 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003787 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003788 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003789 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003790 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003791 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003792 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003793 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003794
Jim Grosbach7ce05792011-08-03 23:50:40 +00003795 // rrx stands alone.
3796 Amount = 0;
3797 if (St != ARM_AM::rrx) {
3798 Loc = Parser.getTok().getLoc();
3799 // A '#' and a shift amount.
3800 const AsmToken &HashTok = Parser.getTok();
3801 if (HashTok.isNot(AsmToken::Hash))
3802 return Error(HashTok.getLoc(), "'#' expected");
3803 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003804
Jim Grosbach7ce05792011-08-03 23:50:40 +00003805 const MCExpr *Expr;
3806 if (getParser().ParseExpression(Expr))
3807 return true;
3808 // Range check the immediate.
3809 // lsl, ror: 0 <= imm <= 31
3810 // lsr, asr: 0 <= imm <= 32
3811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3812 if (!CE)
3813 return Error(Loc, "shift amount must be an immediate");
3814 int64_t Imm = CE->getValue();
3815 if (Imm < 0 ||
3816 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3817 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3818 return Error(Loc, "immediate shift value out of range");
3819 Amount = Imm;
3820 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003821
3822 return false;
3823}
3824
Jim Grosbach9d390362011-10-03 23:38:36 +00003825/// parseFPImm - A floating point immediate expression operand.
3826ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3827parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3828 SMLoc S = Parser.getTok().getLoc();
3829
3830 if (Parser.getTok().isNot(AsmToken::Hash))
3831 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003832
3833 // Disambiguate the VMOV forms that can accept an FP immediate.
3834 // vmov.f32 <sreg>, #imm
3835 // vmov.f64 <dreg>, #imm
3836 // vmov.f32 <dreg>, #imm @ vector f32x2
3837 // vmov.f32 <qreg>, #imm @ vector f32x4
3838 //
3839 // There are also the NEON VMOV instructions which expect an
3840 // integer constant. Make sure we don't try to parse an FPImm
3841 // for these:
3842 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
3843 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
3844 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
3845 TyOp->getToken() != ".f64"))
3846 return MatchOperand_NoMatch;
3847
Jim Grosbach9d390362011-10-03 23:38:36 +00003848 Parser.Lex(); // Eat the '#'.
3849
3850 // Handle negation, as that still comes through as a separate token.
3851 bool isNegative = false;
3852 if (Parser.getTok().is(AsmToken::Minus)) {
3853 isNegative = true;
3854 Parser.Lex();
3855 }
3856 const AsmToken &Tok = Parser.getTok();
3857 if (Tok.is(AsmToken::Real)) {
3858 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
3859 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3860 // If we had a '-' in front, toggle the sign bit.
3861 IntVal ^= (uint64_t)isNegative << 63;
3862 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
3863 Parser.Lex(); // Eat the token.
3864 if (Val == -1) {
3865 TokError("floating point value out of range");
3866 return MatchOperand_ParseFail;
3867 }
3868 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3869 return MatchOperand_Success;
3870 }
3871 if (Tok.is(AsmToken::Integer)) {
3872 int64_t Val = Tok.getIntVal();
3873 Parser.Lex(); // Eat the token.
3874 if (Val > 255 || Val < 0) {
3875 TokError("encoded floating point value out of range");
3876 return MatchOperand_ParseFail;
3877 }
3878 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
3879 return MatchOperand_Success;
3880 }
3881
3882 TokError("invalid floating point immediate");
3883 return MatchOperand_ParseFail;
3884}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003885/// Parse a arm instruction operand. For now this parses the operand regardless
3886/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003887bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003888 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00003889 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003890
3891 // Check if the current operand has a custom associated parser, if so, try to
3892 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00003893 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3894 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003895 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00003896 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3897 // there was a match, but an error occurred, in which case, just return that
3898 // the operand parsing failed.
3899 if (ResTy == MatchOperand_ParseFail)
3900 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00003901
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003902 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00003903 default:
3904 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00003905 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00003906 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003907 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003908 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00003909 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00003910 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00003911 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00003912 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00003913 else if (Res == -1) // irrecoverable error
3914 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00003915 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
3916 S = Parser.getTok().getLoc();
3917 Parser.Lex();
3918 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
3919 return false;
3920 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00003921
3922 // Fall though for the Identifier case that is not a register or a
3923 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00003924 }
Jim Grosbach758a5192011-10-26 21:14:08 +00003925 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00003926 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00003927 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00003928 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00003929 // This was not a register so parse other operands that start with an
3930 // identifier (like labels) as expressions and create them as immediates.
3931 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00003932 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00003933 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003934 return true;
Sean Callanan76264762010-04-02 22:27:05 +00003935 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003936 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
3937 return false;
3938 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003939 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003940 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00003941 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00003942 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00003943 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00003944 // #42 -> immediate.
3945 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00003946 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003947 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00003948 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00003949 const MCExpr *ImmVal;
3950 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00003951 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00003952 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00003953 if (CE) {
3954 int32_t Val = CE->getValue();
3955 if (isNegative && Val == 0)
3956 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00003957 }
Sean Callanan76264762010-04-02 22:27:05 +00003958 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00003959 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
3960 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00003961 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003962 case AsmToken::Colon: {
3963 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00003964 // FIXME: Check it's an expression prefix,
3965 // e.g. (FOO - :lower16:BAR) isn't legal.
3966 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00003967 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003968 return true;
3969
Evan Cheng75972122011-01-13 07:58:56 +00003970 const MCExpr *SubExprVal;
3971 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00003972 return true;
3973
Evan Cheng75972122011-01-13 07:58:56 +00003974 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
3975 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00003976 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00003977 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00003978 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003979 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00003980 }
3981}
3982
Jim Grosbach1355cf12011-07-26 17:10:22 +00003983// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00003984// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00003985bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00003986 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00003987
3988 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00003989 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00003990 Parser.Lex(); // Eat ':'
3991
3992 if (getLexer().isNot(AsmToken::Identifier)) {
3993 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
3994 return true;
3995 }
3996
3997 StringRef IDVal = Parser.getTok().getIdentifier();
3998 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00003999 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004000 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004001 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004002 } else {
4003 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4004 return true;
4005 }
4006 Parser.Lex();
4007
4008 if (getLexer().isNot(AsmToken::Colon)) {
4009 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4010 return true;
4011 }
4012 Parser.Lex(); // Eat the last ':'
4013 return false;
4014}
4015
Daniel Dunbar352e1482011-01-11 15:59:50 +00004016/// \brief Given a mnemonic, split out possible predication code and carry
4017/// setting letters to form a canonical mnemonic and flags.
4018//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004019// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004020// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004021StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004022 unsigned &PredicationCode,
4023 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004024 unsigned &ProcessorIMod,
4025 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004026 PredicationCode = ARMCC::AL;
4027 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004028 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004029
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004030 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004031 //
4032 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004033 if ((Mnemonic == "movs" && isThumb()) ||
4034 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4035 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4036 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4037 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4038 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4039 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4040 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004041 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004042
Jim Grosbach3f00e312011-07-11 17:09:57 +00004043 // First, split out any predication code. Ignore mnemonics we know aren't
4044 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004045 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004046 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004047 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004048 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004049 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4050 .Case("eq", ARMCC::EQ)
4051 .Case("ne", ARMCC::NE)
4052 .Case("hs", ARMCC::HS)
4053 .Case("cs", ARMCC::HS)
4054 .Case("lo", ARMCC::LO)
4055 .Case("cc", ARMCC::LO)
4056 .Case("mi", ARMCC::MI)
4057 .Case("pl", ARMCC::PL)
4058 .Case("vs", ARMCC::VS)
4059 .Case("vc", ARMCC::VC)
4060 .Case("hi", ARMCC::HI)
4061 .Case("ls", ARMCC::LS)
4062 .Case("ge", ARMCC::GE)
4063 .Case("lt", ARMCC::LT)
4064 .Case("gt", ARMCC::GT)
4065 .Case("le", ARMCC::LE)
4066 .Case("al", ARMCC::AL)
4067 .Default(~0U);
4068 if (CC != ~0U) {
4069 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4070 PredicationCode = CC;
4071 }
Bill Wendling52925b62010-10-29 23:50:21 +00004072 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004073
Daniel Dunbar352e1482011-01-11 15:59:50 +00004074 // Next, determine if we have a carry setting bit. We explicitly ignore all
4075 // the instructions we know end in 's'.
4076 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004077 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004078 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4079 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4080 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004081 Mnemonic == "vrsqrts" || Mnemonic == "srs" ||
4082 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004083 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4084 CarrySetting = true;
4085 }
4086
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004087 // The "cps" instruction can have a interrupt mode operand which is glued into
4088 // the mnemonic. Check if this is the case, split it and parse the imod op
4089 if (Mnemonic.startswith("cps")) {
4090 // Split out any imod code.
4091 unsigned IMod =
4092 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4093 .Case("ie", ARM_PROC::IE)
4094 .Case("id", ARM_PROC::ID)
4095 .Default(~0U);
4096 if (IMod != ~0U) {
4097 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4098 ProcessorIMod = IMod;
4099 }
4100 }
4101
Jim Grosbach89df9962011-08-26 21:43:41 +00004102 // The "it" instruction has the condition mask on the end of the mnemonic.
4103 if (Mnemonic.startswith("it")) {
4104 ITMask = Mnemonic.slice(2, Mnemonic.size());
4105 Mnemonic = Mnemonic.slice(0, 2);
4106 }
4107
Daniel Dunbar352e1482011-01-11 15:59:50 +00004108 return Mnemonic;
4109}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004110
4111/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4112/// inclusion of carry set or predication code operands.
4113//
4114// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004115void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004116getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004117 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004118 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4119 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004120 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004121 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004122 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004123 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004124 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004125 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004126 Mnemonic == "mla" || Mnemonic == "smlal" ||
4127 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004128 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004129 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004130 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004131
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004132 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4133 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4134 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4135 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004136 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4137 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004138 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004139 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4140 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4141 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004142 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4143 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004144 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004145 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004146 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004147 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004148
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004149 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004150 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004151 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004152 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004153 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004154}
4155
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004156bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4157 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004158 // FIXME: This is all horribly hacky. We really need a better way to deal
4159 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004160
4161 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4162 // another does not. Specifically, the MOVW instruction does not. So we
4163 // special case it here and remove the defaulted (non-setting) cc_out
4164 // operand if that's the instruction we're trying to match.
4165 //
4166 // We do this as post-processing of the explicit operands rather than just
4167 // conditionally adding the cc_out in the first place because we need
4168 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004169 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004170 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4171 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4172 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4173 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004174
4175 // Register-register 'add' for thumb does not have a cc_out operand
4176 // when there are only two register operands.
4177 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4178 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4179 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4180 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4181 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004182 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004183 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4184 // have to check the immediate range here since Thumb2 has a variant
4185 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004186 if (((isThumb() && Mnemonic == "add") ||
4187 (isThumbTwo() && Mnemonic == "sub")) &&
4188 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004189 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4190 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4191 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004192 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4193 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4194 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004195 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004196 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4197 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004198 // selecting via the generic "add" mnemonic, so to know that we
4199 // should remove the cc_out operand, we have to explicitly check that
4200 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004201 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4202 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004203 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4204 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4205 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4206 // Nest conditions rather than one big 'if' statement for readability.
4207 //
4208 // If either register is a high reg, it's either one of the SP
4209 // variants (handled above) or a 32-bit encoding, so we just
4210 // check against T3.
4211 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4212 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4213 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4214 return false;
4215 // If both registers are low, we're in an IT block, and the immediate is
4216 // in range, we should use encoding T1 instead, which has a cc_out.
4217 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004218 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004219 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4220 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4221 return false;
4222
4223 // Otherwise, we use encoding T4, which does not have a cc_out
4224 // operand.
4225 return true;
4226 }
4227
Jim Grosbach64944f42011-09-14 21:00:40 +00004228 // The thumb2 multiply instruction doesn't have a CCOut register, so
4229 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4230 // use the 16-bit encoding or not.
4231 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4232 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4233 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4234 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4235 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4236 // If the registers aren't low regs, the destination reg isn't the
4237 // same as one of the source regs, or the cc_out operand is zero
4238 // outside of an IT block, we have to use the 32-bit encoding, so
4239 // remove the cc_out operand.
4240 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4241 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004242 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004243 !inITBlock() ||
4244 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4245 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4246 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4247 static_cast<ARMOperand*>(Operands[4])->getReg())))
4248 return true;
4249
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004250 // Also check the 'mul' syntax variant that doesn't specify an explicit
4251 // destination register.
4252 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4253 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4254 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4255 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4256 // If the registers aren't low regs or the cc_out operand is zero
4257 // outside of an IT block, we have to use the 32-bit encoding, so
4258 // remove the cc_out operand.
4259 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4260 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4261 !inITBlock()))
4262 return true;
4263
Jim Grosbach64944f42011-09-14 21:00:40 +00004264
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004265
Jim Grosbachf69c8042011-08-24 21:42:27 +00004266 // Register-register 'add/sub' for thumb does not have a cc_out operand
4267 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4268 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4269 // right, this will result in better diagnostics (which operand is off)
4270 // anyway.
4271 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4272 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004273 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4274 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4275 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4276 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004277
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004278 return false;
4279}
4280
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004281static bool isDataTypeToken(StringRef Tok) {
4282 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4283 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4284 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4285 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4286 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4287 Tok == ".f" || Tok == ".d";
4288}
4289
4290// FIXME: This bit should probably be handled via an explicit match class
4291// in the .td files that matches the suffix instead of having it be
4292// a literal string token the way it is now.
4293static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4294 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4295}
4296
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004297/// Parse an arm instruction mnemonic followed by its operands.
4298bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4299 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4300 // Create the leading tokens for the mnemonic, split by '.' characters.
4301 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004302 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004303
Daniel Dunbar352e1482011-01-11 15:59:50 +00004304 // Split out the predication code and carry setting flag from the mnemonic.
4305 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004306 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004307 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004308 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004309 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004310 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004311
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004312 // In Thumb1, only the branch (B) instruction can be predicated.
4313 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4314 Parser.EatToEndOfStatement();
4315 return Error(NameLoc, "conditional execution not supported in Thumb1");
4316 }
4317
Jim Grosbachffa32252011-07-19 19:13:28 +00004318 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4319
Jim Grosbach89df9962011-08-26 21:43:41 +00004320 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4321 // is the mask as it will be for the IT encoding if the conditional
4322 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4323 // where the conditional bit0 is zero, the instruction post-processing
4324 // will adjust the mask accordingly.
4325 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004326 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4327 if (ITMask.size() > 3) {
4328 Parser.EatToEndOfStatement();
4329 return Error(Loc, "too many conditions on IT instruction");
4330 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004331 unsigned Mask = 8;
4332 for (unsigned i = ITMask.size(); i != 0; --i) {
4333 char pos = ITMask[i - 1];
4334 if (pos != 't' && pos != 'e') {
4335 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004336 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004337 }
4338 Mask >>= 1;
4339 if (ITMask[i - 1] == 't')
4340 Mask |= 8;
4341 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004342 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004343 }
4344
Jim Grosbachffa32252011-07-19 19:13:28 +00004345 // FIXME: This is all a pretty gross hack. We should automatically handle
4346 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004347
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004348 // Next, add the CCOut and ConditionCode operands, if needed.
4349 //
4350 // For mnemonics which can ever incorporate a carry setting bit or predication
4351 // code, our matching model involves us always generating CCOut and
4352 // ConditionCode operands to match the mnemonic "as written" and then we let
4353 // the matcher deal with finding the right instruction or generating an
4354 // appropriate error.
4355 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004356 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004357
Jim Grosbach33c16a22011-07-14 22:04:21 +00004358 // If we had a carry-set on an instruction that can't do that, issue an
4359 // error.
4360 if (!CanAcceptCarrySet && CarrySetting) {
4361 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004362 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004363 "' can not set flags, but 's' suffix specified");
4364 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004365 // If we had a predication code on an instruction that can't do that, issue an
4366 // error.
4367 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4368 Parser.EatToEndOfStatement();
4369 return Error(NameLoc, "instruction '" + Mnemonic +
4370 "' is not predicable, but condition code specified");
4371 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004372
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004373 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004374 if (CanAcceptCarrySet) {
4375 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004376 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004377 Loc));
4378 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004379
4380 // Add the predication code operand, if necessary.
4381 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004382 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4383 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004384 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004385 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004386 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004387
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004388 // Add the processor imod operand, if necessary.
4389 if (ProcessorIMod) {
4390 Operands.push_back(ARMOperand::CreateImm(
4391 MCConstantExpr::Create(ProcessorIMod, getContext()),
4392 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004393 }
4394
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004395 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004396 while (Next != StringRef::npos) {
4397 Start = Next;
4398 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004399 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004400
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004401 // Some NEON instructions have an optional datatype suffix that is
4402 // completely ignored. Check for that.
4403 if (isDataTypeToken(ExtraToken) &&
4404 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4405 continue;
4406
Jim Grosbach81d2e392011-09-07 16:06:04 +00004407 if (ExtraToken != ".n") {
4408 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4409 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4410 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004411 }
4412
4413 // Read the remaining operands.
4414 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004415 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004416 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004417 Parser.EatToEndOfStatement();
4418 return true;
4419 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004420
4421 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004422 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004423
4424 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004425 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004426 Parser.EatToEndOfStatement();
4427 return true;
4428 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004429 }
4430 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004431
Chris Lattnercbf8a982010-09-11 16:18:25 +00004432 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004433 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004434 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004435 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004436 }
Bill Wendling146018f2010-11-06 21:42:12 +00004437
Chris Lattner34e53142010-09-08 05:10:46 +00004438 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004439
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004440 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4441 // do and don't have a cc_out optional-def operand. With some spot-checks
4442 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004443 // parse and adjust accordingly before actually matching. We shouldn't ever
4444 // try to remove a cc_out operand that was explicitly set on the the
4445 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4446 // table driven matcher doesn't fit well with the ARM instruction set.
4447 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004448 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4449 Operands.erase(Operands.begin() + 1);
4450 delete Op;
4451 }
4452
Jim Grosbachcf121c32011-07-28 21:57:55 +00004453 // ARM mode 'blx' need special handling, as the register operand version
4454 // is predicable, but the label operand version is not. So, we can't rely
4455 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004456 // a k_CondCode operand in the list. If we're trying to match the label
4457 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004458 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4459 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4460 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4461 Operands.erase(Operands.begin() + 1);
4462 delete Op;
4463 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004464
4465 // The vector-compare-to-zero instructions have a literal token "#0" at
4466 // the end that comes to here as an immediate operand. Convert it to a
4467 // token to play nicely with the matcher.
4468 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4469 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4470 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4471 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4472 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4473 if (CE && CE->getValue() == 0) {
4474 Operands.erase(Operands.begin() + 5);
4475 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4476 delete Op;
4477 }
4478 }
Jim Grosbach68259142011-10-03 22:30:24 +00004479 // VCMP{E} does the same thing, but with a different operand count.
4480 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4481 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4482 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4483 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4484 if (CE && CE->getValue() == 0) {
4485 Operands.erase(Operands.begin() + 4);
4486 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4487 delete Op;
4488 }
4489 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004490 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4491 // end. Convert it to a token here.
4492 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4493 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4494 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4495 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4496 if (CE && CE->getValue() == 0) {
4497 Operands.erase(Operands.begin() + 5);
4498 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4499 delete Op;
4500 }
4501 }
4502
Chris Lattner98986712010-01-14 22:21:20 +00004503 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004504}
4505
Jim Grosbach189610f2011-07-26 18:25:39 +00004506// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004507
4508// return 'true' if register list contains non-low GPR registers,
4509// 'false' otherwise. If Reg is in the register list or is HiReg, set
4510// 'containsReg' to true.
4511static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4512 unsigned HiReg, bool &containsReg) {
4513 containsReg = false;
4514 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4515 unsigned OpReg = Inst.getOperand(i).getReg();
4516 if (OpReg == Reg)
4517 containsReg = true;
4518 // Anything other than a low register isn't legal here.
4519 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4520 return true;
4521 }
4522 return false;
4523}
4524
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004525// Check if the specified regisgter is in the register list of the inst,
4526// starting at the indicated operand number.
4527static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4528 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4529 unsigned OpReg = Inst.getOperand(i).getReg();
4530 if (OpReg == Reg)
4531 return true;
4532 }
4533 return false;
4534}
4535
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004536// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4537// the ARMInsts array) instead. Getting that here requires awkward
4538// API changes, though. Better way?
4539namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004540extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004541}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004542static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004543 return ARMInsts[Opcode];
4544}
4545
Jim Grosbach189610f2011-07-26 18:25:39 +00004546// FIXME: We would really like to be able to tablegen'erate this.
4547bool ARMAsmParser::
4548validateInstruction(MCInst &Inst,
4549 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004550 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004551 SMLoc Loc = Operands[0]->getStartLoc();
4552 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004553 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4554 // being allowed in IT blocks, but not being predicable. It just always
4555 // executes.
4556 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004557 unsigned bit = 1;
4558 if (ITState.FirstCond)
4559 ITState.FirstCond = false;
4560 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004561 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004562 // The instruction must be predicable.
4563 if (!MCID.isPredicable())
4564 return Error(Loc, "instructions in IT block must be predicable");
4565 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4566 unsigned ITCond = bit ? ITState.Cond :
4567 ARMCC::getOppositeCondition(ITState.Cond);
4568 if (Cond != ITCond) {
4569 // Find the condition code Operand to get its SMLoc information.
4570 SMLoc CondLoc;
4571 for (unsigned i = 1; i < Operands.size(); ++i)
4572 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4573 CondLoc = Operands[i]->getStartLoc();
4574 return Error(CondLoc, "incorrect condition in IT block; got '" +
4575 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4576 "', but expected '" +
4577 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4578 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004579 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004580 } else if (isThumbTwo() && MCID.isPredicable() &&
4581 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004582 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4583 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004584 return Error(Loc, "predicated instructions must be in IT block");
4585
Jim Grosbach189610f2011-07-26 18:25:39 +00004586 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004587 case ARM::LDRD:
4588 case ARM::LDRD_PRE:
4589 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004590 case ARM::LDREXD: {
4591 // Rt2 must be Rt + 1.
4592 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4593 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4594 if (Rt2 != Rt + 1)
4595 return Error(Operands[3]->getStartLoc(),
4596 "destination operands must be sequential");
4597 return false;
4598 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004599 case ARM::STRD: {
4600 // Rt2 must be Rt + 1.
4601 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4602 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4603 if (Rt2 != Rt + 1)
4604 return Error(Operands[3]->getStartLoc(),
4605 "source operands must be sequential");
4606 return false;
4607 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004608 case ARM::STRD_PRE:
4609 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004610 case ARM::STREXD: {
4611 // Rt2 must be Rt + 1.
4612 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4613 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4614 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004615 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004616 "source operands must be sequential");
4617 return false;
4618 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004619 case ARM::SBFX:
4620 case ARM::UBFX: {
4621 // width must be in range [1, 32-lsb]
4622 unsigned lsb = Inst.getOperand(2).getImm();
4623 unsigned widthm1 = Inst.getOperand(3).getImm();
4624 if (widthm1 >= 32 - lsb)
4625 return Error(Operands[5]->getStartLoc(),
4626 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004627 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004628 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004629 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004630 // If we're parsing Thumb2, the .w variant is available and handles
4631 // most cases that are normally illegal for a Thumb1 LDM
4632 // instruction. We'll make the transformation in processInstruction()
4633 // if necessary.
4634 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004635 // Thumb LDM instructions are writeback iff the base register is not
4636 // in the register list.
4637 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004638 bool hasWritebackToken =
4639 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4640 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004641 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004642 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004643 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4644 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004645 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004646 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004647 return Error(Operands[2]->getStartLoc(),
4648 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004649 // If we should not have writeback, there must not be a '!'. This is
4650 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004651 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004652 return Error(Operands[3]->getStartLoc(),
4653 "writeback operator '!' not allowed when base register "
4654 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004655
4656 break;
4657 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004658 case ARM::t2LDMIA_UPD: {
4659 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4660 return Error(Operands[4]->getStartLoc(),
4661 "writeback operator '!' not allowed when base register "
4662 "in register list");
4663 break;
4664 }
Jim Grosbach54026372011-11-10 23:17:11 +00004665 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4666 // so only issue a diagnostic for thumb1. The instructions will be
4667 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004668 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004669 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004670 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4671 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004672 return Error(Operands[2]->getStartLoc(),
4673 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004674 break;
4675 }
4676 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004677 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004678 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4679 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004680 return Error(Operands[2]->getStartLoc(),
4681 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004682 break;
4683 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004684 case ARM::tSTMIA_UPD: {
4685 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004686 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004687 return Error(Operands[4]->getStartLoc(),
4688 "registers must be in range r0-r7");
4689 break;
4690 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004691 }
4692
4693 return false;
4694}
4695
Jim Grosbach83ec8772011-11-10 23:42:14 +00004696bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004697processInstruction(MCInst &Inst,
4698 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4699 switch (Inst.getOpcode()) {
Jim Grosbach71810ab2011-11-10 16:44:55 +00004700 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00004701 case ARM::ASRr:
4702 case ARM::LSRr:
4703 case ARM::LSLr:
4704 case ARM::RORr: {
4705 ARM_AM::ShiftOpc ShiftTy;
4706 switch(Inst.getOpcode()) {
4707 default: llvm_unreachable("unexpected opcode!");
4708 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
4709 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
4710 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
4711 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
4712 }
4713 // A shift by zero is a plain MOVr, not a MOVsi.
4714 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
4715 MCInst TmpInst;
4716 TmpInst.setOpcode(ARM::MOVsr);
4717 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4718 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4719 TmpInst.addOperand(Inst.getOperand(2)); // Rm
4720 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4721 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4722 TmpInst.addOperand(Inst.getOperand(4));
4723 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4724 Inst = TmpInst;
4725 return true;
4726 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00004727 case ARM::ASRi:
4728 case ARM::LSRi:
4729 case ARM::LSLi:
4730 case ARM::RORi: {
4731 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004732 switch(Inst.getOpcode()) {
4733 default: llvm_unreachable("unexpected opcode!");
4734 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
4735 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
4736 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
4737 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
4738 }
4739 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00004740 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00004741 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
4742 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004743 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00004744 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00004745 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4746 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00004747 if (Opc == ARM::MOVsi)
4748 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00004749 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
4750 TmpInst.addOperand(Inst.getOperand(4));
4751 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
4752 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004753 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00004754 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00004755 case ARM::RRXi: {
4756 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
4757 MCInst TmpInst;
4758 TmpInst.setOpcode(ARM::MOVsi);
4759 TmpInst.addOperand(Inst.getOperand(0)); // Rd
4760 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4761 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
4762 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4763 TmpInst.addOperand(Inst.getOperand(3));
4764 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
4765 Inst = TmpInst;
4766 return true;
4767 }
Jim Grosbach0352b462011-11-10 23:58:34 +00004768 case ARM::t2LDMIA_UPD: {
4769 // If this is a load of a single register, then we should use
4770 // a post-indexed LDR instruction instead, per the ARM ARM.
4771 if (Inst.getNumOperands() != 5)
4772 return false;
4773 MCInst TmpInst;
4774 TmpInst.setOpcode(ARM::t2LDR_POST);
4775 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4776 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4777 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4778 TmpInst.addOperand(MCOperand::CreateImm(4));
4779 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4780 TmpInst.addOperand(Inst.getOperand(3));
4781 Inst = TmpInst;
4782 return true;
4783 }
4784 case ARM::t2STMDB_UPD: {
4785 // If this is a store of a single register, then we should use
4786 // a pre-indexed STR instruction instead, per the ARM ARM.
4787 if (Inst.getNumOperands() != 5)
4788 return false;
4789 MCInst TmpInst;
4790 TmpInst.setOpcode(ARM::t2STR_PRE);
4791 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4792 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4793 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4794 TmpInst.addOperand(MCOperand::CreateImm(-4));
4795 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4796 TmpInst.addOperand(Inst.getOperand(3));
4797 Inst = TmpInst;
4798 return true;
4799 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00004800 case ARM::LDMIA_UPD:
4801 // If this is a load of a single register via a 'pop', then we should use
4802 // a post-indexed LDR instruction instead, per the ARM ARM.
4803 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
4804 Inst.getNumOperands() == 5) {
4805 MCInst TmpInst;
4806 TmpInst.setOpcode(ARM::LDR_POST_IMM);
4807 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4808 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4809 TmpInst.addOperand(Inst.getOperand(1)); // Rn
4810 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
4811 TmpInst.addOperand(MCOperand::CreateImm(4));
4812 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4813 TmpInst.addOperand(Inst.getOperand(3));
4814 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004815 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00004816 }
4817 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00004818 case ARM::STMDB_UPD:
4819 // If this is a store of a single register via a 'push', then we should use
4820 // a pre-indexed STR instruction instead, per the ARM ARM.
4821 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
4822 Inst.getNumOperands() == 5) {
4823 MCInst TmpInst;
4824 TmpInst.setOpcode(ARM::STR_PRE_IMM);
4825 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
4826 TmpInst.addOperand(Inst.getOperand(4)); // Rt
4827 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
4828 TmpInst.addOperand(MCOperand::CreateImm(-4));
4829 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
4830 TmpInst.addOperand(Inst.getOperand(3));
4831 Inst = TmpInst;
4832 }
4833 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004834 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00004835 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4836 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4837 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4838 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004839 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004840 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004841 return true;
4842 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00004843 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004844 case ARM::tSUBi8:
4845 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
4846 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
4847 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
4848 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00004849 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00004850 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004851 return true;
4852 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00004853 break;
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004854 case ARM::tB:
4855 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004856 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004857 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004858 return true;
4859 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004860 break;
4861 case ARM::t2B:
4862 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004863 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004864 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004865 return true;
4866 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004867 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00004868 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00004869 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004870 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00004871 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004872 return true;
4873 }
Jim Grosbachc0755102011-08-31 21:17:31 +00004874 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00004875 case ARM::tBcc:
4876 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00004877 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00004878 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004879 return true;
4880 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00004881 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004882 case ARM::tLDMIA: {
4883 // If the register list contains any high registers, or if the writeback
4884 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
4885 // instead if we're in Thumb2. Otherwise, this should have generated
4886 // an error in validateInstruction().
4887 unsigned Rn = Inst.getOperand(0).getReg();
4888 bool hasWritebackToken =
4889 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4890 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
4891 bool listContainsBase;
4892 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
4893 (!listContainsBase && !hasWritebackToken) ||
4894 (listContainsBase && hasWritebackToken)) {
4895 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4896 assert (isThumbTwo());
4897 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
4898 // If we're switching to the updating version, we need to insert
4899 // the writeback tied operand.
4900 if (hasWritebackToken)
4901 Inst.insert(Inst.begin(),
4902 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004903 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004904 }
4905 break;
4906 }
Jim Grosbach8213c962011-09-16 20:50:13 +00004907 case ARM::tSTMIA_UPD: {
4908 // If the register list contains any high registers, we need to use
4909 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4910 // should have generated an error in validateInstruction().
4911 unsigned Rn = Inst.getOperand(0).getReg();
4912 bool listContainsBase;
4913 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
4914 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
4915 assert (isThumbTwo());
4916 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00004917 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00004918 }
4919 break;
4920 }
Jim Grosbach54026372011-11-10 23:17:11 +00004921 case ARM::tPOP: {
4922 bool listContainsBase;
4923 // If the register list contains any high registers, we need to use
4924 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
4925 // should have generated an error in validateInstruction().
4926 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004927 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004928 assert (isThumbTwo());
4929 Inst.setOpcode(ARM::t2LDMIA_UPD);
4930 // Add the base register and writeback operands.
4931 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4932 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004933 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004934 }
4935 case ARM::tPUSH: {
4936 bool listContainsBase;
4937 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00004938 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00004939 assert (isThumbTwo());
4940 Inst.setOpcode(ARM::t2STMDB_UPD);
4941 // Add the base register and writeback operands.
4942 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
4943 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00004944 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00004945 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004946 case ARM::t2MOVi: {
4947 // If we can use the 16-bit encoding and the user didn't explicitly
4948 // request the 32-bit variant, transform it here.
4949 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4950 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00004951 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
4952 Inst.getOperand(4).getReg() == ARM::CPSR) ||
4953 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004954 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4955 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4956 // The operands aren't in the same order for tMOVi8...
4957 MCInst TmpInst;
4958 TmpInst.setOpcode(ARM::tMOVi8);
4959 TmpInst.addOperand(Inst.getOperand(0));
4960 TmpInst.addOperand(Inst.getOperand(4));
4961 TmpInst.addOperand(Inst.getOperand(1));
4962 TmpInst.addOperand(Inst.getOperand(2));
4963 TmpInst.addOperand(Inst.getOperand(3));
4964 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004965 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004966 }
4967 break;
4968 }
4969 case ARM::t2MOVr: {
4970 // If we can use the 16-bit encoding and the user didn't explicitly
4971 // request the 32-bit variant, transform it here.
4972 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4973 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4974 Inst.getOperand(2).getImm() == ARMCC::AL &&
4975 Inst.getOperand(4).getReg() == ARM::CPSR &&
4976 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
4977 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
4978 // The operands aren't the same for tMOV[S]r... (no cc_out)
4979 MCInst TmpInst;
4980 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
4981 TmpInst.addOperand(Inst.getOperand(0));
4982 TmpInst.addOperand(Inst.getOperand(1));
4983 TmpInst.addOperand(Inst.getOperand(2));
4984 TmpInst.addOperand(Inst.getOperand(3));
4985 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00004986 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004987 }
4988 break;
4989 }
Jim Grosbach326efe52011-09-19 20:29:33 +00004990 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00004991 case ARM::t2SXTB:
4992 case ARM::t2UXTH:
4993 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00004994 // If we can use the 16-bit encoding and the user didn't explicitly
4995 // request the 32-bit variant, transform it here.
4996 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
4997 isARMLowRegister(Inst.getOperand(1).getReg()) &&
4998 Inst.getOperand(2).getImm() == 0 &&
4999 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5000 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005001 unsigned NewOpc;
5002 switch (Inst.getOpcode()) {
5003 default: llvm_unreachable("Illegal opcode!");
5004 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5005 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5006 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5007 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5008 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005009 // The operands aren't the same for thumb1 (no rotate operand).
5010 MCInst TmpInst;
5011 TmpInst.setOpcode(NewOpc);
5012 TmpInst.addOperand(Inst.getOperand(0));
5013 TmpInst.addOperand(Inst.getOperand(1));
5014 TmpInst.addOperand(Inst.getOperand(3));
5015 TmpInst.addOperand(Inst.getOperand(4));
5016 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005017 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005018 }
5019 break;
5020 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005021 case ARM::t2IT: {
5022 // The mask bits for all but the first condition are represented as
5023 // the low bit of the condition code value implies 't'. We currently
5024 // always have 1 implies 't', so XOR toggle the bits if the low bit
5025 // of the condition code is zero. The encoding also expects the low
5026 // bit of the condition to be encoded as bit 4 of the mask operand,
5027 // so mask that in if needed
5028 MCOperand &MO = Inst.getOperand(1);
5029 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005030 unsigned OrigMask = Mask;
5031 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005032 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005033 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5034 for (unsigned i = 3; i != TZ; --i)
5035 Mask ^= 1 << i;
5036 } else
5037 Mask |= 0x10;
5038 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005039
5040 // Set up the IT block state according to the IT instruction we just
5041 // matched.
5042 assert(!inITBlock() && "nested IT blocks?!");
5043 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5044 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5045 ITState.CurPosition = 0;
5046 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005047 break;
5048 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005049 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005050 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005051}
5052
Jim Grosbach47a0d522011-08-16 20:45:50 +00005053unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5054 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5055 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005056 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005057 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005058 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5059 assert(MCID.hasOptionalDef() &&
5060 "optionally flag setting instruction missing optional def operand");
5061 assert(MCID.NumOperands == Inst.getNumOperands() &&
5062 "operand count mismatch!");
5063 // Find the optional-def operand (cc_out).
5064 unsigned OpNo;
5065 for (OpNo = 0;
5066 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5067 ++OpNo)
5068 ;
5069 // If we're parsing Thumb1, reject it completely.
5070 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5071 return Match_MnemonicFail;
5072 // If we're parsing Thumb2, which form is legal depends on whether we're
5073 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005074 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5075 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005076 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005077 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5078 inITBlock())
5079 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005080 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005081 // Some high-register supporting Thumb1 encodings only allow both registers
5082 // to be from r0-r7 when in Thumb2.
5083 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5084 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5085 isARMLowRegister(Inst.getOperand(2).getReg()))
5086 return Match_RequiresThumb2;
5087 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005088 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005089 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5090 isARMLowRegister(Inst.getOperand(1).getReg()))
5091 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005092 return Match_Success;
5093}
5094
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005095bool ARMAsmParser::
5096MatchAndEmitInstruction(SMLoc IDLoc,
5097 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5098 MCStreamer &Out) {
5099 MCInst Inst;
5100 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005101 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005102 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005103 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005104 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005105 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005106 // Context sensitive operand constraints aren't handled by the matcher,
5107 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005108 if (validateInstruction(Inst, Operands)) {
5109 // Still progress the IT block, otherwise one wrong condition causes
5110 // nasty cascading errors.
5111 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005112 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005113 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005114
Jim Grosbachf8fce712011-08-11 17:35:48 +00005115 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005116 // encoding is selected. Loop on it while changes happen so the
5117 // individual transformations can chain off each other. E.g.,
5118 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5119 while (processInstruction(Inst, Operands))
5120 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005121
Jim Grosbacha1109882011-09-02 23:22:08 +00005122 // Only move forward at the very end so that everything in validate
5123 // and process gets a consistent answer about whether we're in an IT
5124 // block.
5125 forwardITPosition();
5126
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005127 Out.EmitInstruction(Inst);
5128 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005129 case Match_MissingFeature:
5130 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5131 return true;
5132 case Match_InvalidOperand: {
5133 SMLoc ErrorLoc = IDLoc;
5134 if (ErrorInfo != ~0U) {
5135 if (ErrorInfo >= Operands.size())
5136 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005137
Chris Lattnere73d4f82010-10-28 21:41:58 +00005138 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5139 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5140 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005141
Chris Lattnere73d4f82010-10-28 21:41:58 +00005142 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005143 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005144 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005145 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005146 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005147 // The converter function will have already emited a diagnostic.
5148 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005149 case Match_RequiresNotITBlock:
5150 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005151 case Match_RequiresITBlock:
5152 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005153 case Match_RequiresV6:
5154 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5155 case Match_RequiresThumb2:
5156 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005157 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005158
Eric Christopherc223e2b2010-10-29 09:26:59 +00005159 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005160 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005161}
5162
Jim Grosbach1355cf12011-07-26 17:10:22 +00005163/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005164bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5165 StringRef IDVal = DirectiveID.getIdentifier();
5166 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005167 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005168 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005169 return parseDirectiveThumb(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005170 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005171 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005172 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005173 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005174 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005175 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005176 return true;
5177}
5178
Jim Grosbach1355cf12011-07-26 17:10:22 +00005179/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005180/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005181bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005182 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5183 for (;;) {
5184 const MCExpr *Value;
5185 if (getParser().ParseExpression(Value))
5186 return true;
5187
Chris Lattneraaec2052010-01-19 19:46:13 +00005188 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005189
5190 if (getLexer().is(AsmToken::EndOfStatement))
5191 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005192
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005193 // FIXME: Improve diagnostic.
5194 if (getLexer().isNot(AsmToken::Comma))
5195 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005196 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005197 }
5198 }
5199
Sean Callananb9a25b72010-01-19 20:27:46 +00005200 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005201 return false;
5202}
5203
Jim Grosbach1355cf12011-07-26 17:10:22 +00005204/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005205/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005206bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005207 if (getLexer().isNot(AsmToken::EndOfStatement))
5208 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005209 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005210
5211 // TODO: set thumb mode
5212 // TODO: tell the MC streamer the mode
5213 // getParser().getStreamer().Emit???();
5214 return false;
5215}
5216
Jim Grosbach1355cf12011-07-26 17:10:22 +00005217/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005218/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005219bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005220 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5221 bool isMachO = MAI.hasSubsectionsViaSymbols();
5222 StringRef Name;
5223
5224 // Darwin asm has function name after .thumb_func direction
5225 // ELF doesn't
5226 if (isMachO) {
5227 const AsmToken &Tok = Parser.getTok();
5228 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5229 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005230 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005231 Parser.Lex(); // Consume the identifier token.
5232 }
5233
Jim Grosbachd475f862011-11-10 20:48:53 +00005234 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005235 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005236 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005237
Rafael Espindola64695402011-05-16 16:17:21 +00005238 // FIXME: assuming function name will be the line following .thumb_func
5239 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005240 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005241 }
5242
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005243 // Mark symbol as a thumb symbol.
5244 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5245 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005246 return false;
5247}
5248
Jim Grosbach1355cf12011-07-26 17:10:22 +00005249/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005250/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005251bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005252 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005253 if (Tok.isNot(AsmToken::Identifier))
5254 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005255 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005256 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005257 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005258 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005259 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005260 else
5261 return Error(L, "unrecognized syntax mode in .syntax directive");
5262
5263 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005264 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005265 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005266
5267 // TODO tell the MC streamer the mode
5268 // getParser().getStreamer().Emit???();
5269 return false;
5270}
5271
Jim Grosbach1355cf12011-07-26 17:10:22 +00005272/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005273/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005274bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005275 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005276 if (Tok.isNot(AsmToken::Integer))
5277 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005278 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005279 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005280 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005281 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005282 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005283 else
5284 return Error(L, "invalid operand to .code directive");
5285
5286 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005287 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005288 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005289
Evan Cheng32869202011-07-08 22:36:29 +00005290 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005291 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005292 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005293 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005294 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005295 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005296 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005297 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005298 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005299
Kevin Enderby515d5092009-10-15 20:48:48 +00005300 return false;
5301}
5302
Sean Callanan90b70972010-04-07 20:29:34 +00005303extern "C" void LLVMInitializeARMAsmLexer();
5304
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005305/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005306extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005307 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5308 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005309 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005310}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005311
Chris Lattner0692ee62010-09-06 19:11:01 +00005312#define GET_REGISTER_MATCHER
5313#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005314#include "ARMGenAsmMatcher.inc"