blob: 16878b25548a640fe4486210b2d8bcc9a320eee2 [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 Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
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);
Jim Grosbach9a70df92011-12-07 18:04:19 +000095 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveThumbFunc(SMLoc L);
97 bool parseDirectiveCode(SMLoc L);
98 bool parseDirectiveSyntax(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +000099
Jim Grosbach1355cf12011-07-26 17:10:22 +0000100 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000101 bool &CarrySetting, unsigned &ProcessorIMod,
102 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000103 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000104 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000105
Evan Chengebdeeab2011-07-08 01:53:10 +0000106 bool isThumb() const {
107 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000108 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000109 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000110 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000111 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000112 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000113 bool isThumbTwo() const {
114 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
115 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000116 bool hasV6Ops() const {
117 return STI.getFeatureBits() & ARM::HasV6Ops;
118 }
James Molloyacad68d2011-09-28 14:21:38 +0000119 bool hasV7Ops() const {
120 return STI.getFeatureBits() & ARM::HasV7Ops;
121 }
Evan Cheng32869202011-07-08 22:36:29 +0000122 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000123 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
124 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool isMClass() const {
127 return STI.getFeatureBits() & ARM::FeatureMClass;
128 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000129
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000130 /// @name Auto-generated Match Functions
131 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000132
Chris Lattner0692ee62010-09-06 19:11:01 +0000133#define GET_ASSEMBLER_HEADER
134#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000136 /// }
137
Jim Grosbach89df9962011-08-26 21:43:41 +0000138 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000139 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000140 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000141 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000142 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000143 OperandMatchResultTy parseCoprocOptionOperand(
144 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000145 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000146 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000147 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000148 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000149 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000150 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000151 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
152 StringRef Op, int Low, int High);
153 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
154 return parsePKHImm(O, "lsl", 0, 31);
155 }
156 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
157 return parsePKHImm(O, "asr", 1, 32);
158 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000159 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000160 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000161 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000162 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000163 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000164 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000165 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000166 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000167 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000168
169 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000170 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
171 const SmallVectorImpl<MCParsedAsmOperand*> &);
172 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
173 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000174 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
175 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000176 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
177 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000178 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000179 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000180 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
181 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000182 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
183 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000184 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000185 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000186 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000188 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
190 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
192 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
193 const SmallVectorImpl<MCParsedAsmOperand*> &);
194 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000196 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000198 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000200 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000202 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000204 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000208 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
210 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000212
213 bool validateInstruction(MCInst &Inst,
214 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000215 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000216 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000217 bool shouldOmitCCOutOperand(StringRef Mnemonic,
218 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000220public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000221 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000222 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000223 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000224 Match_RequiresV6,
225 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000226 };
227
Evan Chengffc0e732011-07-09 05:47:46 +0000228 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000229 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000230 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000231
Evan Chengebdeeab2011-07-08 01:53:10 +0000232 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000233 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000234
235 // Not in an ITBlock to start with.
236 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000238
Jim Grosbach1355cf12011-07-26 17:10:22 +0000239 // Implementation of the MCTargetAsmParser interface:
240 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
241 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000242 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000243 bool ParseDirective(AsmToken DirectiveID);
244
Jim Grosbach47a0d522011-08-16 20:45:50 +0000245 unsigned checkTargetMatchPredicate(MCInst &Inst);
246
Jim Grosbach1355cf12011-07-26 17:10:22 +0000247 bool MatchAndEmitInstruction(SMLoc IDLoc,
248 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
249 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000250};
Jim Grosbach16c74252010-10-29 14:46:02 +0000251} // end anonymous namespace
252
Chris Lattner3a697562010-10-28 17:20:03 +0000253namespace {
254
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000255/// ARMOperand - Instances of this class represent a parsed ARM machine
256/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000257class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000258 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000259 k_CondCode,
260 k_CCOut,
261 k_ITCondMask,
262 k_CoprocNum,
263 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000264 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000265 k_Immediate,
266 k_FPImmediate,
267 k_MemBarrierOpt,
268 k_Memory,
269 k_PostIndexRegister,
270 k_MSRMask,
271 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000272 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000273 k_Register,
274 k_RegisterList,
275 k_DPRRegisterList,
276 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000277 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000278 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000279 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_ShiftedRegister,
281 k_ShiftedImmediate,
282 k_ShifterImmediate,
283 k_RotateImmediate,
284 k_BitfieldDescriptor,
285 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000286 } Kind;
287
Sean Callanan76264762010-04-02 22:27:05 +0000288 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000289 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000290
291 union {
292 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000293 ARMCC::CondCodes Val;
294 } CC;
295
296 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000297 unsigned Val;
298 } Cop;
299
300 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000301 unsigned Val;
302 } CoprocOption;
303
304 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000305 unsigned Mask:4;
306 } ITMask;
307
308 struct {
309 ARM_MB::MemBOpt Val;
310 } MBOpt;
311
312 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000313 ARM_PROC::IFlags Val;
314 } IFlags;
315
316 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000317 unsigned Val;
318 } MMask;
319
320 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000321 const char *Data;
322 unsigned Length;
323 } Tok;
324
325 struct {
326 unsigned RegNum;
327 } Reg;
328
Jim Grosbach862019c2011-10-18 23:02:30 +0000329 // A vector register list is a sequential list of 1 to 4 registers.
330 struct {
331 unsigned RegNum;
332 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000333 unsigned LaneIndex;
Jim Grosbach862019c2011-10-18 23:02:30 +0000334 } VectorList;
335
Bill Wendling8155e5b2010-11-06 22:19:43 +0000336 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000337 unsigned Val;
338 } VectorIndex;
339
340 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000341 const MCExpr *Val;
342 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000343
Jim Grosbach9d390362011-10-03 23:38:36 +0000344 struct {
345 unsigned Val; // encoded 8-bit representation
346 } FPImm;
347
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000348 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000349 struct {
350 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000351 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
352 // was specified.
353 const MCConstantExpr *OffsetImm; // Offset immediate value
354 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
355 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000356 unsigned ShiftImm; // shift for OffsetReg.
357 unsigned Alignment; // 0 = no alignment specified
358 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000360 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000361
362 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000363 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000364 bool isAdd;
365 ARM_AM::ShiftOpc ShiftTy;
366 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 } PostIdxReg;
368
369 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000370 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000371 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000372 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000373 struct {
374 ARM_AM::ShiftOpc ShiftTy;
375 unsigned SrcReg;
376 unsigned ShiftReg;
377 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000378 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000379 struct {
380 ARM_AM::ShiftOpc ShiftTy;
381 unsigned SrcReg;
382 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000383 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000384 struct {
385 unsigned Imm;
386 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000387 struct {
388 unsigned LSB;
389 unsigned Width;
390 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000391 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000392
Bill Wendling146018f2010-11-06 21:42:12 +0000393 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
394public:
Sean Callanan76264762010-04-02 22:27:05 +0000395 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
396 Kind = o.Kind;
397 StartLoc = o.StartLoc;
398 EndLoc = o.EndLoc;
399 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000400 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000401 CC = o.CC;
402 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000403 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000404 ITMask = o.ITMask;
405 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000406 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000407 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000408 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000409 case k_CCOut:
410 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000411 Reg = o.Reg;
412 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000413 case k_RegisterList:
414 case k_DPRRegisterList:
415 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000416 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000417 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000418 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000419 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000420 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000421 VectorList = o.VectorList;
422 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000423 case k_CoprocNum:
424 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000425 Cop = o.Cop;
426 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000427 case k_CoprocOption:
428 CoprocOption = o.CoprocOption;
429 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000430 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000431 Imm = o.Imm;
432 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000433 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000434 FPImm = o.FPImm;
435 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000436 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000437 MBOpt = o.MBOpt;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000440 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000441 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000442 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000443 PostIdxReg = o.PostIdxReg;
444 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000445 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000446 MMask = o.MMask;
447 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000448 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000449 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000450 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000451 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000452 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000453 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000454 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000455 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000456 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000457 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000458 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000459 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000460 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000461 RotImm = o.RotImm;
462 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000463 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000464 Bitfield = o.Bitfield;
465 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000466 case k_VectorIndex:
467 VectorIndex = o.VectorIndex;
468 break;
Sean Callanan76264762010-04-02 22:27:05 +0000469 }
470 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000471
Sean Callanan76264762010-04-02 22:27:05 +0000472 /// getStartLoc - Get the location of the first token of this operand.
473 SMLoc getStartLoc() const { return StartLoc; }
474 /// getEndLoc - Get the location of the last token of this operand.
475 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000476
Daniel Dunbar8462b302010-08-11 06:36:53 +0000477 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000478 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000479 return CC.Val;
480 }
481
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000482 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000484 return Cop.Val;
485 }
486
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000487 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489 return StringRef(Tok.Data, Tok.Length);
490 }
491
492 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000494 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 }
496
Bill Wendling5fa22a12010-11-09 23:28:44 +0000497 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
499 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000500 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000501 }
502
Kevin Enderbycfe07242009-10-13 22:19:02 +0000503 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000504 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000505 return Imm.Val;
506 }
507
Jim Grosbach9d390362011-10-03 23:38:36 +0000508 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000509 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000510 return FPImm.Val;
511 }
512
Jim Grosbach460a9052011-10-07 23:56:00 +0000513 unsigned getVectorIndex() const {
514 assert(Kind == k_VectorIndex && "Invalid access!");
515 return VectorIndex.Val;
516 }
517
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000518 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000519 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000520 return MBOpt.Val;
521 }
522
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000523 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000525 return IFlags.Val;
526 }
527
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000528 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000530 return MMask.Val;
531 }
532
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000533 bool isCoprocNum() const { return Kind == k_CoprocNum; }
534 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000535 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000536 bool isCondCode() const { return Kind == k_CondCode; }
537 bool isCCOut() const { return Kind == k_CCOut; }
538 bool isITMask() const { return Kind == k_ITCondMask; }
539 bool isITCondCode() const { return Kind == k_CondCode; }
540 bool isImm() const { return Kind == k_Immediate; }
541 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000542 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000544 return false;
545 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
546 if (!CE) return false;
547 int64_t Value = CE->getValue();
548 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
549 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000550 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000552 return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int64_t Value = CE->getValue();
556 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
557 }
558 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000559 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000560 return false;
561 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
562 if (!CE) return false;
563 int64_t Value = CE->getValue();
564 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
565 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000566 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000568 return false;
569 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
570 if (!CE) return false;
571 int64_t Value = CE->getValue();
572 return Value >= 0 && Value < 256;
573 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000574 bool isImm0_1() const {
575 if (Kind != k_Immediate)
576 return false;
577 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
578 if (!CE) return false;
579 int64_t Value = CE->getValue();
580 return Value >= 0 && Value < 2;
581 }
582 bool isImm0_3() const {
583 if (Kind != k_Immediate)
584 return false;
585 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
586 if (!CE) return false;
587 int64_t Value = CE->getValue();
588 return Value >= 0 && Value < 4;
589 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000590 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000591 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000592 return false;
593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594 if (!CE) return false;
595 int64_t Value = CE->getValue();
596 return Value >= 0 && Value < 8;
597 }
598 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000599 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000600 return false;
601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602 if (!CE) return false;
603 int64_t Value = CE->getValue();
604 return Value >= 0 && Value < 16;
605 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000606 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000608 return false;
609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
610 if (!CE) return false;
611 int64_t Value = CE->getValue();
612 return Value >= 0 && Value < 32;
613 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000614 bool isImm0_63() const {
615 if (Kind != k_Immediate)
616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 64;
621 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000622 bool isImm8() const {
623 if (Kind != k_Immediate)
624 return false;
625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
626 if (!CE) return false;
627 int64_t Value = CE->getValue();
628 return Value == 8;
629 }
630 bool isImm16() const {
631 if (Kind != k_Immediate)
632 return false;
633 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
634 if (!CE) return false;
635 int64_t Value = CE->getValue();
636 return Value == 16;
637 }
638 bool isImm32() const {
639 if (Kind != k_Immediate)
640 return false;
641 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
642 if (!CE) return false;
643 int64_t Value = CE->getValue();
644 return Value == 32;
645 }
646 bool isImm1_7() const {
647 if (Kind != k_Immediate)
648 return false;
649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
650 if (!CE) return false;
651 int64_t Value = CE->getValue();
652 return Value > 0 && Value < 8;
653 }
654 bool isImm1_15() const {
655 if (Kind != k_Immediate)
656 return false;
657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658 if (!CE) return false;
659 int64_t Value = CE->getValue();
660 return Value > 0 && Value < 16;
661 }
662 bool isImm1_31() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value < 32;
669 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000670 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000671 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000672 return false;
673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value > 0 && Value < 17;
677 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000678 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000679 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000680 return false;
681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
682 if (!CE) return false;
683 int64_t Value = CE->getValue();
684 return Value > 0 && Value < 33;
685 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000686 bool isImm0_32() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value >= 0 && Value < 33;
693 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000694 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000695 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value >= 0 && Value < 65536;
701 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000702 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000703 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 // If it's not a constant expression, it'll generate a fixup and be
707 // handled later.
708 if (!CE) return true;
709 int64_t Value = CE->getValue();
710 return Value >= 0 && Value < 65536;
711 }
Jim Grosbached838482011-07-26 16:24:27 +0000712 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000713 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000714 return false;
715 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
716 if (!CE) return false;
717 int64_t Value = CE->getValue();
718 return Value >= 0 && Value <= 0xffffff;
719 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000720 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000721 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000722 return false;
723 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
724 if (!CE) return false;
725 int64_t Value = CE->getValue();
726 return Value > 0 && Value < 33;
727 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000728 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000729 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000730 return false;
731 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
732 if (!CE) return false;
733 int64_t Value = CE->getValue();
734 return Value >= 0 && Value < 32;
735 }
736 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000737 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000738 return false;
739 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
740 if (!CE) return false;
741 int64_t Value = CE->getValue();
742 return Value > 0 && Value <= 32;
743 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000744 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000745 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000746 return false;
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 int64_t Value = CE->getValue();
750 return ARM_AM::getSOImmVal(Value) != -1;
751 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000752 bool isARMSOImmNot() const {
753 if (Kind != k_Immediate)
754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return ARM_AM::getSOImmVal(~Value) != -1;
759 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000760 bool isARMSOImmNeg() const {
761 if (Kind != k_Immediate)
762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return ARM_AM::getSOImmVal(-Value) != -1;
767 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000768 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return ARM_AM::getT2SOImmVal(Value) != -1;
775 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000776 bool isT2SOImmNot() const {
777 if (Kind != k_Immediate)
778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return ARM_AM::getT2SOImmVal(~Value) != -1;
783 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000784 bool isT2SOImmNeg() const {
785 if (Kind != k_Immediate)
786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getT2SOImmVal(-Value) != -1;
791 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000792 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000793 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return Value == 1 || Value == 0;
799 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000800 bool isReg() const { return Kind == k_Register; }
801 bool isRegList() const { return Kind == k_RegisterList; }
802 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
803 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
804 bool isToken() const { return Kind == k_Token; }
805 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
806 bool isMemory() const { return Kind == k_Memory; }
807 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
808 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
809 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
810 bool isRotImm() const { return Kind == k_RotateImmediate; }
811 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
812 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000813 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000814 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000815 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000816 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000817 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000818 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000819 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000820 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
821 (alignOK || Memory.Alignment == 0);
822 }
823 bool isAlignedMemory() const {
824 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000825 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000826 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000827 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000828 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000829 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000830 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000831 if (!Memory.OffsetImm) return true;
832 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000833 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000834 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000835 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000836 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000837 return false;
838 // Immediate offset in range [-4095, 4095].
839 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
840 if (!CE) return false;
841 int64_t Val = CE->getValue();
842 return Val > -4096 && Val < 4096;
843 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000844 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000845 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000846 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000847 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000848 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000849 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000850 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000851 if (!Memory.OffsetImm) return true;
852 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000853 return Val > -256 && Val < 256;
854 }
855 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000856 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000857 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000858 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000859 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
860 // Immediate offset in range [-255, 255].
861 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
862 if (!CE) return false;
863 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000864 // Special case, #-0 is INT32_MIN.
865 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000866 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000867 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000868 // If we have an immediate that's not a constant, treat it as a label
869 // reference needing a fixup. If it is a constant, it's something else
870 // and we reject it.
871 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
872 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000873 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000874 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000875 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000876 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000877 if (!Memory.OffsetImm) return true;
878 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000879 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000880 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000881 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000882 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000883 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000884 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000885 return false;
886 return true;
887 }
888 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000889 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
891 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000892 return false;
893 return true;
894 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000895 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000896 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000897 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000898 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000899 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000900 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000901 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
902 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000903 return false;
904 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000905 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000906 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000907 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000908 return false;
909 return true;
910 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000911 bool isMemThumbRR() const {
912 // Thumb reg+reg addressing is simple. Just two registers, a base and
913 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000914 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000915 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000916 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000917 return isARMLowRegister(Memory.BaseRegNum) &&
918 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000919 }
920 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000921 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000922 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000923 return false;
924 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000925 if (!Memory.OffsetImm) return true;
926 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000927 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
928 }
Jim Grosbach38466302011-08-19 18:55:51 +0000929 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000930 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000931 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000932 return false;
933 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000934 if (!Memory.OffsetImm) return true;
935 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000936 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
937 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000938 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000939 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000940 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000941 return false;
942 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000943 if (!Memory.OffsetImm) return true;
944 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000945 return Val >= 0 && Val <= 31;
946 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000947 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000948 if (!isMemory() || Memory.OffsetRegNum != 0 ||
949 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000950 return false;
951 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (!Memory.OffsetImm) return true;
953 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000954 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000955 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000956 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000958 return false;
959 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000962 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
963 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000964 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000966 return false;
967 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000968 if (!Memory.OffsetImm) return true;
969 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000970 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
971 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000972 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000973 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000974 return false;
975 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (!Memory.OffsetImm) return true;
977 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000978 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000979 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000980 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000981 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000982 return false;
983 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!Memory.OffsetImm) return true;
985 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000986 return Val >= 0 && Val < 256;
987 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000988 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000989 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000990 return false;
991 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000992 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000993 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000994 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000995 }
996 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000997 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000998 return false;
999 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001000 if (!Memory.OffsetImm) return true;
1001 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001002 return (Val >= 0 && Val < 4096);
1003 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001004 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001005 // If we have an immediate that's not a constant, treat it as a label
1006 // reference needing a fixup. If it is a constant, it's something else
1007 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001008 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001009 return true;
1010
Jim Grosbach57dcb852011-10-11 17:29:55 +00001011 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 return false;
1013 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001014 if (!Memory.OffsetImm) return true;
1015 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001016 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001017 }
1018 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001019 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001020 return false;
1021 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1022 if (!CE) return false;
1023 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001024 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001025 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001026 bool isPostIdxImm8s4() const {
1027 if (Kind != k_Immediate)
1028 return false;
1029 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1030 if (!CE) return false;
1031 int64_t Val = CE->getValue();
1032 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1033 (Val == INT32_MIN);
1034 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001035
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001036 bool isMSRMask() const { return Kind == k_MSRMask; }
1037 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001038
Jim Grosbach0e387b22011-10-17 22:26:03 +00001039 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +00001040 bool isVecListOneD() const {
1041 if (Kind != k_VectorList) return false;
1042 return VectorList.Count == 1;
1043 }
1044
Jim Grosbach280dfad2011-10-21 18:54:25 +00001045 bool isVecListTwoD() const {
1046 if (Kind != k_VectorList) return false;
1047 return VectorList.Count == 2;
1048 }
1049
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001050 bool isVecListThreeD() const {
1051 if (Kind != k_VectorList) return false;
1052 return VectorList.Count == 3;
1053 }
1054
Jim Grosbachb6310312011-10-21 20:35:01 +00001055 bool isVecListFourD() const {
1056 if (Kind != k_VectorList) return false;
1057 return VectorList.Count == 4;
1058 }
1059
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001060 bool isVecListTwoQ() const {
1061 if (Kind != k_VectorList) return false;
1062 //FIXME: We haven't taught the parser to handle by-two register lists
1063 // yet, so don't pretend to know one.
1064 return VectorList.Count == 2 && false;
1065 }
1066
Jim Grosbach98b05a52011-11-30 01:09:44 +00001067 bool isVecListOneDAllLanes() const {
1068 if (Kind != k_VectorListAllLanes) return false;
1069 return VectorList.Count == 1;
1070 }
1071
Jim Grosbach13af2222011-11-30 18:21:25 +00001072 bool isVecListTwoDAllLanes() const {
1073 if (Kind != k_VectorListAllLanes) return false;
1074 return VectorList.Count == 2;
1075 }
1076
Jim Grosbach7636bf62011-12-02 00:35:16 +00001077 bool isVecListOneDByteIndexed() const {
1078 if (Kind != k_VectorListIndexed) return false;
1079 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1080 }
1081
Jim Grosbach460a9052011-10-07 23:56:00 +00001082 bool isVectorIndex8() const {
1083 if (Kind != k_VectorIndex) return false;
1084 return VectorIndex.Val < 8;
1085 }
1086 bool isVectorIndex16() const {
1087 if (Kind != k_VectorIndex) return false;
1088 return VectorIndex.Val < 4;
1089 }
1090 bool isVectorIndex32() const {
1091 if (Kind != k_VectorIndex) return false;
1092 return VectorIndex.Val < 2;
1093 }
1094
Jim Grosbach0e387b22011-10-17 22:26:03 +00001095 bool isNEONi8splat() const {
1096 if (Kind != k_Immediate)
1097 return false;
1098 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1099 // Must be a constant.
1100 if (!CE) return false;
1101 int64_t Value = CE->getValue();
1102 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1103 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001104 return Value >= 0 && Value < 256;
1105 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001106
Jim Grosbachea461102011-10-17 23:09:09 +00001107 bool isNEONi16splat() const {
1108 if (Kind != k_Immediate)
1109 return false;
1110 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1111 // Must be a constant.
1112 if (!CE) return false;
1113 int64_t Value = CE->getValue();
1114 // i16 value in the range [0,255] or [0x0100, 0xff00]
1115 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1116 }
1117
Jim Grosbach6248a542011-10-18 00:22:00 +00001118 bool isNEONi32splat() const {
1119 if (Kind != k_Immediate)
1120 return false;
1121 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1122 // Must be a constant.
1123 if (!CE) return false;
1124 int64_t Value = CE->getValue();
1125 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1126 return (Value >= 0 && Value < 256) ||
1127 (Value >= 0x0100 && Value <= 0xff00) ||
1128 (Value >= 0x010000 && Value <= 0xff0000) ||
1129 (Value >= 0x01000000 && Value <= 0xff000000);
1130 }
1131
1132 bool isNEONi32vmov() const {
1133 if (Kind != k_Immediate)
1134 return false;
1135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1136 // Must be a constant.
1137 if (!CE) return false;
1138 int64_t Value = CE->getValue();
1139 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1140 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1141 return (Value >= 0 && Value < 256) ||
1142 (Value >= 0x0100 && Value <= 0xff00) ||
1143 (Value >= 0x010000 && Value <= 0xff0000) ||
1144 (Value >= 0x01000000 && Value <= 0xff000000) ||
1145 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1146 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1147 }
1148
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001149 bool isNEONi64splat() const {
1150 if (Kind != k_Immediate)
1151 return false;
1152 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1153 // Must be a constant.
1154 if (!CE) return false;
1155 uint64_t Value = CE->getValue();
1156 // i64 value with each byte being either 0 or 0xff.
1157 for (unsigned i = 0; i < 8; ++i)
1158 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1159 return true;
1160 }
1161
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001162 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001163 // Add as immediates when possible. Null MCExpr = 0.
1164 if (Expr == 0)
1165 Inst.addOperand(MCOperand::CreateImm(0));
1166 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001167 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1168 else
1169 Inst.addOperand(MCOperand::CreateExpr(Expr));
1170 }
1171
Daniel Dunbar8462b302010-08-11 06:36:53 +00001172 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001173 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001174 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001175 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1176 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001177 }
1178
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001179 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
1181 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1182 }
1183
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001184 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
1186 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1187 }
1188
1189 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
1191 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1192 }
1193
Jim Grosbach89df9962011-08-26 21:43:41 +00001194 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1197 }
1198
1199 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1200 assert(N == 1 && "Invalid number of operands!");
1201 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1202 }
1203
Jim Grosbachd67641b2010-12-06 18:21:12 +00001204 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1205 assert(N == 1 && "Invalid number of operands!");
1206 Inst.addOperand(MCOperand::CreateReg(getReg()));
1207 }
1208
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001209 void addRegOperands(MCInst &Inst, unsigned N) const {
1210 assert(N == 1 && "Invalid number of operands!");
1211 Inst.addOperand(MCOperand::CreateReg(getReg()));
1212 }
1213
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001214 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001215 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001216 assert(isRegShiftedReg() &&
1217 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001218 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1219 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001220 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001221 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001222 }
1223
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001224 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001225 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001226 assert(isRegShiftedImm() &&
1227 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001228 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001229 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001230 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001231 }
1232
Jim Grosbach580f4a92011-07-25 22:20:28 +00001233 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001234 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001235 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1236 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001237 }
1238
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001239 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001240 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001241 const SmallVectorImpl<unsigned> &RegList = getRegList();
1242 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001243 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1244 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001245 }
1246
Bill Wendling0f630752010-11-17 04:32:08 +00001247 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1248 addRegListOperands(Inst, N);
1249 }
1250
1251 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1252 addRegListOperands(Inst, N);
1253 }
1254
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001255 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
1257 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1258 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1259 }
1260
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001261 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 // Munge the lsb/width into a bitfield mask.
1264 unsigned lsb = Bitfield.LSB;
1265 unsigned width = Bitfield.Width;
1266 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1267 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1268 (32 - (lsb + width)));
1269 Inst.addOperand(MCOperand::CreateImm(Mask));
1270 }
1271
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001272 void addImmOperands(MCInst &Inst, unsigned N) const {
1273 assert(N == 1 && "Invalid number of operands!");
1274 addExpr(Inst, getImm());
1275 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001276
Jim Grosbach9d390362011-10-03 23:38:36 +00001277 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1278 assert(N == 1 && "Invalid number of operands!");
1279 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1280 }
1281
Jim Grosbacha77295d2011-09-08 22:07:06 +00001282 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1283 assert(N == 1 && "Invalid number of operands!");
1284 // FIXME: We really want to scale the value here, but the LDRD/STRD
1285 // instruction don't encode operands that way yet.
1286 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1287 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1288 }
1289
Jim Grosbach72f39f82011-08-24 21:22:15 +00001290 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 // The immediate is scaled by four in the encoding and is stored
1293 // in the MCInst as such. Lop off the low two bits here.
1294 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1295 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1296 }
1297
1298 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
1300 // The immediate is scaled by four in the encoding and is stored
1301 // in the MCInst as such. Lop off the low two bits here.
1302 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1303 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1304 }
1305
Jim Grosbachf4943352011-07-25 23:09:14 +00001306 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1307 assert(N == 1 && "Invalid number of operands!");
1308 // The constant encodes as the immediate-1, and we store in the instruction
1309 // the bits as encoded, so subtract off one here.
1310 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1311 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1312 }
1313
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001314 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
1316 // The constant encodes as the immediate-1, and we store in the instruction
1317 // the bits as encoded, so subtract off one here.
1318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1320 }
1321
Jim Grosbach70939ee2011-08-17 21:51:27 +00001322 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
1324 // The constant encodes as the immediate, except for 32, which encodes as
1325 // zero.
1326 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1327 unsigned Imm = CE->getValue();
1328 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1329 }
1330
Jim Grosbachf6c05252011-07-21 17:23:04 +00001331 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1332 assert(N == 1 && "Invalid number of operands!");
1333 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1334 // the instruction as well.
1335 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1336 int Val = CE->getValue();
1337 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1338 }
1339
Jim Grosbach89a63372011-10-28 22:36:30 +00001340 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
1342 // The operand is actually a t2_so_imm, but we have its bitwise
1343 // negation in the assembly source, so twiddle it here.
1344 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1345 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1346 }
1347
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001348 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 // The operand is actually a t2_so_imm, but we have its
1351 // negation in the assembly source, so twiddle it here.
1352 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1353 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1354 }
1355
Jim Grosbache70ec842011-10-28 22:50:54 +00001356 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1357 assert(N == 1 && "Invalid number of operands!");
1358 // The operand is actually a so_imm, but we have its bitwise
1359 // negation in the assembly source, so twiddle it here.
1360 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1361 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1362 }
1363
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001364 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
1366 // The operand is actually a so_imm, but we have its
1367 // negation in the assembly source, so twiddle it here.
1368 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1369 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1370 }
1371
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001372 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1375 }
1376
Jim Grosbach7ce05792011-08-03 23:50:40 +00001377 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001379 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001380 }
1381
Jim Grosbach57dcb852011-10-11 17:29:55 +00001382 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1383 assert(N == 2 && "Invalid number of operands!");
1384 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1385 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1386 }
1387
Jim Grosbach7ce05792011-08-03 23:50:40 +00001388 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1389 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001390 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1391 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001392 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1393 // Special case for #-0
1394 if (Val == INT32_MIN) Val = 0;
1395 if (Val < 0) Val = -Val;
1396 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1397 } else {
1398 // For register offset, we encode the shift type and negation flag
1399 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001400 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1401 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001402 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001403 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1404 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001405 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001406 }
1407
Jim Grosbach039c2e12011-08-04 23:01:30 +00001408 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1409 assert(N == 2 && "Invalid number of operands!");
1410 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1411 assert(CE && "non-constant AM2OffsetImm operand!");
1412 int32_t Val = CE->getValue();
1413 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1414 // Special case for #-0
1415 if (Val == INT32_MIN) Val = 0;
1416 if (Val < 0) Val = -Val;
1417 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1418 Inst.addOperand(MCOperand::CreateReg(0));
1419 Inst.addOperand(MCOperand::CreateImm(Val));
1420 }
1421
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001422 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1423 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001424 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1425 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001426 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1427 // Special case for #-0
1428 if (Val == INT32_MIN) Val = 0;
1429 if (Val < 0) Val = -Val;
1430 Val = ARM_AM::getAM3Opc(AddSub, Val);
1431 } else {
1432 // For register offset, we encode the shift type and negation flag
1433 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001434 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001435 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001436 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1437 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001438 Inst.addOperand(MCOperand::CreateImm(Val));
1439 }
1440
1441 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1442 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001443 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001444 int32_t Val =
1445 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1446 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1447 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001448 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001449 }
1450
1451 // Constant offset.
1452 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1453 int32_t Val = CE->getValue();
1454 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1455 // Special case for #-0
1456 if (Val == INT32_MIN) Val = 0;
1457 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001458 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001459 Inst.addOperand(MCOperand::CreateReg(0));
1460 Inst.addOperand(MCOperand::CreateImm(Val));
1461 }
1462
Jim Grosbach7ce05792011-08-03 23:50:40 +00001463 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1464 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001465 // If we have an immediate that's not a constant, treat it as a label
1466 // reference needing a fixup. If it is a constant, it's something else
1467 // and we reject it.
1468 if (isImm()) {
1469 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1470 Inst.addOperand(MCOperand::CreateImm(0));
1471 return;
1472 }
1473
Jim Grosbach7ce05792011-08-03 23:50:40 +00001474 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001475 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001476 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1477 // Special case for #-0
1478 if (Val == INT32_MIN) Val = 0;
1479 if (Val < 0) Val = -Val;
1480 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001481 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001482 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001483 }
1484
Jim Grosbacha77295d2011-09-08 22:07:06 +00001485 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1486 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001487 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1488 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001489 Inst.addOperand(MCOperand::CreateImm(Val));
1490 }
1491
Jim Grosbachb6aed502011-09-09 18:37:27 +00001492 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 2 && "Invalid number of operands!");
1494 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001495 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1496 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001497 Inst.addOperand(MCOperand::CreateImm(Val));
1498 }
1499
Jim Grosbach7ce05792011-08-03 23:50:40 +00001500 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1501 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001502 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1503 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001504 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001505 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001506
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001507 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1508 addMemImm8OffsetOperands(Inst, N);
1509 }
1510
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001511 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001512 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001513 }
1514
1515 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1516 assert(N == 2 && "Invalid number of operands!");
1517 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001518 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001519 addExpr(Inst, getImm());
1520 Inst.addOperand(MCOperand::CreateImm(0));
1521 return;
1522 }
1523
1524 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001525 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1526 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001527 Inst.addOperand(MCOperand::CreateImm(Val));
1528 }
1529
Jim Grosbach7ce05792011-08-03 23:50:40 +00001530 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1531 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001532 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001533 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001534 addExpr(Inst, getImm());
1535 Inst.addOperand(MCOperand::CreateImm(0));
1536 return;
1537 }
1538
1539 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001540 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1541 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001542 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001543 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001544
Jim Grosbach7f739be2011-09-19 22:21:13 +00001545 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001547 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1548 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001549 }
1550
1551 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001553 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1554 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001555 }
1556
Jim Grosbach7ce05792011-08-03 23:50:40 +00001557 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1558 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001559 unsigned Val =
1560 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1561 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001562 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1563 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001564 Inst.addOperand(MCOperand::CreateImm(Val));
1565 }
1566
Jim Grosbachab899c12011-09-07 23:10:15 +00001567 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1568 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001569 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1570 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1571 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001572 }
1573
Jim Grosbach7ce05792011-08-03 23:50:40 +00001574 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1575 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001576 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1577 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001578 }
1579
Jim Grosbach60f91a32011-08-19 17:55:24 +00001580 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1581 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001582 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1583 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001584 Inst.addOperand(MCOperand::CreateImm(Val));
1585 }
1586
Jim Grosbach38466302011-08-19 18:55:51 +00001587 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1588 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001589 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1590 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001591 Inst.addOperand(MCOperand::CreateImm(Val));
1592 }
1593
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001594 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1595 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001596 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1597 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001598 Inst.addOperand(MCOperand::CreateImm(Val));
1599 }
1600
Jim Grosbachecd85892011-08-19 18:13:48 +00001601 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1602 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001603 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1604 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001605 Inst.addOperand(MCOperand::CreateImm(Val));
1606 }
1607
Jim Grosbach7ce05792011-08-03 23:50:40 +00001608 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1609 assert(N == 1 && "Invalid number of operands!");
1610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1611 assert(CE && "non-constant post-idx-imm8 operand!");
1612 int Imm = CE->getValue();
1613 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001614 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001615 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1616 Inst.addOperand(MCOperand::CreateImm(Imm));
1617 }
1618
Jim Grosbach2bd01182011-10-11 21:55:36 +00001619 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1620 assert(N == 1 && "Invalid number of operands!");
1621 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1622 assert(CE && "non-constant post-idx-imm8s4 operand!");
1623 int Imm = CE->getValue();
1624 bool isAdd = Imm >= 0;
1625 if (Imm == INT32_MIN) Imm = 0;
1626 // Immediate is scaled by 4.
1627 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1628 Inst.addOperand(MCOperand::CreateImm(Imm));
1629 }
1630
Jim Grosbach7ce05792011-08-03 23:50:40 +00001631 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1632 assert(N == 2 && "Invalid number of operands!");
1633 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001634 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1635 }
1636
1637 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1638 assert(N == 2 && "Invalid number of operands!");
1639 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1640 // The sign, shift type, and shift amount are encoded in a single operand
1641 // using the AM2 encoding helpers.
1642 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1643 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1644 PostIdxReg.ShiftTy);
1645 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001646 }
1647
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001648 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1649 assert(N == 1 && "Invalid number of operands!");
1650 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1651 }
1652
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001653 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1654 assert(N == 1 && "Invalid number of operands!");
1655 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1656 }
1657
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001658 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001659 assert(N == 1 && "Invalid number of operands!");
1660 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1661 }
1662
Jim Grosbach7636bf62011-12-02 00:35:16 +00001663 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1664 assert(N == 2 && "Invalid number of operands!");
1665 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1666 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1667 }
1668
Jim Grosbach460a9052011-10-07 23:56:00 +00001669 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1670 assert(N == 1 && "Invalid number of operands!");
1671 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1672 }
1673
1674 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1675 assert(N == 1 && "Invalid number of operands!");
1676 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1677 }
1678
1679 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1680 assert(N == 1 && "Invalid number of operands!");
1681 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1682 }
1683
Jim Grosbach0e387b22011-10-17 22:26:03 +00001684 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1685 assert(N == 1 && "Invalid number of operands!");
1686 // The immediate encodes the type of constant as well as the value.
1687 // Mask in that this is an i8 splat.
1688 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1689 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1690 }
1691
Jim Grosbachea461102011-10-17 23:09:09 +00001692 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1693 assert(N == 1 && "Invalid number of operands!");
1694 // The immediate encodes the type of constant as well as the value.
1695 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1696 unsigned Value = CE->getValue();
1697 if (Value >= 256)
1698 Value = (Value >> 8) | 0xa00;
1699 else
1700 Value |= 0x800;
1701 Inst.addOperand(MCOperand::CreateImm(Value));
1702 }
1703
Jim Grosbach6248a542011-10-18 00:22:00 +00001704 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1705 assert(N == 1 && "Invalid number of operands!");
1706 // The immediate encodes the type of constant as well as the value.
1707 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1708 unsigned Value = CE->getValue();
1709 if (Value >= 256 && Value <= 0xff00)
1710 Value = (Value >> 8) | 0x200;
1711 else if (Value > 0xffff && Value <= 0xff0000)
1712 Value = (Value >> 16) | 0x400;
1713 else if (Value > 0xffffff)
1714 Value = (Value >> 24) | 0x600;
1715 Inst.addOperand(MCOperand::CreateImm(Value));
1716 }
1717
1718 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1719 assert(N == 1 && "Invalid number of operands!");
1720 // The immediate encodes the type of constant as well as the value.
1721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1722 unsigned Value = CE->getValue();
1723 if (Value >= 256 && Value <= 0xffff)
1724 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1725 else if (Value > 0xffff && Value <= 0xffffff)
1726 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1727 else if (Value > 0xffffff)
1728 Value = (Value >> 24) | 0x600;
1729 Inst.addOperand(MCOperand::CreateImm(Value));
1730 }
1731
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001732 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1733 assert(N == 1 && "Invalid number of operands!");
1734 // The immediate encodes the type of constant as well as the value.
1735 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1736 uint64_t Value = CE->getValue();
1737 unsigned Imm = 0;
1738 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1739 Imm |= (Value & 1) << i;
1740 }
1741 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1742 }
1743
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001744 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001745
Jim Grosbach89df9962011-08-26 21:43:41 +00001746 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001747 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001748 Op->ITMask.Mask = Mask;
1749 Op->StartLoc = S;
1750 Op->EndLoc = S;
1751 return Op;
1752 }
1753
Chris Lattner3a697562010-10-28 17:20:03 +00001754 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001756 Op->CC.Val = CC;
1757 Op->StartLoc = S;
1758 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001759 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001760 }
1761
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001762 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001763 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001764 Op->Cop.Val = CopVal;
1765 Op->StartLoc = S;
1766 Op->EndLoc = S;
1767 return Op;
1768 }
1769
1770 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001771 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001772 Op->Cop.Val = CopVal;
1773 Op->StartLoc = S;
1774 Op->EndLoc = S;
1775 return Op;
1776 }
1777
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001778 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1779 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1780 Op->Cop.Val = Val;
1781 Op->StartLoc = S;
1782 Op->EndLoc = E;
1783 return Op;
1784 }
1785
Jim Grosbachd67641b2010-12-06 18:21:12 +00001786 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001787 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001788 Op->Reg.RegNum = RegNum;
1789 Op->StartLoc = S;
1790 Op->EndLoc = S;
1791 return Op;
1792 }
1793
Chris Lattner3a697562010-10-28 17:20:03 +00001794 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001795 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001796 Op->Tok.Data = Str.data();
1797 Op->Tok.Length = Str.size();
1798 Op->StartLoc = S;
1799 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001800 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001801 }
1802
Bill Wendling50d0f582010-11-18 23:43:05 +00001803 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001804 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001805 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001806 Op->StartLoc = S;
1807 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001808 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001809 }
1810
Jim Grosbache8606dc2011-07-13 17:50:29 +00001811 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1812 unsigned SrcReg,
1813 unsigned ShiftReg,
1814 unsigned ShiftImm,
1815 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001816 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001817 Op->RegShiftedReg.ShiftTy = ShTy;
1818 Op->RegShiftedReg.SrcReg = SrcReg;
1819 Op->RegShiftedReg.ShiftReg = ShiftReg;
1820 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001821 Op->StartLoc = S;
1822 Op->EndLoc = E;
1823 return Op;
1824 }
1825
Owen Anderson92a20222011-07-21 18:54:16 +00001826 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1827 unsigned SrcReg,
1828 unsigned ShiftImm,
1829 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001830 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001831 Op->RegShiftedImm.ShiftTy = ShTy;
1832 Op->RegShiftedImm.SrcReg = SrcReg;
1833 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001834 Op->StartLoc = S;
1835 Op->EndLoc = E;
1836 return Op;
1837 }
1838
Jim Grosbach580f4a92011-07-25 22:20:28 +00001839 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001840 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001841 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001842 Op->ShifterImm.isASR = isASR;
1843 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001844 Op->StartLoc = S;
1845 Op->EndLoc = E;
1846 return Op;
1847 }
1848
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001849 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001850 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001851 Op->RotImm.Imm = Imm;
1852 Op->StartLoc = S;
1853 Op->EndLoc = E;
1854 return Op;
1855 }
1856
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001857 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1858 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001859 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001860 Op->Bitfield.LSB = LSB;
1861 Op->Bitfield.Width = Width;
1862 Op->StartLoc = S;
1863 Op->EndLoc = E;
1864 return Op;
1865 }
1866
Bill Wendling7729e062010-11-09 22:44:22 +00001867 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001868 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001869 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001870 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001871
Jim Grosbachd300b942011-09-13 22:56:44 +00001872 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001873 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001874 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001875 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001876 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001877
1878 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001879 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001880 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001881 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001882 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001883 Op->StartLoc = StartLoc;
1884 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001885 return Op;
1886 }
1887
Jim Grosbach862019c2011-10-18 23:02:30 +00001888 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1889 SMLoc S, SMLoc E) {
1890 ARMOperand *Op = new ARMOperand(k_VectorList);
1891 Op->VectorList.RegNum = RegNum;
1892 Op->VectorList.Count = Count;
1893 Op->StartLoc = S;
1894 Op->EndLoc = E;
1895 return Op;
1896 }
1897
Jim Grosbach98b05a52011-11-30 01:09:44 +00001898 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1899 SMLoc S, SMLoc E) {
1900 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1901 Op->VectorList.RegNum = RegNum;
1902 Op->VectorList.Count = Count;
1903 Op->StartLoc = S;
1904 Op->EndLoc = E;
1905 return Op;
1906 }
1907
Jim Grosbach7636bf62011-12-02 00:35:16 +00001908 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1909 unsigned Index, SMLoc S, SMLoc E) {
1910 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1911 Op->VectorList.RegNum = RegNum;
1912 Op->VectorList.Count = Count;
1913 Op->VectorList.LaneIndex = Index;
1914 Op->StartLoc = S;
1915 Op->EndLoc = E;
1916 return Op;
1917 }
1918
Jim Grosbach460a9052011-10-07 23:56:00 +00001919 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1920 MCContext &Ctx) {
1921 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1922 Op->VectorIndex.Val = Idx;
1923 Op->StartLoc = S;
1924 Op->EndLoc = E;
1925 return Op;
1926 }
1927
Chris Lattner3a697562010-10-28 17:20:03 +00001928 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001929 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001930 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001931 Op->StartLoc = S;
1932 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001933 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001934 }
1935
Jim Grosbach9d390362011-10-03 23:38:36 +00001936 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001937 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001938 Op->FPImm.Val = Val;
1939 Op->StartLoc = S;
1940 Op->EndLoc = S;
1941 return Op;
1942 }
1943
Jim Grosbach7ce05792011-08-03 23:50:40 +00001944 static ARMOperand *CreateMem(unsigned BaseRegNum,
1945 const MCConstantExpr *OffsetImm,
1946 unsigned OffsetRegNum,
1947 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001948 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001949 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001950 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001951 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001952 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001953 Op->Memory.BaseRegNum = BaseRegNum;
1954 Op->Memory.OffsetImm = OffsetImm;
1955 Op->Memory.OffsetRegNum = OffsetRegNum;
1956 Op->Memory.ShiftType = ShiftType;
1957 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001958 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001959 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001960 Op->StartLoc = S;
1961 Op->EndLoc = E;
1962 return Op;
1963 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001964
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001965 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1966 ARM_AM::ShiftOpc ShiftTy,
1967 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001968 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001969 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001970 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001971 Op->PostIdxReg.isAdd = isAdd;
1972 Op->PostIdxReg.ShiftTy = ShiftTy;
1973 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001974 Op->StartLoc = S;
1975 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001976 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001977 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001978
1979 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001980 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001981 Op->MBOpt.Val = Opt;
1982 Op->StartLoc = S;
1983 Op->EndLoc = S;
1984 return Op;
1985 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001986
1987 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001989 Op->IFlags.Val = IFlags;
1990 Op->StartLoc = S;
1991 Op->EndLoc = S;
1992 return Op;
1993 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001994
1995 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001996 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001997 Op->MMask.Val = MMask;
1998 Op->StartLoc = S;
1999 Op->EndLoc = S;
2000 return Op;
2001 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002002};
2003
2004} // end anonymous namespace.
2005
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002006void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002007 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002008 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002009 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2010 << ") >";
2011 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002012 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002013 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002014 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002015 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002016 OS << "<ccout " << getReg() << ">";
2017 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002018 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002019 static const char *MaskStr[] = {
2020 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2021 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2022 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002023 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2024 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2025 break;
2026 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002027 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002028 OS << "<coprocessor number: " << getCoproc() << ">";
2029 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002030 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002031 OS << "<coprocessor register: " << getCoproc() << ">";
2032 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002033 case k_CoprocOption:
2034 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2035 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002036 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002037 OS << "<mask: " << getMSRMask() << ">";
2038 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002039 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002040 getImm()->print(OS);
2041 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002042 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002043 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2044 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002046 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002047 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002048 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002049 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002050 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002051 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2052 << PostIdxReg.RegNum;
2053 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2054 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2055 << PostIdxReg.ShiftImm;
2056 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002057 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002058 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002059 OS << "<ARM_PROC::";
2060 unsigned IFlags = getProcIFlags();
2061 for (int i=2; i >= 0; --i)
2062 if (IFlags & (1 << i))
2063 OS << ARM_PROC::IFlagsToString(1 << i);
2064 OS << ">";
2065 break;
2066 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002067 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002068 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002069 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002070 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002071 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2072 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002073 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002074 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002075 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002076 << RegShiftedReg.SrcReg << " "
2077 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2078 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002079 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002080 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002081 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002082 << RegShiftedImm.SrcReg << " "
2083 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2084 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002085 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002086 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002087 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2088 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002089 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002090 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2091 << ", width: " << Bitfield.Width << ">";
2092 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002093 case k_RegisterList:
2094 case k_DPRRegisterList:
2095 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002096 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002097
Bill Wendling5fa22a12010-11-09 23:28:44 +00002098 const SmallVectorImpl<unsigned> &RegList = getRegList();
2099 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002100 I = RegList.begin(), E = RegList.end(); I != E; ) {
2101 OS << *I;
2102 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002103 }
2104
2105 OS << ">";
2106 break;
2107 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002108 case k_VectorList:
2109 OS << "<vector_list " << VectorList.Count << " * "
2110 << VectorList.RegNum << ">";
2111 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002112 case k_VectorListAllLanes:
2113 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2114 << VectorList.RegNum << ">";
2115 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002116 case k_VectorListIndexed:
2117 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2118 << VectorList.Count << " * " << VectorList.RegNum << ">";
2119 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002120 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002121 OS << "'" << getToken() << "'";
2122 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002123 case k_VectorIndex:
2124 OS << "<vectorindex " << getVectorIndex() << ">";
2125 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002126 }
2127}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002128
2129/// @name Auto-generated Match Functions
2130/// {
2131
2132static unsigned MatchRegisterName(StringRef Name);
2133
2134/// }
2135
Bob Wilson69df7232011-02-03 21:46:10 +00002136bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2137 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002138 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002139
2140 return (RegNo == (unsigned)-1);
2141}
2142
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002143/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002144/// and if it is a register name the token is eaten and the register number is
2145/// returned. Otherwise return -1.
2146///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002147int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002148 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002149 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002150
Benjamin Kramer59085362011-11-06 20:37:06 +00002151 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002152 unsigned RegNum = MatchRegisterName(lowerCase);
2153 if (!RegNum) {
2154 RegNum = StringSwitch<unsigned>(lowerCase)
2155 .Case("r13", ARM::SP)
2156 .Case("r14", ARM::LR)
2157 .Case("r15", ARM::PC)
2158 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002159 // Additional register name aliases for 'gas' compatibility.
2160 .Case("a1", ARM::R0)
2161 .Case("a2", ARM::R1)
2162 .Case("a3", ARM::R2)
2163 .Case("a4", ARM::R3)
2164 .Case("v1", ARM::R4)
2165 .Case("v2", ARM::R5)
2166 .Case("v3", ARM::R6)
2167 .Case("v4", ARM::R7)
2168 .Case("v5", ARM::R8)
2169 .Case("v6", ARM::R9)
2170 .Case("v7", ARM::R10)
2171 .Case("v8", ARM::R11)
2172 .Case("sb", ARM::R9)
2173 .Case("sl", ARM::R10)
2174 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002175 .Default(0);
2176 }
2177 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002178
Chris Lattnere5658fa2010-10-30 04:09:10 +00002179 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002180
Chris Lattnere5658fa2010-10-30 04:09:10 +00002181 return RegNum;
2182}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002183
Jim Grosbach19906722011-07-13 18:49:30 +00002184// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2185// If a recoverable error occurs, return 1. If an irrecoverable error
2186// occurs, return -1. An irrecoverable error is one where tokens have been
2187// consumed in the process of trying to parse the shifter (i.e., when it is
2188// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002189int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002190 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2191 SMLoc S = Parser.getTok().getLoc();
2192 const AsmToken &Tok = Parser.getTok();
2193 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2194
Benjamin Kramer59085362011-11-06 20:37:06 +00002195 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002196 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002197 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002198 .Case("lsl", ARM_AM::lsl)
2199 .Case("lsr", ARM_AM::lsr)
2200 .Case("asr", ARM_AM::asr)
2201 .Case("ror", ARM_AM::ror)
2202 .Case("rrx", ARM_AM::rrx)
2203 .Default(ARM_AM::no_shift);
2204
2205 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002206 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002207
Jim Grosbache8606dc2011-07-13 17:50:29 +00002208 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002209
Jim Grosbache8606dc2011-07-13 17:50:29 +00002210 // The source register for the shift has already been added to the
2211 // operand list, so we need to pop it off and combine it into the shifted
2212 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002213 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002214 if (!PrevOp->isReg())
2215 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2216 int SrcReg = PrevOp->getReg();
2217 int64_t Imm = 0;
2218 int ShiftReg = 0;
2219 if (ShiftTy == ARM_AM::rrx) {
2220 // RRX Doesn't have an explicit shift amount. The encoder expects
2221 // the shift register to be the same as the source register. Seems odd,
2222 // but OK.
2223 ShiftReg = SrcReg;
2224 } else {
2225 // Figure out if this is shifted by a constant or a register (for non-RRX).
2226 if (Parser.getTok().is(AsmToken::Hash)) {
2227 Parser.Lex(); // Eat hash.
2228 SMLoc ImmLoc = Parser.getTok().getLoc();
2229 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002230 if (getParser().ParseExpression(ShiftExpr)) {
2231 Error(ImmLoc, "invalid immediate shift value");
2232 return -1;
2233 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002234 // The expression must be evaluatable as an immediate.
2235 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002236 if (!CE) {
2237 Error(ImmLoc, "invalid immediate shift value");
2238 return -1;
2239 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002240 // Range check the immediate.
2241 // lsl, ror: 0 <= imm <= 31
2242 // lsr, asr: 0 <= imm <= 32
2243 Imm = CE->getValue();
2244 if (Imm < 0 ||
2245 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2246 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002247 Error(ImmLoc, "immediate shift value out of range");
2248 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002249 }
2250 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002251 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002252 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002253 if (ShiftReg == -1) {
2254 Error (L, "expected immediate or register in shift operand");
2255 return -1;
2256 }
2257 } else {
2258 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002259 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002260 return -1;
2261 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002262 }
2263
Owen Anderson92a20222011-07-21 18:54:16 +00002264 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2265 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002266 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002267 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002268 else
2269 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2270 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002271
Jim Grosbach19906722011-07-13 18:49:30 +00002272 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002273}
2274
2275
Bill Wendling50d0f582010-11-18 23:43:05 +00002276/// Try to parse a register name. The token must be an Identifier when called.
2277/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2278/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002279///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002280/// TODO this is likely to change to allow different register types and or to
2281/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002282bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002283tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002284 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002285 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002286 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002287 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002288
Bill Wendling50d0f582010-11-18 23:43:05 +00002289 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002290
Chris Lattnere5658fa2010-10-30 04:09:10 +00002291 const AsmToken &ExclaimTok = Parser.getTok();
2292 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002293 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2294 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002295 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002296 return false;
2297 }
2298
2299 // Also check for an index operand. This is only legal for vector registers,
2300 // but that'll get caught OK in operand matching, so we don't need to
2301 // explicitly filter everything else out here.
2302 if (Parser.getTok().is(AsmToken::LBrac)) {
2303 SMLoc SIdx = Parser.getTok().getLoc();
2304 Parser.Lex(); // Eat left bracket token.
2305
2306 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002307 if (getParser().ParseExpression(ImmVal))
2308 return MatchOperand_ParseFail;
2309 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2310 if (!MCE) {
2311 TokError("immediate value expected for vector index");
2312 return MatchOperand_ParseFail;
2313 }
2314
2315 SMLoc E = Parser.getTok().getLoc();
2316 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2317 Error(E, "']' expected");
2318 return MatchOperand_ParseFail;
2319 }
2320
2321 Parser.Lex(); // Eat right bracket token.
2322
2323 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2324 SIdx, E,
2325 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002326 }
2327
Bill Wendling50d0f582010-11-18 23:43:05 +00002328 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002329}
2330
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002331/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2332/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2333/// "c5", ...
2334static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002335 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2336 // but efficient.
2337 switch (Name.size()) {
2338 default: break;
2339 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002340 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002341 return -1;
2342 switch (Name[1]) {
2343 default: return -1;
2344 case '0': return 0;
2345 case '1': return 1;
2346 case '2': return 2;
2347 case '3': return 3;
2348 case '4': return 4;
2349 case '5': return 5;
2350 case '6': return 6;
2351 case '7': return 7;
2352 case '8': return 8;
2353 case '9': return 9;
2354 }
2355 break;
2356 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002357 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002358 return -1;
2359 switch (Name[2]) {
2360 default: return -1;
2361 case '0': return 10;
2362 case '1': return 11;
2363 case '2': return 12;
2364 case '3': return 13;
2365 case '4': return 14;
2366 case '5': return 15;
2367 }
2368 break;
2369 }
2370
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002371 return -1;
2372}
2373
Jim Grosbach89df9962011-08-26 21:43:41 +00002374/// parseITCondCode - Try to parse a condition code for an IT instruction.
2375ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2376parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2377 SMLoc S = Parser.getTok().getLoc();
2378 const AsmToken &Tok = Parser.getTok();
2379 if (!Tok.is(AsmToken::Identifier))
2380 return MatchOperand_NoMatch;
2381 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2382 .Case("eq", ARMCC::EQ)
2383 .Case("ne", ARMCC::NE)
2384 .Case("hs", ARMCC::HS)
2385 .Case("cs", ARMCC::HS)
2386 .Case("lo", ARMCC::LO)
2387 .Case("cc", ARMCC::LO)
2388 .Case("mi", ARMCC::MI)
2389 .Case("pl", ARMCC::PL)
2390 .Case("vs", ARMCC::VS)
2391 .Case("vc", ARMCC::VC)
2392 .Case("hi", ARMCC::HI)
2393 .Case("ls", ARMCC::LS)
2394 .Case("ge", ARMCC::GE)
2395 .Case("lt", ARMCC::LT)
2396 .Case("gt", ARMCC::GT)
2397 .Case("le", ARMCC::LE)
2398 .Case("al", ARMCC::AL)
2399 .Default(~0U);
2400 if (CC == ~0U)
2401 return MatchOperand_NoMatch;
2402 Parser.Lex(); // Eat the token.
2403
2404 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2405
2406 return MatchOperand_Success;
2407}
2408
Jim Grosbach43904292011-07-25 20:14:50 +00002409/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002410/// token must be an Identifier when called, and if it is a coprocessor
2411/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002412ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002413parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002414 SMLoc S = Parser.getTok().getLoc();
2415 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002416 if (Tok.isNot(AsmToken::Identifier))
2417 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002418
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002419 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002420 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002421 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002422
2423 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002424 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002425 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002426}
2427
Jim Grosbach43904292011-07-25 20:14:50 +00002428/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002429/// token must be an Identifier when called, and if it is a coprocessor
2430/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002431ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002432parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002433 SMLoc S = Parser.getTok().getLoc();
2434 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002435 if (Tok.isNot(AsmToken::Identifier))
2436 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002437
2438 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2439 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002440 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002441
2442 Parser.Lex(); // Eat identifier token.
2443 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002444 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002445}
2446
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002447/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2448/// coproc_option : '{' imm0_255 '}'
2449ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2450parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2451 SMLoc S = Parser.getTok().getLoc();
2452
2453 // If this isn't a '{', this isn't a coprocessor immediate operand.
2454 if (Parser.getTok().isNot(AsmToken::LCurly))
2455 return MatchOperand_NoMatch;
2456 Parser.Lex(); // Eat the '{'
2457
2458 const MCExpr *Expr;
2459 SMLoc Loc = Parser.getTok().getLoc();
2460 if (getParser().ParseExpression(Expr)) {
2461 Error(Loc, "illegal expression");
2462 return MatchOperand_ParseFail;
2463 }
2464 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2465 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2466 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2467 return MatchOperand_ParseFail;
2468 }
2469 int Val = CE->getValue();
2470
2471 // Check for and consume the closing '}'
2472 if (Parser.getTok().isNot(AsmToken::RCurly))
2473 return MatchOperand_ParseFail;
2474 SMLoc E = Parser.getTok().getLoc();
2475 Parser.Lex(); // Eat the '}'
2476
2477 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2478 return MatchOperand_Success;
2479}
2480
Jim Grosbachd0588e22011-09-14 18:08:35 +00002481// For register list parsing, we need to map from raw GPR register numbering
2482// to the enumeration values. The enumeration values aren't sorted by
2483// register number due to our using "sp", "lr" and "pc" as canonical names.
2484static unsigned getNextRegister(unsigned Reg) {
2485 // If this is a GPR, we need to do it manually, otherwise we can rely
2486 // on the sort ordering of the enumeration since the other reg-classes
2487 // are sane.
2488 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2489 return Reg + 1;
2490 switch(Reg) {
2491 default: assert(0 && "Invalid GPR number!");
2492 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2493 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2494 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2495 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2496 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2497 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2498 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2499 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2500 }
2501}
2502
Jim Grosbachce485e72011-11-11 21:27:40 +00002503// Return the low-subreg of a given Q register.
2504static unsigned getDRegFromQReg(unsigned QReg) {
2505 switch (QReg) {
2506 default: llvm_unreachable("expected a Q register!");
2507 case ARM::Q0: return ARM::D0;
2508 case ARM::Q1: return ARM::D2;
2509 case ARM::Q2: return ARM::D4;
2510 case ARM::Q3: return ARM::D6;
2511 case ARM::Q4: return ARM::D8;
2512 case ARM::Q5: return ARM::D10;
2513 case ARM::Q6: return ARM::D12;
2514 case ARM::Q7: return ARM::D14;
2515 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002516 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002517 case ARM::Q10: return ARM::D20;
2518 case ARM::Q11: return ARM::D22;
2519 case ARM::Q12: return ARM::D24;
2520 case ARM::Q13: return ARM::D26;
2521 case ARM::Q14: return ARM::D28;
2522 case ARM::Q15: return ARM::D30;
2523 }
2524}
2525
Jim Grosbachd0588e22011-09-14 18:08:35 +00002526/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002527bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002528parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002529 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002530 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002531 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002532 Parser.Lex(); // Eat '{' token.
2533 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002534
Jim Grosbachd0588e22011-09-14 18:08:35 +00002535 // Check the first register in the list to see what register class
2536 // this is a list of.
2537 int Reg = tryParseRegister();
2538 if (Reg == -1)
2539 return Error(RegLoc, "register expected");
2540
Jim Grosbachce485e72011-11-11 21:27:40 +00002541 // The reglist instructions have at most 16 registers, so reserve
2542 // space for that many.
2543 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2544
2545 // Allow Q regs and just interpret them as the two D sub-registers.
2546 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2547 Reg = getDRegFromQReg(Reg);
2548 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2549 ++Reg;
2550 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002551 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002552 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2553 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2554 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2555 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2556 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2557 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2558 else
2559 return Error(RegLoc, "invalid register in register list");
2560
Jim Grosbachce485e72011-11-11 21:27:40 +00002561 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002562 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002563
Jim Grosbachd0588e22011-09-14 18:08:35 +00002564 // This starts immediately after the first register token in the list,
2565 // so we can see either a comma or a minus (range separator) as a legal
2566 // next token.
2567 while (Parser.getTok().is(AsmToken::Comma) ||
2568 Parser.getTok().is(AsmToken::Minus)) {
2569 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002570 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002571 SMLoc EndLoc = Parser.getTok().getLoc();
2572 int EndReg = tryParseRegister();
2573 if (EndReg == -1)
2574 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002575 // Allow Q regs and just interpret them as the two D sub-registers.
2576 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2577 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002578 // If the register is the same as the start reg, there's nothing
2579 // more to do.
2580 if (Reg == EndReg)
2581 continue;
2582 // The register must be in the same register class as the first.
2583 if (!RC->contains(EndReg))
2584 return Error(EndLoc, "invalid register in register list");
2585 // Ranges must go from low to high.
2586 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2587 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002588
Jim Grosbachd0588e22011-09-14 18:08:35 +00002589 // Add all the registers in the range to the register list.
2590 while (Reg != EndReg) {
2591 Reg = getNextRegister(Reg);
2592 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2593 }
2594 continue;
2595 }
2596 Parser.Lex(); // Eat the comma.
2597 RegLoc = Parser.getTok().getLoc();
2598 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002599 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002600 Reg = tryParseRegister();
2601 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002602 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002603 // Allow Q regs and just interpret them as the two D sub-registers.
2604 bool isQReg = false;
2605 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2606 Reg = getDRegFromQReg(Reg);
2607 isQReg = true;
2608 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002609 // The register must be in the same register class as the first.
2610 if (!RC->contains(Reg))
2611 return Error(RegLoc, "invalid register in register list");
2612 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002613 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002614 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002615 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2616 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2617 ") in register list");
2618 continue;
2619 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002620 // VFP register lists must also be contiguous.
2621 // It's OK to use the enumeration values directly here rather, as the
2622 // VFP register classes have the enum sorted properly.
2623 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2624 Reg != OldReg + 1)
2625 return Error(RegLoc, "non-contiguous register range");
2626 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002627 if (isQReg)
2628 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002629 }
2630
Jim Grosbachd0588e22011-09-14 18:08:35 +00002631 SMLoc E = Parser.getTok().getLoc();
2632 if (Parser.getTok().isNot(AsmToken::RCurly))
2633 return Error(E, "'}' expected");
2634 Parser.Lex(); // Eat '}' token.
2635
Bill Wendling50d0f582010-11-18 23:43:05 +00002636 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2637 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002638}
2639
Jim Grosbach98b05a52011-11-30 01:09:44 +00002640// Helper function to parse the lane index for vector lists.
2641ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002642parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2643 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002644 if (Parser.getTok().is(AsmToken::LBrac)) {
2645 Parser.Lex(); // Eat the '['.
2646 if (Parser.getTok().is(AsmToken::RBrac)) {
2647 // "Dn[]" is the 'all lanes' syntax.
2648 LaneKind = AllLanes;
2649 Parser.Lex(); // Eat the ']'.
2650 return MatchOperand_Success;
2651 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002652 if (Parser.getTok().is(AsmToken::Integer)) {
2653 int64_t Val = Parser.getTok().getIntVal();
2654 // Make this range check context sensitive for .8, .16, .32.
2655 if (Val < 0 && Val > 7)
2656 Error(Parser.getTok().getLoc(), "lane index out of range");
2657 Index = Val;
2658 LaneKind = IndexedLane;
2659 Parser.Lex(); // Eat the token;
2660 if (Parser.getTok().isNot(AsmToken::RBrac))
2661 Error(Parser.getTok().getLoc(), "']' expected");
2662 Parser.Lex(); // Eat the ']'.
2663 return MatchOperand_Success;
2664 }
2665 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002666 return MatchOperand_ParseFail;
2667 }
2668 LaneKind = NoLanes;
2669 return MatchOperand_Success;
2670}
2671
Jim Grosbach862019c2011-10-18 23:02:30 +00002672// parse a vector register list
2673ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2674parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002675 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002676 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002677 SMLoc S = Parser.getTok().getLoc();
2678 // As an extension (to match gas), support a plain D register or Q register
2679 // (without encosing curly braces) as a single or double entry list,
2680 // respectively.
2681 if (Parser.getTok().is(AsmToken::Identifier)) {
2682 int Reg = tryParseRegister();
2683 if (Reg == -1)
2684 return MatchOperand_NoMatch;
2685 SMLoc E = Parser.getTok().getLoc();
2686 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002687 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002688 if (Res != MatchOperand_Success)
2689 return Res;
2690 switch (LaneKind) {
2691 default:
2692 assert(0 && "unexpected lane kind!");
2693 case NoLanes:
2694 E = Parser.getTok().getLoc();
2695 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2696 break;
2697 case AllLanes:
2698 E = Parser.getTok().getLoc();
2699 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2700 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002701 case IndexedLane:
2702 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2703 LaneIndex, S,E));
2704 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002705 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002706 return MatchOperand_Success;
2707 }
2708 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2709 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002710 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002711 if (Res != MatchOperand_Success)
2712 return Res;
2713 switch (LaneKind) {
2714 default:
2715 assert(0 && "unexpected lane kind!");
2716 case NoLanes:
2717 E = Parser.getTok().getLoc();
2718 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2719 break;
2720 case AllLanes:
2721 E = Parser.getTok().getLoc();
2722 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2723 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002724 case IndexedLane:
2725 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2726 LaneIndex, S,E));
2727 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002728 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002729 return MatchOperand_Success;
2730 }
2731 Error(S, "vector register expected");
2732 return MatchOperand_ParseFail;
2733 }
2734
2735 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002736 return MatchOperand_NoMatch;
2737
Jim Grosbach862019c2011-10-18 23:02:30 +00002738 Parser.Lex(); // Eat '{' token.
2739 SMLoc RegLoc = Parser.getTok().getLoc();
2740
2741 int Reg = tryParseRegister();
2742 if (Reg == -1) {
2743 Error(RegLoc, "register expected");
2744 return MatchOperand_ParseFail;
2745 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002746 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002747 unsigned FirstReg = Reg;
2748 // The list is of D registers, but we also allow Q regs and just interpret
2749 // them as the two D sub-registers.
2750 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2751 FirstReg = Reg = getDRegFromQReg(Reg);
2752 ++Reg;
2753 ++Count;
2754 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002755 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002756 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002757
Jim Grosbache43862b2011-11-15 23:19:15 +00002758 while (Parser.getTok().is(AsmToken::Comma) ||
2759 Parser.getTok().is(AsmToken::Minus)) {
2760 if (Parser.getTok().is(AsmToken::Minus)) {
2761 Parser.Lex(); // Eat the minus.
2762 SMLoc EndLoc = Parser.getTok().getLoc();
2763 int EndReg = tryParseRegister();
2764 if (EndReg == -1) {
2765 Error(EndLoc, "register expected");
2766 return MatchOperand_ParseFail;
2767 }
2768 // Allow Q regs and just interpret them as the two D sub-registers.
2769 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2770 EndReg = getDRegFromQReg(EndReg) + 1;
2771 // If the register is the same as the start reg, there's nothing
2772 // more to do.
2773 if (Reg == EndReg)
2774 continue;
2775 // The register must be in the same register class as the first.
2776 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2777 Error(EndLoc, "invalid register in register list");
2778 return MatchOperand_ParseFail;
2779 }
2780 // Ranges must go from low to high.
2781 if (Reg > EndReg) {
2782 Error(EndLoc, "bad range in register list");
2783 return MatchOperand_ParseFail;
2784 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002785 // Parse the lane specifier if present.
2786 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002787 unsigned NextLaneIndex;
2788 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002789 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002790 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002791 Error(EndLoc, "mismatched lane index in register list");
2792 return MatchOperand_ParseFail;
2793 }
2794 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002795
2796 // Add all the registers in the range to the register list.
2797 Count += EndReg - Reg;
2798 Reg = EndReg;
2799 continue;
2800 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002801 Parser.Lex(); // Eat the comma.
2802 RegLoc = Parser.getTok().getLoc();
2803 int OldReg = Reg;
2804 Reg = tryParseRegister();
2805 if (Reg == -1) {
2806 Error(RegLoc, "register expected");
2807 return MatchOperand_ParseFail;
2808 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002809 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002810 // It's OK to use the enumeration values directly here rather, as the
2811 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002812 //
2813 // The list is of D registers, but we also allow Q regs and just interpret
2814 // them as the two D sub-registers.
2815 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2816 Reg = getDRegFromQReg(Reg);
2817 if (Reg != OldReg + 1) {
2818 Error(RegLoc, "non-contiguous register range");
2819 return MatchOperand_ParseFail;
2820 }
2821 ++Reg;
2822 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002823 // Parse the lane specifier if present.
2824 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002825 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002826 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002827 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002828 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002829 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002830 Error(EndLoc, "mismatched lane index in register list");
2831 return MatchOperand_ParseFail;
2832 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002833 continue;
2834 }
2835 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002836 if (Reg != OldReg + 1) {
2837 Error(RegLoc, "non-contiguous register range");
2838 return MatchOperand_ParseFail;
2839 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002840 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002841 // Parse the lane specifier if present.
2842 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002843 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002844 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002845 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002846 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002847 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002848 Error(EndLoc, "mismatched lane index in register list");
2849 return MatchOperand_ParseFail;
2850 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002851 }
2852
2853 SMLoc E = Parser.getTok().getLoc();
2854 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2855 Error(E, "'}' expected");
2856 return MatchOperand_ParseFail;
2857 }
2858 Parser.Lex(); // Eat '}' token.
2859
Jim Grosbach98b05a52011-11-30 01:09:44 +00002860 switch (LaneKind) {
2861 default:
2862 assert(0 && "unexpected lane kind in register list.");
2863 case NoLanes:
2864 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2865 break;
2866 case AllLanes:
2867 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2868 S, E));
2869 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002870 case IndexedLane:
2871 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2872 LaneIndex, S, E));
2873 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002874 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002875 return MatchOperand_Success;
2876}
2877
Jim Grosbach43904292011-07-25 20:14:50 +00002878/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002879ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002880parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002881 SMLoc S = Parser.getTok().getLoc();
2882 const AsmToken &Tok = Parser.getTok();
2883 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2884 StringRef OptStr = Tok.getString();
2885
2886 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2887 .Case("sy", ARM_MB::SY)
2888 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002889 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002890 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002891 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002892 .Case("ishst", ARM_MB::ISHST)
2893 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002894 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002895 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002896 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002897 .Case("osh", ARM_MB::OSH)
2898 .Case("oshst", ARM_MB::OSHST)
2899 .Default(~0U);
2900
2901 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002902 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002903
2904 Parser.Lex(); // Eat identifier token.
2905 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002906 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002907}
2908
Jim Grosbach43904292011-07-25 20:14:50 +00002909/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002910ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002911parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002912 SMLoc S = Parser.getTok().getLoc();
2913 const AsmToken &Tok = Parser.getTok();
2914 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2915 StringRef IFlagsStr = Tok.getString();
2916
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002917 // An iflags string of "none" is interpreted to mean that none of the AIF
2918 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002919 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002920 if (IFlagsStr != "none") {
2921 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2922 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2923 .Case("a", ARM_PROC::A)
2924 .Case("i", ARM_PROC::I)
2925 .Case("f", ARM_PROC::F)
2926 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002927
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002928 // If some specific iflag is already set, it means that some letter is
2929 // present more than once, this is not acceptable.
2930 if (Flag == ~0U || (IFlags & Flag))
2931 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002932
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002933 IFlags |= Flag;
2934 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002935 }
2936
2937 Parser.Lex(); // Eat identifier token.
2938 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2939 return MatchOperand_Success;
2940}
2941
Jim Grosbach43904292011-07-25 20:14:50 +00002942/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002943ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002944parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002945 SMLoc S = Parser.getTok().getLoc();
2946 const AsmToken &Tok = Parser.getTok();
2947 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2948 StringRef Mask = Tok.getString();
2949
James Molloyacad68d2011-09-28 14:21:38 +00002950 if (isMClass()) {
2951 // See ARMv6-M 10.1.1
2952 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2953 .Case("apsr", 0)
2954 .Case("iapsr", 1)
2955 .Case("eapsr", 2)
2956 .Case("xpsr", 3)
2957 .Case("ipsr", 5)
2958 .Case("epsr", 6)
2959 .Case("iepsr", 7)
2960 .Case("msp", 8)
2961 .Case("psp", 9)
2962 .Case("primask", 16)
2963 .Case("basepri", 17)
2964 .Case("basepri_max", 18)
2965 .Case("faultmask", 19)
2966 .Case("control", 20)
2967 .Default(~0U);
2968
2969 if (FlagsVal == ~0U)
2970 return MatchOperand_NoMatch;
2971
2972 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2973 // basepri, basepri_max and faultmask only valid for V7m.
2974 return MatchOperand_NoMatch;
2975
2976 Parser.Lex(); // Eat identifier token.
2977 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2978 return MatchOperand_Success;
2979 }
2980
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002981 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2982 size_t Start = 0, Next = Mask.find('_');
2983 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002984 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002985 if (Next != StringRef::npos)
2986 Flags = Mask.slice(Next+1, Mask.size());
2987
2988 // FlagsVal contains the complete mask:
2989 // 3-0: Mask
2990 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2991 unsigned FlagsVal = 0;
2992
2993 if (SpecReg == "apsr") {
2994 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002995 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002996 .Case("g", 0x4) // same as CPSR_s
2997 .Case("nzcvqg", 0xc) // same as CPSR_fs
2998 .Default(~0U);
2999
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003000 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003001 if (!Flags.empty())
3002 return MatchOperand_NoMatch;
3003 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003004 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003005 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003006 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003007 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3008 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003009 for (int i = 0, e = Flags.size(); i != e; ++i) {
3010 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3011 .Case("c", 1)
3012 .Case("x", 2)
3013 .Case("s", 4)
3014 .Case("f", 8)
3015 .Default(~0U);
3016
3017 // If some specific flag is already set, it means that some letter is
3018 // present more than once, this is not acceptable.
3019 if (FlagsVal == ~0U || (FlagsVal & Flag))
3020 return MatchOperand_NoMatch;
3021 FlagsVal |= Flag;
3022 }
3023 } else // No match for special register.
3024 return MatchOperand_NoMatch;
3025
Owen Anderson7784f1d2011-10-21 18:43:28 +00003026 // Special register without flags is NOT equivalent to "fc" flags.
3027 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3028 // two lines would enable gas compatibility at the expense of breaking
3029 // round-tripping.
3030 //
3031 // if (!FlagsVal)
3032 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003033
3034 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3035 if (SpecReg == "spsr")
3036 FlagsVal |= 16;
3037
3038 Parser.Lex(); // Eat identifier token.
3039 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3040 return MatchOperand_Success;
3041}
3042
Jim Grosbachf6c05252011-07-21 17:23:04 +00003043ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3044parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3045 int Low, int High) {
3046 const AsmToken &Tok = Parser.getTok();
3047 if (Tok.isNot(AsmToken::Identifier)) {
3048 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3049 return MatchOperand_ParseFail;
3050 }
3051 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003052 std::string LowerOp = Op.lower();
3053 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003054 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3055 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3056 return MatchOperand_ParseFail;
3057 }
3058 Parser.Lex(); // Eat shift type token.
3059
3060 // There must be a '#' and a shift amount.
3061 if (Parser.getTok().isNot(AsmToken::Hash)) {
3062 Error(Parser.getTok().getLoc(), "'#' expected");
3063 return MatchOperand_ParseFail;
3064 }
3065 Parser.Lex(); // Eat hash token.
3066
3067 const MCExpr *ShiftAmount;
3068 SMLoc Loc = Parser.getTok().getLoc();
3069 if (getParser().ParseExpression(ShiftAmount)) {
3070 Error(Loc, "illegal expression");
3071 return MatchOperand_ParseFail;
3072 }
3073 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3074 if (!CE) {
3075 Error(Loc, "constant expression expected");
3076 return MatchOperand_ParseFail;
3077 }
3078 int Val = CE->getValue();
3079 if (Val < Low || Val > High) {
3080 Error(Loc, "immediate value out of range");
3081 return MatchOperand_ParseFail;
3082 }
3083
3084 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3085
3086 return MatchOperand_Success;
3087}
3088
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003089ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3090parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3091 const AsmToken &Tok = Parser.getTok();
3092 SMLoc S = Tok.getLoc();
3093 if (Tok.isNot(AsmToken::Identifier)) {
3094 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3095 return MatchOperand_ParseFail;
3096 }
3097 int Val = StringSwitch<int>(Tok.getString())
3098 .Case("be", 1)
3099 .Case("le", 0)
3100 .Default(-1);
3101 Parser.Lex(); // Eat the token.
3102
3103 if (Val == -1) {
3104 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3105 return MatchOperand_ParseFail;
3106 }
3107 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3108 getContext()),
3109 S, Parser.getTok().getLoc()));
3110 return MatchOperand_Success;
3111}
3112
Jim Grosbach580f4a92011-07-25 22:20:28 +00003113/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3114/// instructions. Legal values are:
3115/// lsl #n 'n' in [0,31]
3116/// asr #n 'n' in [1,32]
3117/// n == 32 encoded as n == 0.
3118ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3119parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3120 const AsmToken &Tok = Parser.getTok();
3121 SMLoc S = Tok.getLoc();
3122 if (Tok.isNot(AsmToken::Identifier)) {
3123 Error(S, "shift operator 'asr' or 'lsl' expected");
3124 return MatchOperand_ParseFail;
3125 }
3126 StringRef ShiftName = Tok.getString();
3127 bool isASR;
3128 if (ShiftName == "lsl" || ShiftName == "LSL")
3129 isASR = false;
3130 else if (ShiftName == "asr" || ShiftName == "ASR")
3131 isASR = true;
3132 else {
3133 Error(S, "shift operator 'asr' or 'lsl' expected");
3134 return MatchOperand_ParseFail;
3135 }
3136 Parser.Lex(); // Eat the operator.
3137
3138 // A '#' and a shift amount.
3139 if (Parser.getTok().isNot(AsmToken::Hash)) {
3140 Error(Parser.getTok().getLoc(), "'#' expected");
3141 return MatchOperand_ParseFail;
3142 }
3143 Parser.Lex(); // Eat hash token.
3144
3145 const MCExpr *ShiftAmount;
3146 SMLoc E = Parser.getTok().getLoc();
3147 if (getParser().ParseExpression(ShiftAmount)) {
3148 Error(E, "malformed shift expression");
3149 return MatchOperand_ParseFail;
3150 }
3151 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3152 if (!CE) {
3153 Error(E, "shift amount must be an immediate");
3154 return MatchOperand_ParseFail;
3155 }
3156
3157 int64_t Val = CE->getValue();
3158 if (isASR) {
3159 // Shift amount must be in [1,32]
3160 if (Val < 1 || Val > 32) {
3161 Error(E, "'asr' shift amount must be in range [1,32]");
3162 return MatchOperand_ParseFail;
3163 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003164 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3165 if (isThumb() && Val == 32) {
3166 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3167 return MatchOperand_ParseFail;
3168 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003169 if (Val == 32) Val = 0;
3170 } else {
3171 // Shift amount must be in [1,32]
3172 if (Val < 0 || Val > 31) {
3173 Error(E, "'lsr' shift amount must be in range [0,31]");
3174 return MatchOperand_ParseFail;
3175 }
3176 }
3177
3178 E = Parser.getTok().getLoc();
3179 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3180
3181 return MatchOperand_Success;
3182}
3183
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003184/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3185/// of instructions. Legal values are:
3186/// ror #n 'n' in {0, 8, 16, 24}
3187ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3188parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3189 const AsmToken &Tok = Parser.getTok();
3190 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003191 if (Tok.isNot(AsmToken::Identifier))
3192 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003193 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003194 if (ShiftName != "ror" && ShiftName != "ROR")
3195 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003196 Parser.Lex(); // Eat the operator.
3197
3198 // A '#' and a rotate amount.
3199 if (Parser.getTok().isNot(AsmToken::Hash)) {
3200 Error(Parser.getTok().getLoc(), "'#' expected");
3201 return MatchOperand_ParseFail;
3202 }
3203 Parser.Lex(); // Eat hash token.
3204
3205 const MCExpr *ShiftAmount;
3206 SMLoc E = Parser.getTok().getLoc();
3207 if (getParser().ParseExpression(ShiftAmount)) {
3208 Error(E, "malformed rotate expression");
3209 return MatchOperand_ParseFail;
3210 }
3211 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3212 if (!CE) {
3213 Error(E, "rotate amount must be an immediate");
3214 return MatchOperand_ParseFail;
3215 }
3216
3217 int64_t Val = CE->getValue();
3218 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3219 // normally, zero is represented in asm by omitting the rotate operand
3220 // entirely.
3221 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3222 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3223 return MatchOperand_ParseFail;
3224 }
3225
3226 E = Parser.getTok().getLoc();
3227 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3228
3229 return MatchOperand_Success;
3230}
3231
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003232ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3233parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3234 SMLoc S = Parser.getTok().getLoc();
3235 // The bitfield descriptor is really two operands, the LSB and the width.
3236 if (Parser.getTok().isNot(AsmToken::Hash)) {
3237 Error(Parser.getTok().getLoc(), "'#' expected");
3238 return MatchOperand_ParseFail;
3239 }
3240 Parser.Lex(); // Eat hash token.
3241
3242 const MCExpr *LSBExpr;
3243 SMLoc E = Parser.getTok().getLoc();
3244 if (getParser().ParseExpression(LSBExpr)) {
3245 Error(E, "malformed immediate expression");
3246 return MatchOperand_ParseFail;
3247 }
3248 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3249 if (!CE) {
3250 Error(E, "'lsb' operand must be an immediate");
3251 return MatchOperand_ParseFail;
3252 }
3253
3254 int64_t LSB = CE->getValue();
3255 // The LSB must be in the range [0,31]
3256 if (LSB < 0 || LSB > 31) {
3257 Error(E, "'lsb' operand must be in the range [0,31]");
3258 return MatchOperand_ParseFail;
3259 }
3260 E = Parser.getTok().getLoc();
3261
3262 // Expect another immediate operand.
3263 if (Parser.getTok().isNot(AsmToken::Comma)) {
3264 Error(Parser.getTok().getLoc(), "too few operands");
3265 return MatchOperand_ParseFail;
3266 }
3267 Parser.Lex(); // Eat hash token.
3268 if (Parser.getTok().isNot(AsmToken::Hash)) {
3269 Error(Parser.getTok().getLoc(), "'#' expected");
3270 return MatchOperand_ParseFail;
3271 }
3272 Parser.Lex(); // Eat hash token.
3273
3274 const MCExpr *WidthExpr;
3275 if (getParser().ParseExpression(WidthExpr)) {
3276 Error(E, "malformed immediate expression");
3277 return MatchOperand_ParseFail;
3278 }
3279 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3280 if (!CE) {
3281 Error(E, "'width' operand must be an immediate");
3282 return MatchOperand_ParseFail;
3283 }
3284
3285 int64_t Width = CE->getValue();
3286 // The LSB must be in the range [1,32-lsb]
3287 if (Width < 1 || Width > 32 - LSB) {
3288 Error(E, "'width' operand must be in the range [1,32-lsb]");
3289 return MatchOperand_ParseFail;
3290 }
3291 E = Parser.getTok().getLoc();
3292
3293 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3294
3295 return MatchOperand_Success;
3296}
3297
Jim Grosbach7ce05792011-08-03 23:50:40 +00003298ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3299parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3300 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003301 // postidx_reg := '+' register {, shift}
3302 // | '-' register {, shift}
3303 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003304
3305 // This method must return MatchOperand_NoMatch without consuming any tokens
3306 // in the case where there is no match, as other alternatives take other
3307 // parse methods.
3308 AsmToken Tok = Parser.getTok();
3309 SMLoc S = Tok.getLoc();
3310 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003311 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003312 int Reg = -1;
3313 if (Tok.is(AsmToken::Plus)) {
3314 Parser.Lex(); // Eat the '+' token.
3315 haveEaten = true;
3316 } else if (Tok.is(AsmToken::Minus)) {
3317 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003318 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003319 haveEaten = true;
3320 }
3321 if (Parser.getTok().is(AsmToken::Identifier))
3322 Reg = tryParseRegister();
3323 if (Reg == -1) {
3324 if (!haveEaten)
3325 return MatchOperand_NoMatch;
3326 Error(Parser.getTok().getLoc(), "register expected");
3327 return MatchOperand_ParseFail;
3328 }
3329 SMLoc E = Parser.getTok().getLoc();
3330
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003331 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3332 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003333 if (Parser.getTok().is(AsmToken::Comma)) {
3334 Parser.Lex(); // Eat the ','.
3335 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3336 return MatchOperand_ParseFail;
3337 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003338
3339 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3340 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003341
3342 return MatchOperand_Success;
3343}
3344
Jim Grosbach251bf252011-08-10 21:56:18 +00003345ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3346parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3347 // Check for a post-index addressing register operand. Specifically:
3348 // am3offset := '+' register
3349 // | '-' register
3350 // | register
3351 // | # imm
3352 // | # + imm
3353 // | # - imm
3354
3355 // This method must return MatchOperand_NoMatch without consuming any tokens
3356 // in the case where there is no match, as other alternatives take other
3357 // parse methods.
3358 AsmToken Tok = Parser.getTok();
3359 SMLoc S = Tok.getLoc();
3360
3361 // Do immediates first, as we always parse those if we have a '#'.
3362 if (Parser.getTok().is(AsmToken::Hash)) {
3363 Parser.Lex(); // Eat the '#'.
3364 // Explicitly look for a '-', as we need to encode negative zero
3365 // differently.
3366 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3367 const MCExpr *Offset;
3368 if (getParser().ParseExpression(Offset))
3369 return MatchOperand_ParseFail;
3370 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3371 if (!CE) {
3372 Error(S, "constant expression expected");
3373 return MatchOperand_ParseFail;
3374 }
3375 SMLoc E = Tok.getLoc();
3376 // Negative zero is encoded as the flag value INT32_MIN.
3377 int32_t Val = CE->getValue();
3378 if (isNegative && Val == 0)
3379 Val = INT32_MIN;
3380
3381 Operands.push_back(
3382 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3383
3384 return MatchOperand_Success;
3385 }
3386
3387
3388 bool haveEaten = false;
3389 bool isAdd = true;
3390 int Reg = -1;
3391 if (Tok.is(AsmToken::Plus)) {
3392 Parser.Lex(); // Eat the '+' token.
3393 haveEaten = true;
3394 } else if (Tok.is(AsmToken::Minus)) {
3395 Parser.Lex(); // Eat the '-' token.
3396 isAdd = false;
3397 haveEaten = true;
3398 }
3399 if (Parser.getTok().is(AsmToken::Identifier))
3400 Reg = tryParseRegister();
3401 if (Reg == -1) {
3402 if (!haveEaten)
3403 return MatchOperand_NoMatch;
3404 Error(Parser.getTok().getLoc(), "register expected");
3405 return MatchOperand_ParseFail;
3406 }
3407 SMLoc E = Parser.getTok().getLoc();
3408
3409 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3410 0, S, E));
3411
3412 return MatchOperand_Success;
3413}
3414
Jim Grosbacha77295d2011-09-08 22:07:06 +00003415/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3416/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3417/// when they refer multiple MIOperands inside a single one.
3418bool ARMAsmParser::
3419cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3420 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3421 // Rt, Rt2
3422 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3423 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3424 // Create a writeback register dummy placeholder.
3425 Inst.addOperand(MCOperand::CreateReg(0));
3426 // addr
3427 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3428 // pred
3429 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3430 return true;
3431}
3432
3433/// cvtT2StrdPre - Convert parsed operands to MCInst.
3434/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3435/// when they refer multiple MIOperands inside a single one.
3436bool ARMAsmParser::
3437cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3438 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3439 // Create a writeback register dummy placeholder.
3440 Inst.addOperand(MCOperand::CreateReg(0));
3441 // Rt, Rt2
3442 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3443 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3444 // addr
3445 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3446 // pred
3447 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3448 return true;
3449}
3450
Jim Grosbacheeec0252011-09-08 00:39:19 +00003451/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3452/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3453/// when they refer multiple MIOperands inside a single one.
3454bool ARMAsmParser::
3455cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3456 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3457 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3458
3459 // Create a writeback register dummy placeholder.
3460 Inst.addOperand(MCOperand::CreateImm(0));
3461
3462 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3463 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3464 return true;
3465}
3466
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003467/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3468/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3469/// when they refer multiple MIOperands inside a single one.
3470bool ARMAsmParser::
3471cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3472 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3473 // Create a writeback register dummy placeholder.
3474 Inst.addOperand(MCOperand::CreateImm(0));
3475 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3476 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3477 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3478 return true;
3479}
3480
Jim Grosbach1355cf12011-07-26 17:10:22 +00003481/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003482/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3483/// when they refer multiple MIOperands inside a single one.
3484bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003485cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003486 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3487 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3488
3489 // Create a writeback register dummy placeholder.
3490 Inst.addOperand(MCOperand::CreateImm(0));
3491
Jim Grosbach7ce05792011-08-03 23:50:40 +00003492 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003493 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3494 return true;
3495}
3496
Owen Anderson9ab0f252011-08-26 20:43:14 +00003497/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3498/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3499/// when they refer multiple MIOperands inside a single one.
3500bool ARMAsmParser::
3501cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3502 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3503 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3504
3505 // Create a writeback register dummy placeholder.
3506 Inst.addOperand(MCOperand::CreateImm(0));
3507
3508 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3509 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3510 return true;
3511}
3512
3513
Jim Grosbach548340c2011-08-11 19:22:40 +00003514/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3515/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3516/// when they refer multiple MIOperands inside a single one.
3517bool ARMAsmParser::
3518cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3519 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3520 // Create a writeback register dummy placeholder.
3521 Inst.addOperand(MCOperand::CreateImm(0));
3522 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3523 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3524 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3525 return true;
3526}
3527
Jim Grosbach1355cf12011-07-26 17:10:22 +00003528/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003529/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3530/// when they refer multiple MIOperands inside a single one.
3531bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003532cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003533 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3534 // Create a writeback register dummy placeholder.
3535 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003536 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3537 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3538 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003539 return true;
3540}
3541
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003542/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3543/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3544/// when they refer multiple MIOperands inside a single one.
3545bool ARMAsmParser::
3546cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3547 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3548 // Create a writeback register dummy placeholder.
3549 Inst.addOperand(MCOperand::CreateImm(0));
3550 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3551 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3552 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3553 return true;
3554}
3555
Jim Grosbach7ce05792011-08-03 23:50:40 +00003556/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3557/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3558/// when they refer multiple MIOperands inside a single one.
3559bool ARMAsmParser::
3560cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3561 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3562 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003563 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003564 // Create a writeback register dummy placeholder.
3565 Inst.addOperand(MCOperand::CreateImm(0));
3566 // addr
3567 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3568 // offset
3569 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3570 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003571 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3572 return true;
3573}
3574
Jim Grosbach7ce05792011-08-03 23:50:40 +00003575/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003576/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3577/// when they refer multiple MIOperands inside a single one.
3578bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003579cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3580 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3581 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003582 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003583 // Create a writeback register dummy placeholder.
3584 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003585 // addr
3586 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3587 // offset
3588 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3589 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003590 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3591 return true;
3592}
3593
Jim Grosbach7ce05792011-08-03 23:50:40 +00003594/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003595/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3596/// when they refer multiple MIOperands inside a single one.
3597bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003598cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3599 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003600 // Create a writeback register dummy placeholder.
3601 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003602 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003603 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003604 // addr
3605 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3606 // offset
3607 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3608 // pred
3609 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3610 return true;
3611}
3612
3613/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3614/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3615/// when they refer multiple MIOperands inside a single one.
3616bool ARMAsmParser::
3617cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3618 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3619 // Create a writeback register dummy placeholder.
3620 Inst.addOperand(MCOperand::CreateImm(0));
3621 // Rt
3622 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3623 // addr
3624 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3625 // offset
3626 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3627 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003628 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3629 return true;
3630}
3631
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003632/// cvtLdrdPre - Convert parsed operands to MCInst.
3633/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3634/// when they refer multiple MIOperands inside a single one.
3635bool ARMAsmParser::
3636cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3637 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3638 // Rt, Rt2
3639 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3640 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3641 // Create a writeback register dummy placeholder.
3642 Inst.addOperand(MCOperand::CreateImm(0));
3643 // addr
3644 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3645 // pred
3646 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3647 return true;
3648}
3649
Jim Grosbach14605d12011-08-11 20:28:23 +00003650/// cvtStrdPre - Convert parsed operands to MCInst.
3651/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3652/// when they refer multiple MIOperands inside a single one.
3653bool ARMAsmParser::
3654cvtStrdPre(MCInst &Inst, unsigned Opcode,
3655 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3656 // Create a writeback register dummy placeholder.
3657 Inst.addOperand(MCOperand::CreateImm(0));
3658 // Rt, Rt2
3659 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3660 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3661 // addr
3662 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3663 // pred
3664 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3665 return true;
3666}
3667
Jim Grosbach623a4542011-08-10 22:42:16 +00003668/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3669/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3670/// when they refer multiple MIOperands inside a single one.
3671bool ARMAsmParser::
3672cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3673 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3674 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3675 // Create a writeback register dummy placeholder.
3676 Inst.addOperand(MCOperand::CreateImm(0));
3677 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3678 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3679 return true;
3680}
3681
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003682/// cvtThumbMultiple- Convert parsed operands to MCInst.
3683/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3684/// when they refer multiple MIOperands inside a single one.
3685bool ARMAsmParser::
3686cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3687 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3688 // The second source operand must be the same register as the destination
3689 // operand.
3690 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003691 (((ARMOperand*)Operands[3])->getReg() !=
3692 ((ARMOperand*)Operands[5])->getReg()) &&
3693 (((ARMOperand*)Operands[3])->getReg() !=
3694 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003695 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003696 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003697 return false;
3698 }
3699 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3700 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003701 // If we have a three-operand form, make sure to set Rn to be the operand
3702 // that isn't the same as Rd.
3703 unsigned RegOp = 4;
3704 if (Operands.size() == 6 &&
3705 ((ARMOperand*)Operands[4])->getReg() ==
3706 ((ARMOperand*)Operands[3])->getReg())
3707 RegOp = 5;
3708 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3709 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003710 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3711
3712 return true;
3713}
Jim Grosbach623a4542011-08-10 22:42:16 +00003714
Jim Grosbach12431322011-10-24 22:16:58 +00003715bool ARMAsmParser::
3716cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3717 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3718 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003719 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003720 // Create a writeback register dummy placeholder.
3721 Inst.addOperand(MCOperand::CreateImm(0));
3722 // Vn
3723 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3724 // pred
3725 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3726 return true;
3727}
3728
3729bool ARMAsmParser::
3730cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3731 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3732 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003733 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003734 // Create a writeback register dummy placeholder.
3735 Inst.addOperand(MCOperand::CreateImm(0));
3736 // Vn
3737 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3738 // Vm
3739 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3740 // pred
3741 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3742 return true;
3743}
3744
Jim Grosbach4334e032011-10-31 21:50:31 +00003745bool ARMAsmParser::
3746cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3747 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3748 // Create a writeback register dummy placeholder.
3749 Inst.addOperand(MCOperand::CreateImm(0));
3750 // Vn
3751 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3752 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003753 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003754 // pred
3755 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3756 return true;
3757}
3758
3759bool ARMAsmParser::
3760cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3761 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3762 // Create a writeback register dummy placeholder.
3763 Inst.addOperand(MCOperand::CreateImm(0));
3764 // Vn
3765 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3766 // Vm
3767 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3768 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003769 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003770 // pred
3771 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3772 return true;
3773}
3774
Bill Wendlinge7176102010-11-06 22:36:58 +00003775/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003776/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003777bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003778parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003779 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003780 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003781 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003782 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003783 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003784
Sean Callanan18b83232010-01-19 21:44:56 +00003785 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003786 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003787 if (BaseRegNum == -1)
3788 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003789
Daniel Dunbar05710932011-01-18 05:34:17 +00003790 // The next token must either be a comma or a closing bracket.
3791 const AsmToken &Tok = Parser.getTok();
3792 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003793 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003794
Jim Grosbach7ce05792011-08-03 23:50:40 +00003795 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003796 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003797 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003798
Jim Grosbach7ce05792011-08-03 23:50:40 +00003799 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003800 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003801
Jim Grosbachfb12f352011-09-19 18:42:21 +00003802 // If there's a pre-indexing writeback marker, '!', just add it as a token
3803 // operand. It's rather odd, but syntactically valid.
3804 if (Parser.getTok().is(AsmToken::Exclaim)) {
3805 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3806 Parser.Lex(); // Eat the '!'.
3807 }
3808
Jim Grosbach7ce05792011-08-03 23:50:40 +00003809 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003810 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003811
Jim Grosbach7ce05792011-08-03 23:50:40 +00003812 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3813 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003814
Jim Grosbach57dcb852011-10-11 17:29:55 +00003815 // If we have a ':', it's an alignment specifier.
3816 if (Parser.getTok().is(AsmToken::Colon)) {
3817 Parser.Lex(); // Eat the ':'.
3818 E = Parser.getTok().getLoc();
3819
3820 const MCExpr *Expr;
3821 if (getParser().ParseExpression(Expr))
3822 return true;
3823
3824 // The expression has to be a constant. Memory references with relocations
3825 // don't come through here, as they use the <label> forms of the relevant
3826 // instructions.
3827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3828 if (!CE)
3829 return Error (E, "constant expression expected");
3830
3831 unsigned Align = 0;
3832 switch (CE->getValue()) {
3833 default:
3834 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3835 case 64: Align = 8; break;
3836 case 128: Align = 16; break;
3837 case 256: Align = 32; break;
3838 }
3839
3840 // Now we should have the closing ']'
3841 E = Parser.getTok().getLoc();
3842 if (Parser.getTok().isNot(AsmToken::RBrac))
3843 return Error(E, "']' expected");
3844 Parser.Lex(); // Eat right bracket token.
3845
3846 // Don't worry about range checking the value here. That's handled by
3847 // the is*() predicates.
3848 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3849 ARM_AM::no_shift, 0, Align,
3850 false, S, E));
3851
3852 // If there's a pre-indexing writeback marker, '!', just add it as a token
3853 // operand.
3854 if (Parser.getTok().is(AsmToken::Exclaim)) {
3855 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3856 Parser.Lex(); // Eat the '!'.
3857 }
3858
3859 return false;
3860 }
3861
3862 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003863 // offset. Be friendly and also accept a plain integer (without a leading
3864 // hash) for gas compatibility.
3865 if (Parser.getTok().is(AsmToken::Hash) ||
3866 Parser.getTok().is(AsmToken::Integer)) {
3867 if (Parser.getTok().is(AsmToken::Hash))
3868 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003869 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003870
Owen Anderson0da10cf2011-08-29 19:36:44 +00003871 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003872 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003873 if (getParser().ParseExpression(Offset))
3874 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003875
3876 // The expression has to be a constant. Memory references with relocations
3877 // don't come through here, as they use the <label> forms of the relevant
3878 // instructions.
3879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3880 if (!CE)
3881 return Error (E, "constant expression expected");
3882
Owen Anderson0da10cf2011-08-29 19:36:44 +00003883 // If the constant was #-0, represent it as INT32_MIN.
3884 int32_t Val = CE->getValue();
3885 if (isNegative && Val == 0)
3886 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3887
Jim Grosbach7ce05792011-08-03 23:50:40 +00003888 // Now we should have the closing ']'
3889 E = Parser.getTok().getLoc();
3890 if (Parser.getTok().isNot(AsmToken::RBrac))
3891 return Error(E, "']' expected");
3892 Parser.Lex(); // Eat right bracket token.
3893
3894 // Don't worry about range checking the value here. That's handled by
3895 // the is*() predicates.
3896 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003897 ARM_AM::no_shift, 0, 0,
3898 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003899
3900 // If there's a pre-indexing writeback marker, '!', just add it as a token
3901 // operand.
3902 if (Parser.getTok().is(AsmToken::Exclaim)) {
3903 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3904 Parser.Lex(); // Eat the '!'.
3905 }
3906
3907 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003908 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003909
3910 // The register offset is optionally preceded by a '+' or '-'
3911 bool isNegative = false;
3912 if (Parser.getTok().is(AsmToken::Minus)) {
3913 isNegative = true;
3914 Parser.Lex(); // Eat the '-'.
3915 } else if (Parser.getTok().is(AsmToken::Plus)) {
3916 // Nothing to do.
3917 Parser.Lex(); // Eat the '+'.
3918 }
3919
3920 E = Parser.getTok().getLoc();
3921 int OffsetRegNum = tryParseRegister();
3922 if (OffsetRegNum == -1)
3923 return Error(E, "register expected");
3924
3925 // If there's a shift operator, handle it.
3926 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003927 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003928 if (Parser.getTok().is(AsmToken::Comma)) {
3929 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003930 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003931 return true;
3932 }
3933
3934 // Now we should have the closing ']'
3935 E = Parser.getTok().getLoc();
3936 if (Parser.getTok().isNot(AsmToken::RBrac))
3937 return Error(E, "']' expected");
3938 Parser.Lex(); // Eat right bracket token.
3939
3940 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003941 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003942 S, E));
3943
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003944 // If there's a pre-indexing writeback marker, '!', just add it as a token
3945 // operand.
3946 if (Parser.getTok().is(AsmToken::Exclaim)) {
3947 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3948 Parser.Lex(); // Eat the '!'.
3949 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003950
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003951 return false;
3952}
3953
Jim Grosbach7ce05792011-08-03 23:50:40 +00003954/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003955/// ( lsl | lsr | asr | ror ) , # shift_amount
3956/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003957/// return true if it parses a shift otherwise it returns false.
3958bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3959 unsigned &Amount) {
3960 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003961 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003962 if (Tok.isNot(AsmToken::Identifier))
3963 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003964 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00003965 if (ShiftName == "lsl" || ShiftName == "LSL" ||
3966 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00003967 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003968 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003969 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003970 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003971 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003972 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003973 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003974 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003975 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003976 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003977 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003978 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003979
Jim Grosbach7ce05792011-08-03 23:50:40 +00003980 // rrx stands alone.
3981 Amount = 0;
3982 if (St != ARM_AM::rrx) {
3983 Loc = Parser.getTok().getLoc();
3984 // A '#' and a shift amount.
3985 const AsmToken &HashTok = Parser.getTok();
3986 if (HashTok.isNot(AsmToken::Hash))
3987 return Error(HashTok.getLoc(), "'#' expected");
3988 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003989
Jim Grosbach7ce05792011-08-03 23:50:40 +00003990 const MCExpr *Expr;
3991 if (getParser().ParseExpression(Expr))
3992 return true;
3993 // Range check the immediate.
3994 // lsl, ror: 0 <= imm <= 31
3995 // lsr, asr: 0 <= imm <= 32
3996 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3997 if (!CE)
3998 return Error(Loc, "shift amount must be an immediate");
3999 int64_t Imm = CE->getValue();
4000 if (Imm < 0 ||
4001 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4002 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4003 return Error(Loc, "immediate shift value out of range");
4004 Amount = Imm;
4005 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004006
4007 return false;
4008}
4009
Jim Grosbach9d390362011-10-03 23:38:36 +00004010/// parseFPImm - A floating point immediate expression operand.
4011ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4012parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4013 SMLoc S = Parser.getTok().getLoc();
4014
4015 if (Parser.getTok().isNot(AsmToken::Hash))
4016 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004017
4018 // Disambiguate the VMOV forms that can accept an FP immediate.
4019 // vmov.f32 <sreg>, #imm
4020 // vmov.f64 <dreg>, #imm
4021 // vmov.f32 <dreg>, #imm @ vector f32x2
4022 // vmov.f32 <qreg>, #imm @ vector f32x4
4023 //
4024 // There are also the NEON VMOV instructions which expect an
4025 // integer constant. Make sure we don't try to parse an FPImm
4026 // for these:
4027 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4028 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4029 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4030 TyOp->getToken() != ".f64"))
4031 return MatchOperand_NoMatch;
4032
Jim Grosbach9d390362011-10-03 23:38:36 +00004033 Parser.Lex(); // Eat the '#'.
4034
4035 // Handle negation, as that still comes through as a separate token.
4036 bool isNegative = false;
4037 if (Parser.getTok().is(AsmToken::Minus)) {
4038 isNegative = true;
4039 Parser.Lex();
4040 }
4041 const AsmToken &Tok = Parser.getTok();
4042 if (Tok.is(AsmToken::Real)) {
4043 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4044 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4045 // If we had a '-' in front, toggle the sign bit.
4046 IntVal ^= (uint64_t)isNegative << 63;
4047 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4048 Parser.Lex(); // Eat the token.
4049 if (Val == -1) {
4050 TokError("floating point value out of range");
4051 return MatchOperand_ParseFail;
4052 }
4053 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4054 return MatchOperand_Success;
4055 }
4056 if (Tok.is(AsmToken::Integer)) {
4057 int64_t Val = Tok.getIntVal();
4058 Parser.Lex(); // Eat the token.
4059 if (Val > 255 || Val < 0) {
4060 TokError("encoded floating point value out of range");
4061 return MatchOperand_ParseFail;
4062 }
4063 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4064 return MatchOperand_Success;
4065 }
4066
4067 TokError("invalid floating point immediate");
4068 return MatchOperand_ParseFail;
4069}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004070/// Parse a arm instruction operand. For now this parses the operand regardless
4071/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004072bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004073 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004074 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004075
4076 // Check if the current operand has a custom associated parser, if so, try to
4077 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004078 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4079 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004080 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004081 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4082 // there was a match, but an error occurred, in which case, just return that
4083 // the operand parsing failed.
4084 if (ResTy == MatchOperand_ParseFail)
4085 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004086
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004087 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004088 default:
4089 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004090 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004091 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004092 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004093 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004094 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004095 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004096 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004097 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004098 else if (Res == -1) // irrecoverable error
4099 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004100 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4101 S = Parser.getTok().getLoc();
4102 Parser.Lex();
4103 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4104 return false;
4105 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004106
4107 // Fall though for the Identifier case that is not a register or a
4108 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004109 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004110 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004111 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004112 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004113 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004114 // This was not a register so parse other operands that start with an
4115 // identifier (like labels) as expressions and create them as immediates.
4116 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004117 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004118 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004119 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004120 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004121 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4122 return false;
4123 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004124 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004125 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004126 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004127 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00004128 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004129 // #42 -> immediate.
4130 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004131 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004132 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004133 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004134 const MCExpr *ImmVal;
4135 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004136 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004137 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004138 if (CE) {
4139 int32_t Val = CE->getValue();
4140 if (isNegative && Val == 0)
4141 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004142 }
Sean Callanan76264762010-04-02 22:27:05 +00004143 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004144 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4145 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004146 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004147 case AsmToken::Colon: {
4148 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004149 // FIXME: Check it's an expression prefix,
4150 // e.g. (FOO - :lower16:BAR) isn't legal.
4151 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004152 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004153 return true;
4154
Evan Cheng75972122011-01-13 07:58:56 +00004155 const MCExpr *SubExprVal;
4156 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004157 return true;
4158
Evan Cheng75972122011-01-13 07:58:56 +00004159 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4160 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004161 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004162 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004163 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004164 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004165 }
4166}
4167
Jim Grosbach1355cf12011-07-26 17:10:22 +00004168// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004169// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004170bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004171 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004172
4173 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004174 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004175 Parser.Lex(); // Eat ':'
4176
4177 if (getLexer().isNot(AsmToken::Identifier)) {
4178 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4179 return true;
4180 }
4181
4182 StringRef IDVal = Parser.getTok().getIdentifier();
4183 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004184 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004185 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004186 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004187 } else {
4188 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4189 return true;
4190 }
4191 Parser.Lex();
4192
4193 if (getLexer().isNot(AsmToken::Colon)) {
4194 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4195 return true;
4196 }
4197 Parser.Lex(); // Eat the last ':'
4198 return false;
4199}
4200
Daniel Dunbar352e1482011-01-11 15:59:50 +00004201/// \brief Given a mnemonic, split out possible predication code and carry
4202/// setting letters to form a canonical mnemonic and flags.
4203//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004204// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004205// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004206StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004207 unsigned &PredicationCode,
4208 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004209 unsigned &ProcessorIMod,
4210 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004211 PredicationCode = ARMCC::AL;
4212 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004213 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004214
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004215 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004216 //
4217 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004218 if ((Mnemonic == "movs" && isThumb()) ||
4219 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4220 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4221 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4222 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4223 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4224 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4225 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004226 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004227
Jim Grosbach3f00e312011-07-11 17:09:57 +00004228 // First, split out any predication code. Ignore mnemonics we know aren't
4229 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004230 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004231 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004232 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004233 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004234 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4235 .Case("eq", ARMCC::EQ)
4236 .Case("ne", ARMCC::NE)
4237 .Case("hs", ARMCC::HS)
4238 .Case("cs", ARMCC::HS)
4239 .Case("lo", ARMCC::LO)
4240 .Case("cc", ARMCC::LO)
4241 .Case("mi", ARMCC::MI)
4242 .Case("pl", ARMCC::PL)
4243 .Case("vs", ARMCC::VS)
4244 .Case("vc", ARMCC::VC)
4245 .Case("hi", ARMCC::HI)
4246 .Case("ls", ARMCC::LS)
4247 .Case("ge", ARMCC::GE)
4248 .Case("lt", ARMCC::LT)
4249 .Case("gt", ARMCC::GT)
4250 .Case("le", ARMCC::LE)
4251 .Case("al", ARMCC::AL)
4252 .Default(~0U);
4253 if (CC != ~0U) {
4254 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4255 PredicationCode = CC;
4256 }
Bill Wendling52925b62010-10-29 23:50:21 +00004257 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004258
Daniel Dunbar352e1482011-01-11 15:59:50 +00004259 // Next, determine if we have a carry setting bit. We explicitly ignore all
4260 // the instructions we know end in 's'.
4261 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004262 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004263 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4264 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4265 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004266 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach8254f022011-12-08 00:52:55 +00004267 Mnemonic == "fmrs" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004268 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004269 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4270 CarrySetting = true;
4271 }
4272
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004273 // The "cps" instruction can have a interrupt mode operand which is glued into
4274 // the mnemonic. Check if this is the case, split it and parse the imod op
4275 if (Mnemonic.startswith("cps")) {
4276 // Split out any imod code.
4277 unsigned IMod =
4278 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4279 .Case("ie", ARM_PROC::IE)
4280 .Case("id", ARM_PROC::ID)
4281 .Default(~0U);
4282 if (IMod != ~0U) {
4283 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4284 ProcessorIMod = IMod;
4285 }
4286 }
4287
Jim Grosbach89df9962011-08-26 21:43:41 +00004288 // The "it" instruction has the condition mask on the end of the mnemonic.
4289 if (Mnemonic.startswith("it")) {
4290 ITMask = Mnemonic.slice(2, Mnemonic.size());
4291 Mnemonic = Mnemonic.slice(0, 2);
4292 }
4293
Daniel Dunbar352e1482011-01-11 15:59:50 +00004294 return Mnemonic;
4295}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004296
4297/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4298/// inclusion of carry set or predication code operands.
4299//
4300// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004301void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004302getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004303 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004304 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4305 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004306 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004307 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004308 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004309 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004310 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004311 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004312 Mnemonic == "mla" || Mnemonic == "smlal" ||
4313 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004314 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004315 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004316 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004317
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004318 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4319 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4320 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4321 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004322 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4323 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004324 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004325 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4326 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4327 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004328 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4329 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004330 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004331 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004332 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004333 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004334
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004335 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004336 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004337 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004338 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004339 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004340}
4341
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004342bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4343 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004344 // FIXME: This is all horribly hacky. We really need a better way to deal
4345 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004346
4347 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4348 // another does not. Specifically, the MOVW instruction does not. So we
4349 // special case it here and remove the defaulted (non-setting) cc_out
4350 // operand if that's the instruction we're trying to match.
4351 //
4352 // We do this as post-processing of the explicit operands rather than just
4353 // conditionally adding the cc_out in the first place because we need
4354 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004355 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004356 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4357 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4358 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4359 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004360
4361 // Register-register 'add' for thumb does not have a cc_out operand
4362 // when there are only two register operands.
4363 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4364 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4365 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4366 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4367 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004368 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004369 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4370 // have to check the immediate range here since Thumb2 has a variant
4371 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004372 if (((isThumb() && Mnemonic == "add") ||
4373 (isThumbTwo() && Mnemonic == "sub")) &&
4374 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004375 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4376 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4377 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004378 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4379 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4380 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004381 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004382 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4383 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004384 // selecting via the generic "add" mnemonic, so to know that we
4385 // should remove the cc_out operand, we have to explicitly check that
4386 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004387 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4388 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004389 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4390 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4391 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4392 // Nest conditions rather than one big 'if' statement for readability.
4393 //
4394 // If either register is a high reg, it's either one of the SP
4395 // variants (handled above) or a 32-bit encoding, so we just
4396 // check against T3.
4397 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4398 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4399 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4400 return false;
4401 // If both registers are low, we're in an IT block, and the immediate is
4402 // in range, we should use encoding T1 instead, which has a cc_out.
4403 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004404 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004405 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4406 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4407 return false;
4408
4409 // Otherwise, we use encoding T4, which does not have a cc_out
4410 // operand.
4411 return true;
4412 }
4413
Jim Grosbach64944f42011-09-14 21:00:40 +00004414 // The thumb2 multiply instruction doesn't have a CCOut register, so
4415 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4416 // use the 16-bit encoding or not.
4417 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4418 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4419 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4420 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4421 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4422 // If the registers aren't low regs, the destination reg isn't the
4423 // same as one of the source regs, or the cc_out operand is zero
4424 // outside of an IT block, we have to use the 32-bit encoding, so
4425 // remove the cc_out operand.
4426 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4427 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004428 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004429 !inITBlock() ||
4430 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4431 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4432 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4433 static_cast<ARMOperand*>(Operands[4])->getReg())))
4434 return true;
4435
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004436 // Also check the 'mul' syntax variant that doesn't specify an explicit
4437 // destination register.
4438 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4439 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4440 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4441 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4442 // If the registers aren't low regs or the cc_out operand is zero
4443 // outside of an IT block, we have to use the 32-bit encoding, so
4444 // remove the cc_out operand.
4445 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4446 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4447 !inITBlock()))
4448 return true;
4449
Jim Grosbach64944f42011-09-14 21:00:40 +00004450
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004451
Jim Grosbachf69c8042011-08-24 21:42:27 +00004452 // Register-register 'add/sub' for thumb does not have a cc_out operand
4453 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4454 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4455 // right, this will result in better diagnostics (which operand is off)
4456 // anyway.
4457 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4458 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004459 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4460 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4461 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4462 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004463
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004464 return false;
4465}
4466
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004467static bool isDataTypeToken(StringRef Tok) {
4468 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4469 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4470 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4471 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4472 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4473 Tok == ".f" || Tok == ".d";
4474}
4475
4476// FIXME: This bit should probably be handled via an explicit match class
4477// in the .td files that matches the suffix instead of having it be
4478// a literal string token the way it is now.
4479static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4480 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4481}
4482
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004483/// Parse an arm instruction mnemonic followed by its operands.
4484bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4485 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4486 // Create the leading tokens for the mnemonic, split by '.' characters.
4487 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004488 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004489
Daniel Dunbar352e1482011-01-11 15:59:50 +00004490 // Split out the predication code and carry setting flag from the mnemonic.
4491 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004492 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004493 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004494 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004495 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004496 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004497
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004498 // In Thumb1, only the branch (B) instruction can be predicated.
4499 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4500 Parser.EatToEndOfStatement();
4501 return Error(NameLoc, "conditional execution not supported in Thumb1");
4502 }
4503
Jim Grosbachffa32252011-07-19 19:13:28 +00004504 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4505
Jim Grosbach89df9962011-08-26 21:43:41 +00004506 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4507 // is the mask as it will be for the IT encoding if the conditional
4508 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4509 // where the conditional bit0 is zero, the instruction post-processing
4510 // will adjust the mask accordingly.
4511 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004512 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4513 if (ITMask.size() > 3) {
4514 Parser.EatToEndOfStatement();
4515 return Error(Loc, "too many conditions on IT instruction");
4516 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004517 unsigned Mask = 8;
4518 for (unsigned i = ITMask.size(); i != 0; --i) {
4519 char pos = ITMask[i - 1];
4520 if (pos != 't' && pos != 'e') {
4521 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004522 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004523 }
4524 Mask >>= 1;
4525 if (ITMask[i - 1] == 't')
4526 Mask |= 8;
4527 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004528 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004529 }
4530
Jim Grosbachffa32252011-07-19 19:13:28 +00004531 // FIXME: This is all a pretty gross hack. We should automatically handle
4532 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004533
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004534 // Next, add the CCOut and ConditionCode operands, if needed.
4535 //
4536 // For mnemonics which can ever incorporate a carry setting bit or predication
4537 // code, our matching model involves us always generating CCOut and
4538 // ConditionCode operands to match the mnemonic "as written" and then we let
4539 // the matcher deal with finding the right instruction or generating an
4540 // appropriate error.
4541 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004542 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004543
Jim Grosbach33c16a22011-07-14 22:04:21 +00004544 // If we had a carry-set on an instruction that can't do that, issue an
4545 // error.
4546 if (!CanAcceptCarrySet && CarrySetting) {
4547 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004548 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004549 "' can not set flags, but 's' suffix specified");
4550 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004551 // If we had a predication code on an instruction that can't do that, issue an
4552 // error.
4553 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4554 Parser.EatToEndOfStatement();
4555 return Error(NameLoc, "instruction '" + Mnemonic +
4556 "' is not predicable, but condition code specified");
4557 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004558
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004559 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004560 if (CanAcceptCarrySet) {
4561 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004562 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004563 Loc));
4564 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004565
4566 // Add the predication code operand, if necessary.
4567 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004568 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4569 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004570 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004571 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004572 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004573
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004574 // Add the processor imod operand, if necessary.
4575 if (ProcessorIMod) {
4576 Operands.push_back(ARMOperand::CreateImm(
4577 MCConstantExpr::Create(ProcessorIMod, getContext()),
4578 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004579 }
4580
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004581 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004582 while (Next != StringRef::npos) {
4583 Start = Next;
4584 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004585 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004586
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004587 // Some NEON instructions have an optional datatype suffix that is
4588 // completely ignored. Check for that.
4589 if (isDataTypeToken(ExtraToken) &&
4590 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4591 continue;
4592
Jim Grosbach81d2e392011-09-07 16:06:04 +00004593 if (ExtraToken != ".n") {
4594 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4595 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4596 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004597 }
4598
4599 // Read the remaining operands.
4600 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004601 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004602 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004603 Parser.EatToEndOfStatement();
4604 return true;
4605 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004606
4607 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004608 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004609
4610 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004611 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004612 Parser.EatToEndOfStatement();
4613 return true;
4614 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004615 }
4616 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004617
Chris Lattnercbf8a982010-09-11 16:18:25 +00004618 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004619 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004620 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004621 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004622 }
Bill Wendling146018f2010-11-06 21:42:12 +00004623
Chris Lattner34e53142010-09-08 05:10:46 +00004624 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004625
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004626 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4627 // do and don't have a cc_out optional-def operand. With some spot-checks
4628 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004629 // parse and adjust accordingly before actually matching. We shouldn't ever
4630 // try to remove a cc_out operand that was explicitly set on the the
4631 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4632 // table driven matcher doesn't fit well with the ARM instruction set.
4633 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004634 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4635 Operands.erase(Operands.begin() + 1);
4636 delete Op;
4637 }
4638
Jim Grosbachcf121c32011-07-28 21:57:55 +00004639 // ARM mode 'blx' need special handling, as the register operand version
4640 // is predicable, but the label operand version is not. So, we can't rely
4641 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004642 // a k_CondCode operand in the list. If we're trying to match the label
4643 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004644 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4645 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4646 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4647 Operands.erase(Operands.begin() + 1);
4648 delete Op;
4649 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004650
4651 // The vector-compare-to-zero instructions have a literal token "#0" at
4652 // the end that comes to here as an immediate operand. Convert it to a
4653 // token to play nicely with the matcher.
4654 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4655 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4656 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4657 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4659 if (CE && CE->getValue() == 0) {
4660 Operands.erase(Operands.begin() + 5);
4661 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4662 delete Op;
4663 }
4664 }
Jim Grosbach68259142011-10-03 22:30:24 +00004665 // VCMP{E} does the same thing, but with a different operand count.
4666 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4667 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4668 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4669 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4670 if (CE && CE->getValue() == 0) {
4671 Operands.erase(Operands.begin() + 4);
4672 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4673 delete Op;
4674 }
4675 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004676 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4677 // end. Convert it to a token here.
4678 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4679 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4680 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4681 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4682 if (CE && CE->getValue() == 0) {
4683 Operands.erase(Operands.begin() + 5);
4684 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4685 delete Op;
4686 }
4687 }
4688
Chris Lattner98986712010-01-14 22:21:20 +00004689 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004690}
4691
Jim Grosbach189610f2011-07-26 18:25:39 +00004692// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004693
4694// return 'true' if register list contains non-low GPR registers,
4695// 'false' otherwise. If Reg is in the register list or is HiReg, set
4696// 'containsReg' to true.
4697static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4698 unsigned HiReg, bool &containsReg) {
4699 containsReg = false;
4700 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4701 unsigned OpReg = Inst.getOperand(i).getReg();
4702 if (OpReg == Reg)
4703 containsReg = true;
4704 // Anything other than a low register isn't legal here.
4705 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4706 return true;
4707 }
4708 return false;
4709}
4710
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004711// Check if the specified regisgter is in the register list of the inst,
4712// starting at the indicated operand number.
4713static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4714 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4715 unsigned OpReg = Inst.getOperand(i).getReg();
4716 if (OpReg == Reg)
4717 return true;
4718 }
4719 return false;
4720}
4721
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004722// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4723// the ARMInsts array) instead. Getting that here requires awkward
4724// API changes, though. Better way?
4725namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004726extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004727}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004728static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004729 return ARMInsts[Opcode];
4730}
4731
Jim Grosbach189610f2011-07-26 18:25:39 +00004732// FIXME: We would really like to be able to tablegen'erate this.
4733bool ARMAsmParser::
4734validateInstruction(MCInst &Inst,
4735 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004736 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004737 SMLoc Loc = Operands[0]->getStartLoc();
4738 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004739 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4740 // being allowed in IT blocks, but not being predicable. It just always
4741 // executes.
4742 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004743 unsigned bit = 1;
4744 if (ITState.FirstCond)
4745 ITState.FirstCond = false;
4746 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004747 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004748 // The instruction must be predicable.
4749 if (!MCID.isPredicable())
4750 return Error(Loc, "instructions in IT block must be predicable");
4751 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4752 unsigned ITCond = bit ? ITState.Cond :
4753 ARMCC::getOppositeCondition(ITState.Cond);
4754 if (Cond != ITCond) {
4755 // Find the condition code Operand to get its SMLoc information.
4756 SMLoc CondLoc;
4757 for (unsigned i = 1; i < Operands.size(); ++i)
4758 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4759 CondLoc = Operands[i]->getStartLoc();
4760 return Error(CondLoc, "incorrect condition in IT block; got '" +
4761 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4762 "', but expected '" +
4763 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4764 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004765 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004766 } else if (isThumbTwo() && MCID.isPredicable() &&
4767 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004768 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4769 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004770 return Error(Loc, "predicated instructions must be in IT block");
4771
Jim Grosbach189610f2011-07-26 18:25:39 +00004772 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004773 case ARM::LDRD:
4774 case ARM::LDRD_PRE:
4775 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004776 case ARM::LDREXD: {
4777 // Rt2 must be Rt + 1.
4778 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4779 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4780 if (Rt2 != Rt + 1)
4781 return Error(Operands[3]->getStartLoc(),
4782 "destination operands must be sequential");
4783 return false;
4784 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004785 case ARM::STRD: {
4786 // Rt2 must be Rt + 1.
4787 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4788 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4789 if (Rt2 != Rt + 1)
4790 return Error(Operands[3]->getStartLoc(),
4791 "source operands must be sequential");
4792 return false;
4793 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004794 case ARM::STRD_PRE:
4795 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004796 case ARM::STREXD: {
4797 // Rt2 must be Rt + 1.
4798 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4799 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4800 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004801 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004802 "source operands must be sequential");
4803 return false;
4804 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004805 case ARM::SBFX:
4806 case ARM::UBFX: {
4807 // width must be in range [1, 32-lsb]
4808 unsigned lsb = Inst.getOperand(2).getImm();
4809 unsigned widthm1 = Inst.getOperand(3).getImm();
4810 if (widthm1 >= 32 - lsb)
4811 return Error(Operands[5]->getStartLoc(),
4812 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004813 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004814 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004815 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004816 // If we're parsing Thumb2, the .w variant is available and handles
4817 // most cases that are normally illegal for a Thumb1 LDM
4818 // instruction. We'll make the transformation in processInstruction()
4819 // if necessary.
4820 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004821 // Thumb LDM instructions are writeback iff the base register is not
4822 // in the register list.
4823 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004824 bool hasWritebackToken =
4825 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4826 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004827 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004828 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004829 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4830 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004831 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004832 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004833 return Error(Operands[2]->getStartLoc(),
4834 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004835 // If we should not have writeback, there must not be a '!'. This is
4836 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004837 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004838 return Error(Operands[3]->getStartLoc(),
4839 "writeback operator '!' not allowed when base register "
4840 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004841
4842 break;
4843 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004844 case ARM::t2LDMIA_UPD: {
4845 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4846 return Error(Operands[4]->getStartLoc(),
4847 "writeback operator '!' not allowed when base register "
4848 "in register list");
4849 break;
4850 }
Jim Grosbach54026372011-11-10 23:17:11 +00004851 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4852 // so only issue a diagnostic for thumb1. The instructions will be
4853 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004854 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004855 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004856 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4857 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004858 return Error(Operands[2]->getStartLoc(),
4859 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004860 break;
4861 }
4862 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004863 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004864 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4865 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004866 return Error(Operands[2]->getStartLoc(),
4867 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004868 break;
4869 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004870 case ARM::tSTMIA_UPD: {
4871 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004872 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004873 return Error(Operands[4]->getStartLoc(),
4874 "registers must be in range r0-r7");
4875 break;
4876 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004877 }
4878
4879 return false;
4880}
4881
Jim Grosbach84defb52011-12-02 22:34:51 +00004882static unsigned getRealVSTLNOpcode(unsigned Opc) {
4883 switch(Opc) {
4884 default: assert(0 && "unexpected opcode!");
4885 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4886 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4887 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4888 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4889 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4890 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4891 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4892 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4893 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4894 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4895 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4896 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4897 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4898 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4899 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4900 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4901 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4902 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4903 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4904 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4905 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4906 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4907 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4908 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4909 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4910 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4911 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4912 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4913 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4914 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4915 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4916 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4917 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4918 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4919 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4920 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4921 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4922 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4923 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4924 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4925 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4926 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4927 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4928 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4929 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
4930 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
4931 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
4932 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
4933 }
4934}
4935
4936static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004937 switch(Opc) {
4938 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00004939 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
4940 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
4941 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
4942 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
4943 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
4944 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
4945 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
4946 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
4947 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
4948 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
4949 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
4950 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
4951 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
4952 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
4953 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
4954 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
4955 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
4956 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
4957 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
4958 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
4959 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
4960 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
4961 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
4962 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
4963 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
4964 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
4965 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
4966 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
4967 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
4968 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
4969 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
4970 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004971 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
4972 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
4973 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
4974 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
4975 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00004976 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
4977 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
4978 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
4979 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
4980 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004981 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
4982 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
4983 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
4984 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
4985 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
4986 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00004987 }
4988}
4989
Jim Grosbach83ec8772011-11-10 23:42:14 +00004990bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004991processInstruction(MCInst &Inst,
4992 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4993 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00004994 // Handle NEON VST1 complex aliases.
4995 case ARM::VST1LNdWB_register_Asm_8:
4996 case ARM::VST1LNdWB_register_Asm_P8:
4997 case ARM::VST1LNdWB_register_Asm_I8:
4998 case ARM::VST1LNdWB_register_Asm_S8:
4999 case ARM::VST1LNdWB_register_Asm_U8:
5000 case ARM::VST1LNdWB_register_Asm_16:
5001 case ARM::VST1LNdWB_register_Asm_P16:
5002 case ARM::VST1LNdWB_register_Asm_I16:
5003 case ARM::VST1LNdWB_register_Asm_S16:
5004 case ARM::VST1LNdWB_register_Asm_U16:
5005 case ARM::VST1LNdWB_register_Asm_32:
5006 case ARM::VST1LNdWB_register_Asm_F:
5007 case ARM::VST1LNdWB_register_Asm_F32:
5008 case ARM::VST1LNdWB_register_Asm_I32:
5009 case ARM::VST1LNdWB_register_Asm_S32:
5010 case ARM::VST1LNdWB_register_Asm_U32: {
5011 MCInst TmpInst;
5012 // Shuffle the operands around so the lane index operand is in the
5013 // right place.
5014 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5015 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5016 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5017 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5018 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5019 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5020 TmpInst.addOperand(Inst.getOperand(1)); // lane
5021 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5022 TmpInst.addOperand(Inst.getOperand(6));
5023 Inst = TmpInst;
5024 return true;
5025 }
5026 case ARM::VST1LNdWB_fixed_Asm_8:
5027 case ARM::VST1LNdWB_fixed_Asm_P8:
5028 case ARM::VST1LNdWB_fixed_Asm_I8:
5029 case ARM::VST1LNdWB_fixed_Asm_S8:
5030 case ARM::VST1LNdWB_fixed_Asm_U8:
5031 case ARM::VST1LNdWB_fixed_Asm_16:
5032 case ARM::VST1LNdWB_fixed_Asm_P16:
5033 case ARM::VST1LNdWB_fixed_Asm_I16:
5034 case ARM::VST1LNdWB_fixed_Asm_S16:
5035 case ARM::VST1LNdWB_fixed_Asm_U16:
5036 case ARM::VST1LNdWB_fixed_Asm_32:
5037 case ARM::VST1LNdWB_fixed_Asm_F:
5038 case ARM::VST1LNdWB_fixed_Asm_F32:
5039 case ARM::VST1LNdWB_fixed_Asm_I32:
5040 case ARM::VST1LNdWB_fixed_Asm_S32:
5041 case ARM::VST1LNdWB_fixed_Asm_U32: {
5042 MCInst TmpInst;
5043 // Shuffle the operands around so the lane index operand is in the
5044 // right place.
5045 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5046 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5047 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5048 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5049 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5050 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5051 TmpInst.addOperand(Inst.getOperand(1)); // lane
5052 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5053 TmpInst.addOperand(Inst.getOperand(5));
5054 Inst = TmpInst;
5055 return true;
5056 }
5057 case ARM::VST1LNdAsm_8:
5058 case ARM::VST1LNdAsm_P8:
5059 case ARM::VST1LNdAsm_I8:
5060 case ARM::VST1LNdAsm_S8:
5061 case ARM::VST1LNdAsm_U8:
5062 case ARM::VST1LNdAsm_16:
5063 case ARM::VST1LNdAsm_P16:
5064 case ARM::VST1LNdAsm_I16:
5065 case ARM::VST1LNdAsm_S16:
5066 case ARM::VST1LNdAsm_U16:
5067 case ARM::VST1LNdAsm_32:
5068 case ARM::VST1LNdAsm_F:
5069 case ARM::VST1LNdAsm_F32:
5070 case ARM::VST1LNdAsm_I32:
5071 case ARM::VST1LNdAsm_S32:
5072 case ARM::VST1LNdAsm_U32: {
5073 MCInst TmpInst;
5074 // Shuffle the operands around so the lane index operand is in the
5075 // right place.
5076 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5077 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5078 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5079 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5080 TmpInst.addOperand(Inst.getOperand(1)); // lane
5081 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5082 TmpInst.addOperand(Inst.getOperand(5));
5083 Inst = TmpInst;
5084 return true;
5085 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005086 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005087 case ARM::VLD1LNdWB_register_Asm_8:
5088 case ARM::VLD1LNdWB_register_Asm_P8:
5089 case ARM::VLD1LNdWB_register_Asm_I8:
5090 case ARM::VLD1LNdWB_register_Asm_S8:
5091 case ARM::VLD1LNdWB_register_Asm_U8:
5092 case ARM::VLD1LNdWB_register_Asm_16:
5093 case ARM::VLD1LNdWB_register_Asm_P16:
5094 case ARM::VLD1LNdWB_register_Asm_I16:
5095 case ARM::VLD1LNdWB_register_Asm_S16:
5096 case ARM::VLD1LNdWB_register_Asm_U16:
5097 case ARM::VLD1LNdWB_register_Asm_32:
5098 case ARM::VLD1LNdWB_register_Asm_F:
5099 case ARM::VLD1LNdWB_register_Asm_F32:
5100 case ARM::VLD1LNdWB_register_Asm_I32:
5101 case ARM::VLD1LNdWB_register_Asm_S32:
5102 case ARM::VLD1LNdWB_register_Asm_U32: {
5103 MCInst TmpInst;
5104 // Shuffle the operands around so the lane index operand is in the
5105 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005106 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005107 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5108 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5109 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5110 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5111 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5112 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5113 TmpInst.addOperand(Inst.getOperand(1)); // lane
5114 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5115 TmpInst.addOperand(Inst.getOperand(6));
5116 Inst = TmpInst;
5117 return true;
5118 }
5119 case ARM::VLD1LNdWB_fixed_Asm_8:
5120 case ARM::VLD1LNdWB_fixed_Asm_P8:
5121 case ARM::VLD1LNdWB_fixed_Asm_I8:
5122 case ARM::VLD1LNdWB_fixed_Asm_S8:
5123 case ARM::VLD1LNdWB_fixed_Asm_U8:
5124 case ARM::VLD1LNdWB_fixed_Asm_16:
5125 case ARM::VLD1LNdWB_fixed_Asm_P16:
5126 case ARM::VLD1LNdWB_fixed_Asm_I16:
5127 case ARM::VLD1LNdWB_fixed_Asm_S16:
5128 case ARM::VLD1LNdWB_fixed_Asm_U16:
5129 case ARM::VLD1LNdWB_fixed_Asm_32:
5130 case ARM::VLD1LNdWB_fixed_Asm_F:
5131 case ARM::VLD1LNdWB_fixed_Asm_F32:
5132 case ARM::VLD1LNdWB_fixed_Asm_I32:
5133 case ARM::VLD1LNdWB_fixed_Asm_S32:
5134 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5135 MCInst TmpInst;
5136 // Shuffle the operands around so the lane index operand is in the
5137 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005138 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005139 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5140 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5141 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5142 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5143 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5144 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5145 TmpInst.addOperand(Inst.getOperand(1)); // lane
5146 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5147 TmpInst.addOperand(Inst.getOperand(5));
5148 Inst = TmpInst;
5149 return true;
5150 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005151 case ARM::VLD1LNdAsm_8:
5152 case ARM::VLD1LNdAsm_P8:
5153 case ARM::VLD1LNdAsm_I8:
5154 case ARM::VLD1LNdAsm_S8:
5155 case ARM::VLD1LNdAsm_U8:
5156 case ARM::VLD1LNdAsm_16:
5157 case ARM::VLD1LNdAsm_P16:
5158 case ARM::VLD1LNdAsm_I16:
5159 case ARM::VLD1LNdAsm_S16:
5160 case ARM::VLD1LNdAsm_U16:
5161 case ARM::VLD1LNdAsm_32:
5162 case ARM::VLD1LNdAsm_F:
5163 case ARM::VLD1LNdAsm_F32:
5164 case ARM::VLD1LNdAsm_I32:
5165 case ARM::VLD1LNdAsm_S32:
5166 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005167 MCInst TmpInst;
5168 // Shuffle the operands around so the lane index operand is in the
5169 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005170 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005171 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5172 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5173 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5174 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5175 TmpInst.addOperand(Inst.getOperand(1)); // lane
5176 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5177 TmpInst.addOperand(Inst.getOperand(5));
5178 Inst = TmpInst;
5179 return true;
5180 }
Jim Grosbach71810ab2011-11-10 16:44:55 +00005181 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005182 case ARM::ASRr:
5183 case ARM::LSRr:
5184 case ARM::LSLr:
5185 case ARM::RORr: {
5186 ARM_AM::ShiftOpc ShiftTy;
5187 switch(Inst.getOpcode()) {
5188 default: llvm_unreachable("unexpected opcode!");
5189 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5190 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5191 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5192 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5193 }
5194 // A shift by zero is a plain MOVr, not a MOVsi.
5195 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5196 MCInst TmpInst;
5197 TmpInst.setOpcode(ARM::MOVsr);
5198 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5199 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5200 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5201 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5202 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5203 TmpInst.addOperand(Inst.getOperand(4));
5204 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5205 Inst = TmpInst;
5206 return true;
5207 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005208 case ARM::ASRi:
5209 case ARM::LSRi:
5210 case ARM::LSLi:
5211 case ARM::RORi: {
5212 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005213 switch(Inst.getOpcode()) {
5214 default: llvm_unreachable("unexpected opcode!");
5215 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5216 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5217 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5218 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5219 }
5220 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005221 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005222 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5223 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005224 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005225 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005226 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5227 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005228 if (Opc == ARM::MOVsi)
5229 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005230 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5231 TmpInst.addOperand(Inst.getOperand(4));
5232 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5233 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005234 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005235 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005236 case ARM::RRXi: {
5237 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5238 MCInst TmpInst;
5239 TmpInst.setOpcode(ARM::MOVsi);
5240 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5241 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5242 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5243 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5244 TmpInst.addOperand(Inst.getOperand(3));
5245 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5246 Inst = TmpInst;
5247 return true;
5248 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005249 case ARM::t2LDMIA_UPD: {
5250 // If this is a load of a single register, then we should use
5251 // a post-indexed LDR instruction instead, per the ARM ARM.
5252 if (Inst.getNumOperands() != 5)
5253 return false;
5254 MCInst TmpInst;
5255 TmpInst.setOpcode(ARM::t2LDR_POST);
5256 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5257 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5258 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5259 TmpInst.addOperand(MCOperand::CreateImm(4));
5260 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5261 TmpInst.addOperand(Inst.getOperand(3));
5262 Inst = TmpInst;
5263 return true;
5264 }
5265 case ARM::t2STMDB_UPD: {
5266 // If this is a store of a single register, then we should use
5267 // a pre-indexed STR instruction instead, per the ARM ARM.
5268 if (Inst.getNumOperands() != 5)
5269 return false;
5270 MCInst TmpInst;
5271 TmpInst.setOpcode(ARM::t2STR_PRE);
5272 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5273 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5274 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5275 TmpInst.addOperand(MCOperand::CreateImm(-4));
5276 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5277 TmpInst.addOperand(Inst.getOperand(3));
5278 Inst = TmpInst;
5279 return true;
5280 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005281 case ARM::LDMIA_UPD:
5282 // If this is a load of a single register via a 'pop', then we should use
5283 // a post-indexed LDR instruction instead, per the ARM ARM.
5284 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5285 Inst.getNumOperands() == 5) {
5286 MCInst TmpInst;
5287 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5288 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5289 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5290 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5291 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5292 TmpInst.addOperand(MCOperand::CreateImm(4));
5293 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5294 TmpInst.addOperand(Inst.getOperand(3));
5295 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005296 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005297 }
5298 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005299 case ARM::STMDB_UPD:
5300 // If this is a store of a single register via a 'push', then we should use
5301 // a pre-indexed STR instruction instead, per the ARM ARM.
5302 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5303 Inst.getNumOperands() == 5) {
5304 MCInst TmpInst;
5305 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5306 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5307 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5308 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5309 TmpInst.addOperand(MCOperand::CreateImm(-4));
5310 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5311 TmpInst.addOperand(Inst.getOperand(3));
5312 Inst = TmpInst;
5313 }
5314 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005315 case ARM::t2ADDri12:
5316 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5317 // mnemonic was used (not "addw"), encoding T3 is preferred.
5318 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5319 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5320 break;
5321 Inst.setOpcode(ARM::t2ADDri);
5322 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5323 break;
5324 case ARM::t2SUBri12:
5325 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5326 // mnemonic was used (not "subw"), encoding T3 is preferred.
5327 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5328 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5329 break;
5330 Inst.setOpcode(ARM::t2SUBri);
5331 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5332 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005333 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005334 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5335 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5336 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5337 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005338 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005339 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005340 return true;
5341 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005342 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005343 case ARM::tSUBi8:
5344 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5345 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5346 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5347 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005348 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005349 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005350 return true;
5351 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005352 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005353 case ARM::t2ADDrr: {
5354 // If the destination and first source operand are the same, and
5355 // there's no setting of the flags, use encoding T2 instead of T3.
5356 // Note that this is only for ADD, not SUB. This mirrors the system
5357 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5358 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5359 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005360 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5361 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005362 break;
5363 MCInst TmpInst;
5364 TmpInst.setOpcode(ARM::tADDhirr);
5365 TmpInst.addOperand(Inst.getOperand(0));
5366 TmpInst.addOperand(Inst.getOperand(0));
5367 TmpInst.addOperand(Inst.getOperand(2));
5368 TmpInst.addOperand(Inst.getOperand(3));
5369 TmpInst.addOperand(Inst.getOperand(4));
5370 Inst = TmpInst;
5371 return true;
5372 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005373 case ARM::tB:
5374 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005375 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005376 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005377 return true;
5378 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005379 break;
5380 case ARM::t2B:
5381 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005382 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005383 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005384 return true;
5385 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005386 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005387 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005388 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005389 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005390 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005391 return true;
5392 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005393 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005394 case ARM::tBcc:
5395 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005396 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005397 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005398 return true;
5399 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005400 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005401 case ARM::tLDMIA: {
5402 // If the register list contains any high registers, or if the writeback
5403 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5404 // instead if we're in Thumb2. Otherwise, this should have generated
5405 // an error in validateInstruction().
5406 unsigned Rn = Inst.getOperand(0).getReg();
5407 bool hasWritebackToken =
5408 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5409 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5410 bool listContainsBase;
5411 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5412 (!listContainsBase && !hasWritebackToken) ||
5413 (listContainsBase && hasWritebackToken)) {
5414 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5415 assert (isThumbTwo());
5416 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5417 // If we're switching to the updating version, we need to insert
5418 // the writeback tied operand.
5419 if (hasWritebackToken)
5420 Inst.insert(Inst.begin(),
5421 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005422 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005423 }
5424 break;
5425 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005426 case ARM::tSTMIA_UPD: {
5427 // If the register list contains any high registers, we need to use
5428 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5429 // should have generated an error in validateInstruction().
5430 unsigned Rn = Inst.getOperand(0).getReg();
5431 bool listContainsBase;
5432 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5433 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5434 assert (isThumbTwo());
5435 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005436 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005437 }
5438 break;
5439 }
Jim Grosbach54026372011-11-10 23:17:11 +00005440 case ARM::tPOP: {
5441 bool listContainsBase;
5442 // If the register list contains any high registers, we need to use
5443 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5444 // should have generated an error in validateInstruction().
5445 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005446 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005447 assert (isThumbTwo());
5448 Inst.setOpcode(ARM::t2LDMIA_UPD);
5449 // Add the base register and writeback operands.
5450 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5451 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005452 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005453 }
5454 case ARM::tPUSH: {
5455 bool listContainsBase;
5456 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005457 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005458 assert (isThumbTwo());
5459 Inst.setOpcode(ARM::t2STMDB_UPD);
5460 // Add the base register and writeback operands.
5461 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5462 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005463 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005464 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005465 case ARM::t2MOVi: {
5466 // If we can use the 16-bit encoding and the user didn't explicitly
5467 // request the 32-bit variant, transform it here.
5468 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5469 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005470 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5471 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5472 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005473 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5474 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5475 // The operands aren't in the same order for tMOVi8...
5476 MCInst TmpInst;
5477 TmpInst.setOpcode(ARM::tMOVi8);
5478 TmpInst.addOperand(Inst.getOperand(0));
5479 TmpInst.addOperand(Inst.getOperand(4));
5480 TmpInst.addOperand(Inst.getOperand(1));
5481 TmpInst.addOperand(Inst.getOperand(2));
5482 TmpInst.addOperand(Inst.getOperand(3));
5483 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005484 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005485 }
5486 break;
5487 }
5488 case ARM::t2MOVr: {
5489 // If we can use the 16-bit encoding and the user didn't explicitly
5490 // request the 32-bit variant, transform it here.
5491 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5492 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5493 Inst.getOperand(2).getImm() == ARMCC::AL &&
5494 Inst.getOperand(4).getReg() == ARM::CPSR &&
5495 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5496 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5497 // The operands aren't the same for tMOV[S]r... (no cc_out)
5498 MCInst TmpInst;
5499 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5500 TmpInst.addOperand(Inst.getOperand(0));
5501 TmpInst.addOperand(Inst.getOperand(1));
5502 TmpInst.addOperand(Inst.getOperand(2));
5503 TmpInst.addOperand(Inst.getOperand(3));
5504 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005505 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005506 }
5507 break;
5508 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005509 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005510 case ARM::t2SXTB:
5511 case ARM::t2UXTH:
5512 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005513 // If we can use the 16-bit encoding and the user didn't explicitly
5514 // request the 32-bit variant, transform it here.
5515 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5516 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5517 Inst.getOperand(2).getImm() == 0 &&
5518 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5519 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005520 unsigned NewOpc;
5521 switch (Inst.getOpcode()) {
5522 default: llvm_unreachable("Illegal opcode!");
5523 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5524 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5525 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5526 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5527 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005528 // The operands aren't the same for thumb1 (no rotate operand).
5529 MCInst TmpInst;
5530 TmpInst.setOpcode(NewOpc);
5531 TmpInst.addOperand(Inst.getOperand(0));
5532 TmpInst.addOperand(Inst.getOperand(1));
5533 TmpInst.addOperand(Inst.getOperand(3));
5534 TmpInst.addOperand(Inst.getOperand(4));
5535 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005536 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005537 }
5538 break;
5539 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005540 case ARM::t2IT: {
5541 // The mask bits for all but the first condition are represented as
5542 // the low bit of the condition code value implies 't'. We currently
5543 // always have 1 implies 't', so XOR toggle the bits if the low bit
5544 // of the condition code is zero. The encoding also expects the low
5545 // bit of the condition to be encoded as bit 4 of the mask operand,
5546 // so mask that in if needed
5547 MCOperand &MO = Inst.getOperand(1);
5548 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005549 unsigned OrigMask = Mask;
5550 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005551 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005552 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5553 for (unsigned i = 3; i != TZ; --i)
5554 Mask ^= 1 << i;
5555 } else
5556 Mask |= 0x10;
5557 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005558
5559 // Set up the IT block state according to the IT instruction we just
5560 // matched.
5561 assert(!inITBlock() && "nested IT blocks?!");
5562 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5563 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5564 ITState.CurPosition = 0;
5565 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005566 break;
5567 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005568 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005569 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005570}
5571
Jim Grosbach47a0d522011-08-16 20:45:50 +00005572unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5573 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5574 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005575 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005576 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005577 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5578 assert(MCID.hasOptionalDef() &&
5579 "optionally flag setting instruction missing optional def operand");
5580 assert(MCID.NumOperands == Inst.getNumOperands() &&
5581 "operand count mismatch!");
5582 // Find the optional-def operand (cc_out).
5583 unsigned OpNo;
5584 for (OpNo = 0;
5585 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5586 ++OpNo)
5587 ;
5588 // If we're parsing Thumb1, reject it completely.
5589 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5590 return Match_MnemonicFail;
5591 // If we're parsing Thumb2, which form is legal depends on whether we're
5592 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005593 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5594 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005595 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005596 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5597 inITBlock())
5598 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005599 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005600 // Some high-register supporting Thumb1 encodings only allow both registers
5601 // to be from r0-r7 when in Thumb2.
5602 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5603 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5604 isARMLowRegister(Inst.getOperand(2).getReg()))
5605 return Match_RequiresThumb2;
5606 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005607 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005608 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5609 isARMLowRegister(Inst.getOperand(1).getReg()))
5610 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005611 return Match_Success;
5612}
5613
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005614bool ARMAsmParser::
5615MatchAndEmitInstruction(SMLoc IDLoc,
5616 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5617 MCStreamer &Out) {
5618 MCInst Inst;
5619 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005620 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005621 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005622 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005623 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005624 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005625 // Context sensitive operand constraints aren't handled by the matcher,
5626 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005627 if (validateInstruction(Inst, Operands)) {
5628 // Still progress the IT block, otherwise one wrong condition causes
5629 // nasty cascading errors.
5630 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005631 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005632 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005633
Jim Grosbachf8fce712011-08-11 17:35:48 +00005634 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005635 // encoding is selected. Loop on it while changes happen so the
5636 // individual transformations can chain off each other. E.g.,
5637 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5638 while (processInstruction(Inst, Operands))
5639 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005640
Jim Grosbacha1109882011-09-02 23:22:08 +00005641 // Only move forward at the very end so that everything in validate
5642 // and process gets a consistent answer about whether we're in an IT
5643 // block.
5644 forwardITPosition();
5645
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005646 Out.EmitInstruction(Inst);
5647 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005648 case Match_MissingFeature:
5649 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5650 return true;
5651 case Match_InvalidOperand: {
5652 SMLoc ErrorLoc = IDLoc;
5653 if (ErrorInfo != ~0U) {
5654 if (ErrorInfo >= Operands.size())
5655 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005656
Chris Lattnere73d4f82010-10-28 21:41:58 +00005657 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5658 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5659 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005660
Chris Lattnere73d4f82010-10-28 21:41:58 +00005661 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005662 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005663 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005664 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005665 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005666 // The converter function will have already emited a diagnostic.
5667 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005668 case Match_RequiresNotITBlock:
5669 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005670 case Match_RequiresITBlock:
5671 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005672 case Match_RequiresV6:
5673 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5674 case Match_RequiresThumb2:
5675 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005676 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005677
Eric Christopherc223e2b2010-10-29 09:26:59 +00005678 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005679 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005680}
5681
Jim Grosbach1355cf12011-07-26 17:10:22 +00005682/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005683bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5684 StringRef IDVal = DirectiveID.getIdentifier();
5685 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005686 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005687 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005688 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00005689 else if (IDVal == ".arm")
5690 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005691 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005692 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005693 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005694 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005695 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005696 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005697 return true;
5698}
5699
Jim Grosbach1355cf12011-07-26 17:10:22 +00005700/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005701/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005702bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5704 for (;;) {
5705 const MCExpr *Value;
5706 if (getParser().ParseExpression(Value))
5707 return true;
5708
Chris Lattneraaec2052010-01-19 19:46:13 +00005709 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005710
5711 if (getLexer().is(AsmToken::EndOfStatement))
5712 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005713
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005714 // FIXME: Improve diagnostic.
5715 if (getLexer().isNot(AsmToken::Comma))
5716 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005717 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005718 }
5719 }
5720
Sean Callananb9a25b72010-01-19 20:27:46 +00005721 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005722 return false;
5723}
5724
Jim Grosbach1355cf12011-07-26 17:10:22 +00005725/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005726/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005727bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005728 if (getLexer().isNot(AsmToken::EndOfStatement))
5729 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005730 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005731
Jim Grosbach9a70df92011-12-07 18:04:19 +00005732 if (!isThumb())
5733 SwitchMode();
5734 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5735 return false;
5736}
5737
5738/// parseDirectiveARM
5739/// ::= .arm
5740bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5741 if (getLexer().isNot(AsmToken::EndOfStatement))
5742 return Error(L, "unexpected token in directive");
5743 Parser.Lex();
5744
5745 if (isThumb())
5746 SwitchMode();
5747 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00005748 return false;
5749}
5750
Jim Grosbach1355cf12011-07-26 17:10:22 +00005751/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005752/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005753bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005754 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5755 bool isMachO = MAI.hasSubsectionsViaSymbols();
5756 StringRef Name;
5757
5758 // Darwin asm has function name after .thumb_func direction
5759 // ELF doesn't
5760 if (isMachO) {
5761 const AsmToken &Tok = Parser.getTok();
5762 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5763 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005764 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005765 Parser.Lex(); // Consume the identifier token.
5766 }
5767
Jim Grosbachd475f862011-11-10 20:48:53 +00005768 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005769 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005770 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005771
Rafael Espindola64695402011-05-16 16:17:21 +00005772 // FIXME: assuming function name will be the line following .thumb_func
5773 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005774 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005775 }
5776
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005777 // Mark symbol as a thumb symbol.
5778 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5779 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005780 return false;
5781}
5782
Jim Grosbach1355cf12011-07-26 17:10:22 +00005783/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005784/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005785bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005786 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005787 if (Tok.isNot(AsmToken::Identifier))
5788 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005789 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005790 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005791 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005792 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005793 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005794 else
5795 return Error(L, "unrecognized syntax mode in .syntax directive");
5796
5797 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005798 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005799 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005800
5801 // TODO tell the MC streamer the mode
5802 // getParser().getStreamer().Emit???();
5803 return false;
5804}
5805
Jim Grosbach1355cf12011-07-26 17:10:22 +00005806/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005807/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005808bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005809 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005810 if (Tok.isNot(AsmToken::Integer))
5811 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005812 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005813 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005814 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005815 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005816 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005817 else
5818 return Error(L, "invalid operand to .code directive");
5819
5820 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005821 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005822 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005823
Evan Cheng32869202011-07-08 22:36:29 +00005824 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005825 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005826 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005827 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005828 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005829 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005830 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005831 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005832 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005833
Kevin Enderby515d5092009-10-15 20:48:48 +00005834 return false;
5835}
5836
Sean Callanan90b70972010-04-07 20:29:34 +00005837extern "C" void LLVMInitializeARMAsmLexer();
5838
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005839/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005840extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005841 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5842 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005843 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005844}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005845
Chris Lattner0692ee62010-09-06 19:11:01 +00005846#define GET_REGISTER_MATCHER
5847#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005848#include "ARMGenAsmMatcher.inc"