blob: 7e1d6333fa6b0f1606e570b22ca2f07a3f58b0a6 [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
Chris Lattnere5658fa2010-10-30 04:09:10 +00002151 // FIXME: Validate register for the current architecture; we have to do
2152 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002153 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002154 unsigned RegNum = MatchRegisterName(lowerCase);
2155 if (!RegNum) {
2156 RegNum = StringSwitch<unsigned>(lowerCase)
2157 .Case("r13", ARM::SP)
2158 .Case("r14", ARM::LR)
2159 .Case("r15", ARM::PC)
2160 .Case("ip", ARM::R12)
2161 .Default(0);
2162 }
2163 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002164
Chris Lattnere5658fa2010-10-30 04:09:10 +00002165 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002166
Chris Lattnere5658fa2010-10-30 04:09:10 +00002167 return RegNum;
2168}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002169
Jim Grosbach19906722011-07-13 18:49:30 +00002170// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2171// If a recoverable error occurs, return 1. If an irrecoverable error
2172// occurs, return -1. An irrecoverable error is one where tokens have been
2173// consumed in the process of trying to parse the shifter (i.e., when it is
2174// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002175int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002176 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2177 SMLoc S = Parser.getTok().getLoc();
2178 const AsmToken &Tok = Parser.getTok();
2179 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2180
Benjamin Kramer59085362011-11-06 20:37:06 +00002181 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002182 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002183 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002184 .Case("lsl", ARM_AM::lsl)
2185 .Case("lsr", ARM_AM::lsr)
2186 .Case("asr", ARM_AM::asr)
2187 .Case("ror", ARM_AM::ror)
2188 .Case("rrx", ARM_AM::rrx)
2189 .Default(ARM_AM::no_shift);
2190
2191 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002192 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002193
Jim Grosbache8606dc2011-07-13 17:50:29 +00002194 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002195
Jim Grosbache8606dc2011-07-13 17:50:29 +00002196 // The source register for the shift has already been added to the
2197 // operand list, so we need to pop it off and combine it into the shifted
2198 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002199 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002200 if (!PrevOp->isReg())
2201 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2202 int SrcReg = PrevOp->getReg();
2203 int64_t Imm = 0;
2204 int ShiftReg = 0;
2205 if (ShiftTy == ARM_AM::rrx) {
2206 // RRX Doesn't have an explicit shift amount. The encoder expects
2207 // the shift register to be the same as the source register. Seems odd,
2208 // but OK.
2209 ShiftReg = SrcReg;
2210 } else {
2211 // Figure out if this is shifted by a constant or a register (for non-RRX).
2212 if (Parser.getTok().is(AsmToken::Hash)) {
2213 Parser.Lex(); // Eat hash.
2214 SMLoc ImmLoc = Parser.getTok().getLoc();
2215 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002216 if (getParser().ParseExpression(ShiftExpr)) {
2217 Error(ImmLoc, "invalid immediate shift value");
2218 return -1;
2219 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002220 // The expression must be evaluatable as an immediate.
2221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002222 if (!CE) {
2223 Error(ImmLoc, "invalid immediate shift value");
2224 return -1;
2225 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002226 // Range check the immediate.
2227 // lsl, ror: 0 <= imm <= 31
2228 // lsr, asr: 0 <= imm <= 32
2229 Imm = CE->getValue();
2230 if (Imm < 0 ||
2231 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2232 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002233 Error(ImmLoc, "immediate shift value out of range");
2234 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002235 }
2236 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002237 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002238 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002239 if (ShiftReg == -1) {
2240 Error (L, "expected immediate or register in shift operand");
2241 return -1;
2242 }
2243 } else {
2244 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002245 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002246 return -1;
2247 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002248 }
2249
Owen Anderson92a20222011-07-21 18:54:16 +00002250 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2251 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002252 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002253 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002254 else
2255 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2256 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002257
Jim Grosbach19906722011-07-13 18:49:30 +00002258 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002259}
2260
2261
Bill Wendling50d0f582010-11-18 23:43:05 +00002262/// Try to parse a register name. The token must be an Identifier when called.
2263/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2264/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002265///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002266/// TODO this is likely to change to allow different register types and or to
2267/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002268bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002269tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002270 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002271 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002272 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002273 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002274
Bill Wendling50d0f582010-11-18 23:43:05 +00002275 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002276
Chris Lattnere5658fa2010-10-30 04:09:10 +00002277 const AsmToken &ExclaimTok = Parser.getTok();
2278 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002279 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2280 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002281 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002282 return false;
2283 }
2284
2285 // Also check for an index operand. This is only legal for vector registers,
2286 // but that'll get caught OK in operand matching, so we don't need to
2287 // explicitly filter everything else out here.
2288 if (Parser.getTok().is(AsmToken::LBrac)) {
2289 SMLoc SIdx = Parser.getTok().getLoc();
2290 Parser.Lex(); // Eat left bracket token.
2291
2292 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002293 if (getParser().ParseExpression(ImmVal))
2294 return MatchOperand_ParseFail;
2295 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2296 if (!MCE) {
2297 TokError("immediate value expected for vector index");
2298 return MatchOperand_ParseFail;
2299 }
2300
2301 SMLoc E = Parser.getTok().getLoc();
2302 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2303 Error(E, "']' expected");
2304 return MatchOperand_ParseFail;
2305 }
2306
2307 Parser.Lex(); // Eat right bracket token.
2308
2309 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2310 SIdx, E,
2311 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002312 }
2313
Bill Wendling50d0f582010-11-18 23:43:05 +00002314 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002315}
2316
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002317/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2318/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2319/// "c5", ...
2320static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002321 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2322 // but efficient.
2323 switch (Name.size()) {
2324 default: break;
2325 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002326 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002327 return -1;
2328 switch (Name[1]) {
2329 default: return -1;
2330 case '0': return 0;
2331 case '1': return 1;
2332 case '2': return 2;
2333 case '3': return 3;
2334 case '4': return 4;
2335 case '5': return 5;
2336 case '6': return 6;
2337 case '7': return 7;
2338 case '8': return 8;
2339 case '9': return 9;
2340 }
2341 break;
2342 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002343 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002344 return -1;
2345 switch (Name[2]) {
2346 default: return -1;
2347 case '0': return 10;
2348 case '1': return 11;
2349 case '2': return 12;
2350 case '3': return 13;
2351 case '4': return 14;
2352 case '5': return 15;
2353 }
2354 break;
2355 }
2356
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002357 return -1;
2358}
2359
Jim Grosbach89df9962011-08-26 21:43:41 +00002360/// parseITCondCode - Try to parse a condition code for an IT instruction.
2361ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2362parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2363 SMLoc S = Parser.getTok().getLoc();
2364 const AsmToken &Tok = Parser.getTok();
2365 if (!Tok.is(AsmToken::Identifier))
2366 return MatchOperand_NoMatch;
2367 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2368 .Case("eq", ARMCC::EQ)
2369 .Case("ne", ARMCC::NE)
2370 .Case("hs", ARMCC::HS)
2371 .Case("cs", ARMCC::HS)
2372 .Case("lo", ARMCC::LO)
2373 .Case("cc", ARMCC::LO)
2374 .Case("mi", ARMCC::MI)
2375 .Case("pl", ARMCC::PL)
2376 .Case("vs", ARMCC::VS)
2377 .Case("vc", ARMCC::VC)
2378 .Case("hi", ARMCC::HI)
2379 .Case("ls", ARMCC::LS)
2380 .Case("ge", ARMCC::GE)
2381 .Case("lt", ARMCC::LT)
2382 .Case("gt", ARMCC::GT)
2383 .Case("le", ARMCC::LE)
2384 .Case("al", ARMCC::AL)
2385 .Default(~0U);
2386 if (CC == ~0U)
2387 return MatchOperand_NoMatch;
2388 Parser.Lex(); // Eat the token.
2389
2390 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2391
2392 return MatchOperand_Success;
2393}
2394
Jim Grosbach43904292011-07-25 20:14:50 +00002395/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002396/// token must be an Identifier when called, and if it is a coprocessor
2397/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002398ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002399parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002400 SMLoc S = Parser.getTok().getLoc();
2401 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002402 if (Tok.isNot(AsmToken::Identifier))
2403 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002404
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002405 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002406 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002407 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002408
2409 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002410 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002411 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002412}
2413
Jim Grosbach43904292011-07-25 20:14:50 +00002414/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002415/// token must be an Identifier when called, and if it is a coprocessor
2416/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002417ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002418parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002419 SMLoc S = Parser.getTok().getLoc();
2420 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002421 if (Tok.isNot(AsmToken::Identifier))
2422 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002423
2424 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2425 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002426 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002427
2428 Parser.Lex(); // Eat identifier token.
2429 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002430 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002431}
2432
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002433/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2434/// coproc_option : '{' imm0_255 '}'
2435ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2436parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2437 SMLoc S = Parser.getTok().getLoc();
2438
2439 // If this isn't a '{', this isn't a coprocessor immediate operand.
2440 if (Parser.getTok().isNot(AsmToken::LCurly))
2441 return MatchOperand_NoMatch;
2442 Parser.Lex(); // Eat the '{'
2443
2444 const MCExpr *Expr;
2445 SMLoc Loc = Parser.getTok().getLoc();
2446 if (getParser().ParseExpression(Expr)) {
2447 Error(Loc, "illegal expression");
2448 return MatchOperand_ParseFail;
2449 }
2450 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2451 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2452 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2453 return MatchOperand_ParseFail;
2454 }
2455 int Val = CE->getValue();
2456
2457 // Check for and consume the closing '}'
2458 if (Parser.getTok().isNot(AsmToken::RCurly))
2459 return MatchOperand_ParseFail;
2460 SMLoc E = Parser.getTok().getLoc();
2461 Parser.Lex(); // Eat the '}'
2462
2463 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2464 return MatchOperand_Success;
2465}
2466
Jim Grosbachd0588e22011-09-14 18:08:35 +00002467// For register list parsing, we need to map from raw GPR register numbering
2468// to the enumeration values. The enumeration values aren't sorted by
2469// register number due to our using "sp", "lr" and "pc" as canonical names.
2470static unsigned getNextRegister(unsigned Reg) {
2471 // If this is a GPR, we need to do it manually, otherwise we can rely
2472 // on the sort ordering of the enumeration since the other reg-classes
2473 // are sane.
2474 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2475 return Reg + 1;
2476 switch(Reg) {
2477 default: assert(0 && "Invalid GPR number!");
2478 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2479 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2480 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2481 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2482 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2483 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2484 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2485 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2486 }
2487}
2488
Jim Grosbachce485e72011-11-11 21:27:40 +00002489// Return the low-subreg of a given Q register.
2490static unsigned getDRegFromQReg(unsigned QReg) {
2491 switch (QReg) {
2492 default: llvm_unreachable("expected a Q register!");
2493 case ARM::Q0: return ARM::D0;
2494 case ARM::Q1: return ARM::D2;
2495 case ARM::Q2: return ARM::D4;
2496 case ARM::Q3: return ARM::D6;
2497 case ARM::Q4: return ARM::D8;
2498 case ARM::Q5: return ARM::D10;
2499 case ARM::Q6: return ARM::D12;
2500 case ARM::Q7: return ARM::D14;
2501 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002502 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002503 case ARM::Q10: return ARM::D20;
2504 case ARM::Q11: return ARM::D22;
2505 case ARM::Q12: return ARM::D24;
2506 case ARM::Q13: return ARM::D26;
2507 case ARM::Q14: return ARM::D28;
2508 case ARM::Q15: return ARM::D30;
2509 }
2510}
2511
Jim Grosbachd0588e22011-09-14 18:08:35 +00002512/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002513bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002514parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002515 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002516 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002517 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002518 Parser.Lex(); // Eat '{' token.
2519 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002520
Jim Grosbachd0588e22011-09-14 18:08:35 +00002521 // Check the first register in the list to see what register class
2522 // this is a list of.
2523 int Reg = tryParseRegister();
2524 if (Reg == -1)
2525 return Error(RegLoc, "register expected");
2526
Jim Grosbachce485e72011-11-11 21:27:40 +00002527 // The reglist instructions have at most 16 registers, so reserve
2528 // space for that many.
2529 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2530
2531 // Allow Q regs and just interpret them as the two D sub-registers.
2532 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2533 Reg = getDRegFromQReg(Reg);
2534 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2535 ++Reg;
2536 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002537 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002538 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2539 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2540 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2541 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2542 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2543 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2544 else
2545 return Error(RegLoc, "invalid register in register list");
2546
Jim Grosbachce485e72011-11-11 21:27:40 +00002547 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002548 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002549
Jim Grosbachd0588e22011-09-14 18:08:35 +00002550 // This starts immediately after the first register token in the list,
2551 // so we can see either a comma or a minus (range separator) as a legal
2552 // next token.
2553 while (Parser.getTok().is(AsmToken::Comma) ||
2554 Parser.getTok().is(AsmToken::Minus)) {
2555 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002556 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002557 SMLoc EndLoc = Parser.getTok().getLoc();
2558 int EndReg = tryParseRegister();
2559 if (EndReg == -1)
2560 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002561 // Allow Q regs and just interpret them as the two D sub-registers.
2562 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2563 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002564 // If the register is the same as the start reg, there's nothing
2565 // more to do.
2566 if (Reg == EndReg)
2567 continue;
2568 // The register must be in the same register class as the first.
2569 if (!RC->contains(EndReg))
2570 return Error(EndLoc, "invalid register in register list");
2571 // Ranges must go from low to high.
2572 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2573 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002574
Jim Grosbachd0588e22011-09-14 18:08:35 +00002575 // Add all the registers in the range to the register list.
2576 while (Reg != EndReg) {
2577 Reg = getNextRegister(Reg);
2578 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2579 }
2580 continue;
2581 }
2582 Parser.Lex(); // Eat the comma.
2583 RegLoc = Parser.getTok().getLoc();
2584 int OldReg = Reg;
2585 Reg = tryParseRegister();
2586 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002587 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002588 // Allow Q regs and just interpret them as the two D sub-registers.
2589 bool isQReg = false;
2590 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2591 Reg = getDRegFromQReg(Reg);
2592 isQReg = true;
2593 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002594 // The register must be in the same register class as the first.
2595 if (!RC->contains(Reg))
2596 return Error(RegLoc, "invalid register in register list");
2597 // List must be monotonically increasing.
2598 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2599 return Error(RegLoc, "register list not in ascending order");
2600 // VFP register lists must also be contiguous.
2601 // It's OK to use the enumeration values directly here rather, as the
2602 // VFP register classes have the enum sorted properly.
2603 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2604 Reg != OldReg + 1)
2605 return Error(RegLoc, "non-contiguous register range");
2606 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002607 if (isQReg)
2608 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002609 }
2610
Jim Grosbachd0588e22011-09-14 18:08:35 +00002611 SMLoc E = Parser.getTok().getLoc();
2612 if (Parser.getTok().isNot(AsmToken::RCurly))
2613 return Error(E, "'}' expected");
2614 Parser.Lex(); // Eat '}' token.
2615
Bill Wendling50d0f582010-11-18 23:43:05 +00002616 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2617 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002618}
2619
Jim Grosbach98b05a52011-11-30 01:09:44 +00002620// Helper function to parse the lane index for vector lists.
2621ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002622parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2623 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002624 if (Parser.getTok().is(AsmToken::LBrac)) {
2625 Parser.Lex(); // Eat the '['.
2626 if (Parser.getTok().is(AsmToken::RBrac)) {
2627 // "Dn[]" is the 'all lanes' syntax.
2628 LaneKind = AllLanes;
2629 Parser.Lex(); // Eat the ']'.
2630 return MatchOperand_Success;
2631 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002632 if (Parser.getTok().is(AsmToken::Integer)) {
2633 int64_t Val = Parser.getTok().getIntVal();
2634 // Make this range check context sensitive for .8, .16, .32.
2635 if (Val < 0 && Val > 7)
2636 Error(Parser.getTok().getLoc(), "lane index out of range");
2637 Index = Val;
2638 LaneKind = IndexedLane;
2639 Parser.Lex(); // Eat the token;
2640 if (Parser.getTok().isNot(AsmToken::RBrac))
2641 Error(Parser.getTok().getLoc(), "']' expected");
2642 Parser.Lex(); // Eat the ']'.
2643 return MatchOperand_Success;
2644 }
2645 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002646 return MatchOperand_ParseFail;
2647 }
2648 LaneKind = NoLanes;
2649 return MatchOperand_Success;
2650}
2651
Jim Grosbach862019c2011-10-18 23:02:30 +00002652// parse a vector register list
2653ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2654parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002655 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002656 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002657 SMLoc S = Parser.getTok().getLoc();
2658 // As an extension (to match gas), support a plain D register or Q register
2659 // (without encosing curly braces) as a single or double entry list,
2660 // respectively.
2661 if (Parser.getTok().is(AsmToken::Identifier)) {
2662 int Reg = tryParseRegister();
2663 if (Reg == -1)
2664 return MatchOperand_NoMatch;
2665 SMLoc E = Parser.getTok().getLoc();
2666 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002667 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002668 if (Res != MatchOperand_Success)
2669 return Res;
2670 switch (LaneKind) {
2671 default:
2672 assert(0 && "unexpected lane kind!");
2673 case NoLanes:
2674 E = Parser.getTok().getLoc();
2675 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2676 break;
2677 case AllLanes:
2678 E = Parser.getTok().getLoc();
2679 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2680 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002681 case IndexedLane:
2682 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2683 LaneIndex, S,E));
2684 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002685 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002686 return MatchOperand_Success;
2687 }
2688 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2689 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002690 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002691 if (Res != MatchOperand_Success)
2692 return Res;
2693 switch (LaneKind) {
2694 default:
2695 assert(0 && "unexpected lane kind!");
2696 case NoLanes:
2697 E = Parser.getTok().getLoc();
2698 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2699 break;
2700 case AllLanes:
2701 E = Parser.getTok().getLoc();
2702 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2703 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002704 case IndexedLane:
2705 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2706 LaneIndex, S,E));
2707 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002708 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002709 return MatchOperand_Success;
2710 }
2711 Error(S, "vector register expected");
2712 return MatchOperand_ParseFail;
2713 }
2714
2715 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002716 return MatchOperand_NoMatch;
2717
Jim Grosbach862019c2011-10-18 23:02:30 +00002718 Parser.Lex(); // Eat '{' token.
2719 SMLoc RegLoc = Parser.getTok().getLoc();
2720
2721 int Reg = tryParseRegister();
2722 if (Reg == -1) {
2723 Error(RegLoc, "register expected");
2724 return MatchOperand_ParseFail;
2725 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002726 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002727 unsigned FirstReg = Reg;
2728 // The list is of D registers, but we also allow Q regs and just interpret
2729 // them as the two D sub-registers.
2730 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2731 FirstReg = Reg = getDRegFromQReg(Reg);
2732 ++Reg;
2733 ++Count;
2734 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002735 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002736 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002737
Jim Grosbache43862b2011-11-15 23:19:15 +00002738 while (Parser.getTok().is(AsmToken::Comma) ||
2739 Parser.getTok().is(AsmToken::Minus)) {
2740 if (Parser.getTok().is(AsmToken::Minus)) {
2741 Parser.Lex(); // Eat the minus.
2742 SMLoc EndLoc = Parser.getTok().getLoc();
2743 int EndReg = tryParseRegister();
2744 if (EndReg == -1) {
2745 Error(EndLoc, "register expected");
2746 return MatchOperand_ParseFail;
2747 }
2748 // Allow Q regs and just interpret them as the two D sub-registers.
2749 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2750 EndReg = getDRegFromQReg(EndReg) + 1;
2751 // If the register is the same as the start reg, there's nothing
2752 // more to do.
2753 if (Reg == EndReg)
2754 continue;
2755 // The register must be in the same register class as the first.
2756 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2757 Error(EndLoc, "invalid register in register list");
2758 return MatchOperand_ParseFail;
2759 }
2760 // Ranges must go from low to high.
2761 if (Reg > EndReg) {
2762 Error(EndLoc, "bad range in register list");
2763 return MatchOperand_ParseFail;
2764 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002765 // Parse the lane specifier if present.
2766 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002767 unsigned NextLaneIndex;
2768 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002769 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002770 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002771 Error(EndLoc, "mismatched lane index in register list");
2772 return MatchOperand_ParseFail;
2773 }
2774 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002775
2776 // Add all the registers in the range to the register list.
2777 Count += EndReg - Reg;
2778 Reg = EndReg;
2779 continue;
2780 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002781 Parser.Lex(); // Eat the comma.
2782 RegLoc = Parser.getTok().getLoc();
2783 int OldReg = Reg;
2784 Reg = tryParseRegister();
2785 if (Reg == -1) {
2786 Error(RegLoc, "register expected");
2787 return MatchOperand_ParseFail;
2788 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002789 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002790 // It's OK to use the enumeration values directly here rather, as the
2791 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002792 //
2793 // The list is of D registers, but we also allow Q regs and just interpret
2794 // them as the two D sub-registers.
2795 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2796 Reg = getDRegFromQReg(Reg);
2797 if (Reg != OldReg + 1) {
2798 Error(RegLoc, "non-contiguous register range");
2799 return MatchOperand_ParseFail;
2800 }
2801 ++Reg;
2802 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002803 // Parse the lane specifier if present.
2804 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002805 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002806 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002807 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002808 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002809 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002810 Error(EndLoc, "mismatched lane index in register list");
2811 return MatchOperand_ParseFail;
2812 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002813 continue;
2814 }
2815 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002816 if (Reg != OldReg + 1) {
2817 Error(RegLoc, "non-contiguous register range");
2818 return MatchOperand_ParseFail;
2819 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002820 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002821 // Parse the lane specifier if present.
2822 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002823 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002824 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002825 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002826 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002827 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002828 Error(EndLoc, "mismatched lane index in register list");
2829 return MatchOperand_ParseFail;
2830 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002831 }
2832
2833 SMLoc E = Parser.getTok().getLoc();
2834 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2835 Error(E, "'}' expected");
2836 return MatchOperand_ParseFail;
2837 }
2838 Parser.Lex(); // Eat '}' token.
2839
Jim Grosbach98b05a52011-11-30 01:09:44 +00002840 switch (LaneKind) {
2841 default:
2842 assert(0 && "unexpected lane kind in register list.");
2843 case NoLanes:
2844 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2845 break;
2846 case AllLanes:
2847 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2848 S, E));
2849 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002850 case IndexedLane:
2851 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2852 LaneIndex, S, E));
2853 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002854 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002855 return MatchOperand_Success;
2856}
2857
Jim Grosbach43904292011-07-25 20:14:50 +00002858/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002859ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002860parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002861 SMLoc S = Parser.getTok().getLoc();
2862 const AsmToken &Tok = Parser.getTok();
2863 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2864 StringRef OptStr = Tok.getString();
2865
2866 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2867 .Case("sy", ARM_MB::SY)
2868 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002869 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002870 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002871 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002872 .Case("ishst", ARM_MB::ISHST)
2873 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002874 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002875 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002876 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002877 .Case("osh", ARM_MB::OSH)
2878 .Case("oshst", ARM_MB::OSHST)
2879 .Default(~0U);
2880
2881 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002882 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002883
2884 Parser.Lex(); // Eat identifier token.
2885 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002886 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002887}
2888
Jim Grosbach43904292011-07-25 20:14:50 +00002889/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002890ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002891parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002892 SMLoc S = Parser.getTok().getLoc();
2893 const AsmToken &Tok = Parser.getTok();
2894 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2895 StringRef IFlagsStr = Tok.getString();
2896
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002897 // An iflags string of "none" is interpreted to mean that none of the AIF
2898 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002899 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002900 if (IFlagsStr != "none") {
2901 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2902 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2903 .Case("a", ARM_PROC::A)
2904 .Case("i", ARM_PROC::I)
2905 .Case("f", ARM_PROC::F)
2906 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002907
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002908 // If some specific iflag is already set, it means that some letter is
2909 // present more than once, this is not acceptable.
2910 if (Flag == ~0U || (IFlags & Flag))
2911 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002912
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002913 IFlags |= Flag;
2914 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002915 }
2916
2917 Parser.Lex(); // Eat identifier token.
2918 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2919 return MatchOperand_Success;
2920}
2921
Jim Grosbach43904292011-07-25 20:14:50 +00002922/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002923ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002924parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002925 SMLoc S = Parser.getTok().getLoc();
2926 const AsmToken &Tok = Parser.getTok();
2927 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2928 StringRef Mask = Tok.getString();
2929
James Molloyacad68d2011-09-28 14:21:38 +00002930 if (isMClass()) {
2931 // See ARMv6-M 10.1.1
2932 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2933 .Case("apsr", 0)
2934 .Case("iapsr", 1)
2935 .Case("eapsr", 2)
2936 .Case("xpsr", 3)
2937 .Case("ipsr", 5)
2938 .Case("epsr", 6)
2939 .Case("iepsr", 7)
2940 .Case("msp", 8)
2941 .Case("psp", 9)
2942 .Case("primask", 16)
2943 .Case("basepri", 17)
2944 .Case("basepri_max", 18)
2945 .Case("faultmask", 19)
2946 .Case("control", 20)
2947 .Default(~0U);
2948
2949 if (FlagsVal == ~0U)
2950 return MatchOperand_NoMatch;
2951
2952 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2953 // basepri, basepri_max and faultmask only valid for V7m.
2954 return MatchOperand_NoMatch;
2955
2956 Parser.Lex(); // Eat identifier token.
2957 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2958 return MatchOperand_Success;
2959 }
2960
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002961 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2962 size_t Start = 0, Next = Mask.find('_');
2963 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002964 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002965 if (Next != StringRef::npos)
2966 Flags = Mask.slice(Next+1, Mask.size());
2967
2968 // FlagsVal contains the complete mask:
2969 // 3-0: Mask
2970 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2971 unsigned FlagsVal = 0;
2972
2973 if (SpecReg == "apsr") {
2974 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002975 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002976 .Case("g", 0x4) // same as CPSR_s
2977 .Case("nzcvqg", 0xc) // same as CPSR_fs
2978 .Default(~0U);
2979
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002980 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002981 if (!Flags.empty())
2982 return MatchOperand_NoMatch;
2983 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002984 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002985 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002986 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002987 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2988 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002989 for (int i = 0, e = Flags.size(); i != e; ++i) {
2990 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2991 .Case("c", 1)
2992 .Case("x", 2)
2993 .Case("s", 4)
2994 .Case("f", 8)
2995 .Default(~0U);
2996
2997 // If some specific flag is already set, it means that some letter is
2998 // present more than once, this is not acceptable.
2999 if (FlagsVal == ~0U || (FlagsVal & Flag))
3000 return MatchOperand_NoMatch;
3001 FlagsVal |= Flag;
3002 }
3003 } else // No match for special register.
3004 return MatchOperand_NoMatch;
3005
Owen Anderson7784f1d2011-10-21 18:43:28 +00003006 // Special register without flags is NOT equivalent to "fc" flags.
3007 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3008 // two lines would enable gas compatibility at the expense of breaking
3009 // round-tripping.
3010 //
3011 // if (!FlagsVal)
3012 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003013
3014 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3015 if (SpecReg == "spsr")
3016 FlagsVal |= 16;
3017
3018 Parser.Lex(); // Eat identifier token.
3019 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3020 return MatchOperand_Success;
3021}
3022
Jim Grosbachf6c05252011-07-21 17:23:04 +00003023ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3024parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3025 int Low, int High) {
3026 const AsmToken &Tok = Parser.getTok();
3027 if (Tok.isNot(AsmToken::Identifier)) {
3028 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3029 return MatchOperand_ParseFail;
3030 }
3031 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003032 std::string LowerOp = Op.lower();
3033 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003034 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3035 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3036 return MatchOperand_ParseFail;
3037 }
3038 Parser.Lex(); // Eat shift type token.
3039
3040 // There must be a '#' and a shift amount.
3041 if (Parser.getTok().isNot(AsmToken::Hash)) {
3042 Error(Parser.getTok().getLoc(), "'#' expected");
3043 return MatchOperand_ParseFail;
3044 }
3045 Parser.Lex(); // Eat hash token.
3046
3047 const MCExpr *ShiftAmount;
3048 SMLoc Loc = Parser.getTok().getLoc();
3049 if (getParser().ParseExpression(ShiftAmount)) {
3050 Error(Loc, "illegal expression");
3051 return MatchOperand_ParseFail;
3052 }
3053 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3054 if (!CE) {
3055 Error(Loc, "constant expression expected");
3056 return MatchOperand_ParseFail;
3057 }
3058 int Val = CE->getValue();
3059 if (Val < Low || Val > High) {
3060 Error(Loc, "immediate value out of range");
3061 return MatchOperand_ParseFail;
3062 }
3063
3064 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3065
3066 return MatchOperand_Success;
3067}
3068
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003069ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3070parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3071 const AsmToken &Tok = Parser.getTok();
3072 SMLoc S = Tok.getLoc();
3073 if (Tok.isNot(AsmToken::Identifier)) {
3074 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3075 return MatchOperand_ParseFail;
3076 }
3077 int Val = StringSwitch<int>(Tok.getString())
3078 .Case("be", 1)
3079 .Case("le", 0)
3080 .Default(-1);
3081 Parser.Lex(); // Eat the token.
3082
3083 if (Val == -1) {
3084 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3085 return MatchOperand_ParseFail;
3086 }
3087 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3088 getContext()),
3089 S, Parser.getTok().getLoc()));
3090 return MatchOperand_Success;
3091}
3092
Jim Grosbach580f4a92011-07-25 22:20:28 +00003093/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3094/// instructions. Legal values are:
3095/// lsl #n 'n' in [0,31]
3096/// asr #n 'n' in [1,32]
3097/// n == 32 encoded as n == 0.
3098ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3099parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3100 const AsmToken &Tok = Parser.getTok();
3101 SMLoc S = Tok.getLoc();
3102 if (Tok.isNot(AsmToken::Identifier)) {
3103 Error(S, "shift operator 'asr' or 'lsl' expected");
3104 return MatchOperand_ParseFail;
3105 }
3106 StringRef ShiftName = Tok.getString();
3107 bool isASR;
3108 if (ShiftName == "lsl" || ShiftName == "LSL")
3109 isASR = false;
3110 else if (ShiftName == "asr" || ShiftName == "ASR")
3111 isASR = true;
3112 else {
3113 Error(S, "shift operator 'asr' or 'lsl' expected");
3114 return MatchOperand_ParseFail;
3115 }
3116 Parser.Lex(); // Eat the operator.
3117
3118 // A '#' and a shift amount.
3119 if (Parser.getTok().isNot(AsmToken::Hash)) {
3120 Error(Parser.getTok().getLoc(), "'#' expected");
3121 return MatchOperand_ParseFail;
3122 }
3123 Parser.Lex(); // Eat hash token.
3124
3125 const MCExpr *ShiftAmount;
3126 SMLoc E = Parser.getTok().getLoc();
3127 if (getParser().ParseExpression(ShiftAmount)) {
3128 Error(E, "malformed shift expression");
3129 return MatchOperand_ParseFail;
3130 }
3131 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3132 if (!CE) {
3133 Error(E, "shift amount must be an immediate");
3134 return MatchOperand_ParseFail;
3135 }
3136
3137 int64_t Val = CE->getValue();
3138 if (isASR) {
3139 // Shift amount must be in [1,32]
3140 if (Val < 1 || Val > 32) {
3141 Error(E, "'asr' shift amount must be in range [1,32]");
3142 return MatchOperand_ParseFail;
3143 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003144 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3145 if (isThumb() && Val == 32) {
3146 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3147 return MatchOperand_ParseFail;
3148 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003149 if (Val == 32) Val = 0;
3150 } else {
3151 // Shift amount must be in [1,32]
3152 if (Val < 0 || Val > 31) {
3153 Error(E, "'lsr' shift amount must be in range [0,31]");
3154 return MatchOperand_ParseFail;
3155 }
3156 }
3157
3158 E = Parser.getTok().getLoc();
3159 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3160
3161 return MatchOperand_Success;
3162}
3163
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003164/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3165/// of instructions. Legal values are:
3166/// ror #n 'n' in {0, 8, 16, 24}
3167ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3168parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3169 const AsmToken &Tok = Parser.getTok();
3170 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003171 if (Tok.isNot(AsmToken::Identifier))
3172 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003173 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003174 if (ShiftName != "ror" && ShiftName != "ROR")
3175 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003176 Parser.Lex(); // Eat the operator.
3177
3178 // A '#' and a rotate amount.
3179 if (Parser.getTok().isNot(AsmToken::Hash)) {
3180 Error(Parser.getTok().getLoc(), "'#' expected");
3181 return MatchOperand_ParseFail;
3182 }
3183 Parser.Lex(); // Eat hash token.
3184
3185 const MCExpr *ShiftAmount;
3186 SMLoc E = Parser.getTok().getLoc();
3187 if (getParser().ParseExpression(ShiftAmount)) {
3188 Error(E, "malformed rotate expression");
3189 return MatchOperand_ParseFail;
3190 }
3191 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3192 if (!CE) {
3193 Error(E, "rotate amount must be an immediate");
3194 return MatchOperand_ParseFail;
3195 }
3196
3197 int64_t Val = CE->getValue();
3198 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3199 // normally, zero is represented in asm by omitting the rotate operand
3200 // entirely.
3201 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3202 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3203 return MatchOperand_ParseFail;
3204 }
3205
3206 E = Parser.getTok().getLoc();
3207 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3208
3209 return MatchOperand_Success;
3210}
3211
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003212ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3213parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3214 SMLoc S = Parser.getTok().getLoc();
3215 // The bitfield descriptor is really two operands, the LSB and the width.
3216 if (Parser.getTok().isNot(AsmToken::Hash)) {
3217 Error(Parser.getTok().getLoc(), "'#' expected");
3218 return MatchOperand_ParseFail;
3219 }
3220 Parser.Lex(); // Eat hash token.
3221
3222 const MCExpr *LSBExpr;
3223 SMLoc E = Parser.getTok().getLoc();
3224 if (getParser().ParseExpression(LSBExpr)) {
3225 Error(E, "malformed immediate expression");
3226 return MatchOperand_ParseFail;
3227 }
3228 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3229 if (!CE) {
3230 Error(E, "'lsb' operand must be an immediate");
3231 return MatchOperand_ParseFail;
3232 }
3233
3234 int64_t LSB = CE->getValue();
3235 // The LSB must be in the range [0,31]
3236 if (LSB < 0 || LSB > 31) {
3237 Error(E, "'lsb' operand must be in the range [0,31]");
3238 return MatchOperand_ParseFail;
3239 }
3240 E = Parser.getTok().getLoc();
3241
3242 // Expect another immediate operand.
3243 if (Parser.getTok().isNot(AsmToken::Comma)) {
3244 Error(Parser.getTok().getLoc(), "too few operands");
3245 return MatchOperand_ParseFail;
3246 }
3247 Parser.Lex(); // Eat hash token.
3248 if (Parser.getTok().isNot(AsmToken::Hash)) {
3249 Error(Parser.getTok().getLoc(), "'#' expected");
3250 return MatchOperand_ParseFail;
3251 }
3252 Parser.Lex(); // Eat hash token.
3253
3254 const MCExpr *WidthExpr;
3255 if (getParser().ParseExpression(WidthExpr)) {
3256 Error(E, "malformed immediate expression");
3257 return MatchOperand_ParseFail;
3258 }
3259 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3260 if (!CE) {
3261 Error(E, "'width' operand must be an immediate");
3262 return MatchOperand_ParseFail;
3263 }
3264
3265 int64_t Width = CE->getValue();
3266 // The LSB must be in the range [1,32-lsb]
3267 if (Width < 1 || Width > 32 - LSB) {
3268 Error(E, "'width' operand must be in the range [1,32-lsb]");
3269 return MatchOperand_ParseFail;
3270 }
3271 E = Parser.getTok().getLoc();
3272
3273 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3274
3275 return MatchOperand_Success;
3276}
3277
Jim Grosbach7ce05792011-08-03 23:50:40 +00003278ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3279parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3280 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003281 // postidx_reg := '+' register {, shift}
3282 // | '-' register {, shift}
3283 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003284
3285 // This method must return MatchOperand_NoMatch without consuming any tokens
3286 // in the case where there is no match, as other alternatives take other
3287 // parse methods.
3288 AsmToken Tok = Parser.getTok();
3289 SMLoc S = Tok.getLoc();
3290 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003291 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003292 int Reg = -1;
3293 if (Tok.is(AsmToken::Plus)) {
3294 Parser.Lex(); // Eat the '+' token.
3295 haveEaten = true;
3296 } else if (Tok.is(AsmToken::Minus)) {
3297 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003298 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003299 haveEaten = true;
3300 }
3301 if (Parser.getTok().is(AsmToken::Identifier))
3302 Reg = tryParseRegister();
3303 if (Reg == -1) {
3304 if (!haveEaten)
3305 return MatchOperand_NoMatch;
3306 Error(Parser.getTok().getLoc(), "register expected");
3307 return MatchOperand_ParseFail;
3308 }
3309 SMLoc E = Parser.getTok().getLoc();
3310
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003311 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3312 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003313 if (Parser.getTok().is(AsmToken::Comma)) {
3314 Parser.Lex(); // Eat the ','.
3315 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3316 return MatchOperand_ParseFail;
3317 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003318
3319 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3320 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003321
3322 return MatchOperand_Success;
3323}
3324
Jim Grosbach251bf252011-08-10 21:56:18 +00003325ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3326parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3327 // Check for a post-index addressing register operand. Specifically:
3328 // am3offset := '+' register
3329 // | '-' register
3330 // | register
3331 // | # imm
3332 // | # + imm
3333 // | # - imm
3334
3335 // This method must return MatchOperand_NoMatch without consuming any tokens
3336 // in the case where there is no match, as other alternatives take other
3337 // parse methods.
3338 AsmToken Tok = Parser.getTok();
3339 SMLoc S = Tok.getLoc();
3340
3341 // Do immediates first, as we always parse those if we have a '#'.
3342 if (Parser.getTok().is(AsmToken::Hash)) {
3343 Parser.Lex(); // Eat the '#'.
3344 // Explicitly look for a '-', as we need to encode negative zero
3345 // differently.
3346 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3347 const MCExpr *Offset;
3348 if (getParser().ParseExpression(Offset))
3349 return MatchOperand_ParseFail;
3350 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3351 if (!CE) {
3352 Error(S, "constant expression expected");
3353 return MatchOperand_ParseFail;
3354 }
3355 SMLoc E = Tok.getLoc();
3356 // Negative zero is encoded as the flag value INT32_MIN.
3357 int32_t Val = CE->getValue();
3358 if (isNegative && Val == 0)
3359 Val = INT32_MIN;
3360
3361 Operands.push_back(
3362 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3363
3364 return MatchOperand_Success;
3365 }
3366
3367
3368 bool haveEaten = false;
3369 bool isAdd = true;
3370 int Reg = -1;
3371 if (Tok.is(AsmToken::Plus)) {
3372 Parser.Lex(); // Eat the '+' token.
3373 haveEaten = true;
3374 } else if (Tok.is(AsmToken::Minus)) {
3375 Parser.Lex(); // Eat the '-' token.
3376 isAdd = false;
3377 haveEaten = true;
3378 }
3379 if (Parser.getTok().is(AsmToken::Identifier))
3380 Reg = tryParseRegister();
3381 if (Reg == -1) {
3382 if (!haveEaten)
3383 return MatchOperand_NoMatch;
3384 Error(Parser.getTok().getLoc(), "register expected");
3385 return MatchOperand_ParseFail;
3386 }
3387 SMLoc E = Parser.getTok().getLoc();
3388
3389 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3390 0, S, E));
3391
3392 return MatchOperand_Success;
3393}
3394
Jim Grosbacha77295d2011-09-08 22:07:06 +00003395/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3396/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3397/// when they refer multiple MIOperands inside a single one.
3398bool ARMAsmParser::
3399cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3400 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3401 // Rt, Rt2
3402 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3403 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3404 // Create a writeback register dummy placeholder.
3405 Inst.addOperand(MCOperand::CreateReg(0));
3406 // addr
3407 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3408 // pred
3409 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3410 return true;
3411}
3412
3413/// cvtT2StrdPre - Convert parsed operands to MCInst.
3414/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3415/// when they refer multiple MIOperands inside a single one.
3416bool ARMAsmParser::
3417cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3418 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3419 // Create a writeback register dummy placeholder.
3420 Inst.addOperand(MCOperand::CreateReg(0));
3421 // Rt, Rt2
3422 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3423 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3424 // addr
3425 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3426 // pred
3427 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3428 return true;
3429}
3430
Jim Grosbacheeec0252011-09-08 00:39:19 +00003431/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3432/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3433/// when they refer multiple MIOperands inside a single one.
3434bool ARMAsmParser::
3435cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3436 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3437 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3438
3439 // Create a writeback register dummy placeholder.
3440 Inst.addOperand(MCOperand::CreateImm(0));
3441
3442 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3443 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3444 return true;
3445}
3446
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003447/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3448/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3449/// when they refer multiple MIOperands inside a single one.
3450bool ARMAsmParser::
3451cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3452 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3453 // Create a writeback register dummy placeholder.
3454 Inst.addOperand(MCOperand::CreateImm(0));
3455 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3456 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3457 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3458 return true;
3459}
3460
Jim Grosbach1355cf12011-07-26 17:10:22 +00003461/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003462/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3463/// when they refer multiple MIOperands inside a single one.
3464bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003465cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003466 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3467 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3468
3469 // Create a writeback register dummy placeholder.
3470 Inst.addOperand(MCOperand::CreateImm(0));
3471
Jim Grosbach7ce05792011-08-03 23:50:40 +00003472 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003473 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3474 return true;
3475}
3476
Owen Anderson9ab0f252011-08-26 20:43:14 +00003477/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3478/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3479/// when they refer multiple MIOperands inside a single one.
3480bool ARMAsmParser::
3481cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3482 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3483 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3484
3485 // Create a writeback register dummy placeholder.
3486 Inst.addOperand(MCOperand::CreateImm(0));
3487
3488 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3489 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3490 return true;
3491}
3492
3493
Jim Grosbach548340c2011-08-11 19:22:40 +00003494/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3495/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3496/// when they refer multiple MIOperands inside a single one.
3497bool ARMAsmParser::
3498cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3499 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3500 // Create a writeback register dummy placeholder.
3501 Inst.addOperand(MCOperand::CreateImm(0));
3502 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3503 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3504 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3505 return true;
3506}
3507
Jim Grosbach1355cf12011-07-26 17:10:22 +00003508/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003509/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3510/// when they refer multiple MIOperands inside a single one.
3511bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003512cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003513 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3514 // Create a writeback register dummy placeholder.
3515 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003516 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3517 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3518 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003519 return true;
3520}
3521
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003522/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3523/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3524/// when they refer multiple MIOperands inside a single one.
3525bool ARMAsmParser::
3526cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3527 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3528 // Create a writeback register dummy placeholder.
3529 Inst.addOperand(MCOperand::CreateImm(0));
3530 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3531 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3532 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3533 return true;
3534}
3535
Jim Grosbach7ce05792011-08-03 23:50:40 +00003536/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3537/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3538/// when they refer multiple MIOperands inside a single one.
3539bool ARMAsmParser::
3540cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3541 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3542 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003543 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003544 // Create a writeback register dummy placeholder.
3545 Inst.addOperand(MCOperand::CreateImm(0));
3546 // addr
3547 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3548 // offset
3549 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3550 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003551 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3552 return true;
3553}
3554
Jim Grosbach7ce05792011-08-03 23:50:40 +00003555/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003556/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3557/// when they refer multiple MIOperands inside a single one.
3558bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003559cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3560 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3561 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003562 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003563 // Create a writeback register dummy placeholder.
3564 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003565 // addr
3566 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3567 // offset
3568 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3569 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003570 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3571 return true;
3572}
3573
Jim Grosbach7ce05792011-08-03 23:50:40 +00003574/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003575/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3576/// when they refer multiple MIOperands inside a single one.
3577bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003578cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3579 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003580 // Create a writeback register dummy placeholder.
3581 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003582 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003583 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003584 // addr
3585 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3586 // offset
3587 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3588 // pred
3589 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3590 return true;
3591}
3592
3593/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3594/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3595/// when they refer multiple MIOperands inside a single one.
3596bool ARMAsmParser::
3597cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3598 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3599 // Create a writeback register dummy placeholder.
3600 Inst.addOperand(MCOperand::CreateImm(0));
3601 // Rt
3602 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3603 // addr
3604 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3605 // offset
3606 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3607 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003608 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3609 return true;
3610}
3611
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003612/// cvtLdrdPre - Convert parsed operands to MCInst.
3613/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3614/// when they refer multiple MIOperands inside a single one.
3615bool ARMAsmParser::
3616cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3617 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3618 // Rt, Rt2
3619 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3620 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3621 // Create a writeback register dummy placeholder.
3622 Inst.addOperand(MCOperand::CreateImm(0));
3623 // addr
3624 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3625 // pred
3626 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3627 return true;
3628}
3629
Jim Grosbach14605d12011-08-11 20:28:23 +00003630/// cvtStrdPre - Convert parsed operands to MCInst.
3631/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3632/// when they refer multiple MIOperands inside a single one.
3633bool ARMAsmParser::
3634cvtStrdPre(MCInst &Inst, unsigned Opcode,
3635 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3636 // Create a writeback register dummy placeholder.
3637 Inst.addOperand(MCOperand::CreateImm(0));
3638 // Rt, Rt2
3639 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3640 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3641 // addr
3642 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3643 // pred
3644 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3645 return true;
3646}
3647
Jim Grosbach623a4542011-08-10 22:42:16 +00003648/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3649/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3650/// when they refer multiple MIOperands inside a single one.
3651bool ARMAsmParser::
3652cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3653 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3654 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3655 // Create a writeback register dummy placeholder.
3656 Inst.addOperand(MCOperand::CreateImm(0));
3657 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3658 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3659 return true;
3660}
3661
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003662/// cvtThumbMultiple- Convert parsed operands to MCInst.
3663/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3664/// when they refer multiple MIOperands inside a single one.
3665bool ARMAsmParser::
3666cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3667 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3668 // The second source operand must be the same register as the destination
3669 // operand.
3670 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003671 (((ARMOperand*)Operands[3])->getReg() !=
3672 ((ARMOperand*)Operands[5])->getReg()) &&
3673 (((ARMOperand*)Operands[3])->getReg() !=
3674 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003675 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003676 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003677 return false;
3678 }
3679 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3680 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003681 // If we have a three-operand form, make sure to set Rn to be the operand
3682 // that isn't the same as Rd.
3683 unsigned RegOp = 4;
3684 if (Operands.size() == 6 &&
3685 ((ARMOperand*)Operands[4])->getReg() ==
3686 ((ARMOperand*)Operands[3])->getReg())
3687 RegOp = 5;
3688 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3689 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003690 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3691
3692 return true;
3693}
Jim Grosbach623a4542011-08-10 22:42:16 +00003694
Jim Grosbach12431322011-10-24 22:16:58 +00003695bool ARMAsmParser::
3696cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3697 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3698 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003699 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003700 // Create a writeback register dummy placeholder.
3701 Inst.addOperand(MCOperand::CreateImm(0));
3702 // Vn
3703 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3704 // pred
3705 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3706 return true;
3707}
3708
3709bool ARMAsmParser::
3710cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3711 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3712 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003713 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003714 // Create a writeback register dummy placeholder.
3715 Inst.addOperand(MCOperand::CreateImm(0));
3716 // Vn
3717 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3718 // Vm
3719 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3720 // pred
3721 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3722 return true;
3723}
3724
Jim Grosbach4334e032011-10-31 21:50:31 +00003725bool ARMAsmParser::
3726cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3727 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3728 // Create a writeback register dummy placeholder.
3729 Inst.addOperand(MCOperand::CreateImm(0));
3730 // Vn
3731 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3732 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003733 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003734 // pred
3735 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3736 return true;
3737}
3738
3739bool ARMAsmParser::
3740cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3741 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3742 // Create a writeback register dummy placeholder.
3743 Inst.addOperand(MCOperand::CreateImm(0));
3744 // Vn
3745 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3746 // Vm
3747 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3748 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003749 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003750 // pred
3751 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3752 return true;
3753}
3754
Bill Wendlinge7176102010-11-06 22:36:58 +00003755/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003756/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003757bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003758parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003759 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003760 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003761 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003762 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003763 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003764
Sean Callanan18b83232010-01-19 21:44:56 +00003765 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003766 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003767 if (BaseRegNum == -1)
3768 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003769
Daniel Dunbar05710932011-01-18 05:34:17 +00003770 // The next token must either be a comma or a closing bracket.
3771 const AsmToken &Tok = Parser.getTok();
3772 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003773 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003774
Jim Grosbach7ce05792011-08-03 23:50:40 +00003775 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003776 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003777 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003778
Jim Grosbach7ce05792011-08-03 23:50:40 +00003779 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003780 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003781
Jim Grosbachfb12f352011-09-19 18:42:21 +00003782 // If there's a pre-indexing writeback marker, '!', just add it as a token
3783 // operand. It's rather odd, but syntactically valid.
3784 if (Parser.getTok().is(AsmToken::Exclaim)) {
3785 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3786 Parser.Lex(); // Eat the '!'.
3787 }
3788
Jim Grosbach7ce05792011-08-03 23:50:40 +00003789 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003790 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003791
Jim Grosbach7ce05792011-08-03 23:50:40 +00003792 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3793 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003794
Jim Grosbach57dcb852011-10-11 17:29:55 +00003795 // If we have a ':', it's an alignment specifier.
3796 if (Parser.getTok().is(AsmToken::Colon)) {
3797 Parser.Lex(); // Eat the ':'.
3798 E = Parser.getTok().getLoc();
3799
3800 const MCExpr *Expr;
3801 if (getParser().ParseExpression(Expr))
3802 return true;
3803
3804 // The expression has to be a constant. Memory references with relocations
3805 // don't come through here, as they use the <label> forms of the relevant
3806 // instructions.
3807 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3808 if (!CE)
3809 return Error (E, "constant expression expected");
3810
3811 unsigned Align = 0;
3812 switch (CE->getValue()) {
3813 default:
3814 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3815 case 64: Align = 8; break;
3816 case 128: Align = 16; break;
3817 case 256: Align = 32; break;
3818 }
3819
3820 // Now we should have the closing ']'
3821 E = Parser.getTok().getLoc();
3822 if (Parser.getTok().isNot(AsmToken::RBrac))
3823 return Error(E, "']' expected");
3824 Parser.Lex(); // Eat right bracket token.
3825
3826 // Don't worry about range checking the value here. That's handled by
3827 // the is*() predicates.
3828 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3829 ARM_AM::no_shift, 0, Align,
3830 false, S, E));
3831
3832 // If there's a pre-indexing writeback marker, '!', just add it as a token
3833 // operand.
3834 if (Parser.getTok().is(AsmToken::Exclaim)) {
3835 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3836 Parser.Lex(); // Eat the '!'.
3837 }
3838
3839 return false;
3840 }
3841
3842 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003843 // offset. Be friendly and also accept a plain integer (without a leading
3844 // hash) for gas compatibility.
3845 if (Parser.getTok().is(AsmToken::Hash) ||
3846 Parser.getTok().is(AsmToken::Integer)) {
3847 if (Parser.getTok().is(AsmToken::Hash))
3848 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003849 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003850
Owen Anderson0da10cf2011-08-29 19:36:44 +00003851 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003852 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003853 if (getParser().ParseExpression(Offset))
3854 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003855
3856 // The expression has to be a constant. Memory references with relocations
3857 // don't come through here, as they use the <label> forms of the relevant
3858 // instructions.
3859 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3860 if (!CE)
3861 return Error (E, "constant expression expected");
3862
Owen Anderson0da10cf2011-08-29 19:36:44 +00003863 // If the constant was #-0, represent it as INT32_MIN.
3864 int32_t Val = CE->getValue();
3865 if (isNegative && Val == 0)
3866 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3867
Jim Grosbach7ce05792011-08-03 23:50:40 +00003868 // Now we should have the closing ']'
3869 E = Parser.getTok().getLoc();
3870 if (Parser.getTok().isNot(AsmToken::RBrac))
3871 return Error(E, "']' expected");
3872 Parser.Lex(); // Eat right bracket token.
3873
3874 // Don't worry about range checking the value here. That's handled by
3875 // the is*() predicates.
3876 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003877 ARM_AM::no_shift, 0, 0,
3878 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003879
3880 // If there's a pre-indexing writeback marker, '!', just add it as a token
3881 // operand.
3882 if (Parser.getTok().is(AsmToken::Exclaim)) {
3883 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3884 Parser.Lex(); // Eat the '!'.
3885 }
3886
3887 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003888 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003889
3890 // The register offset is optionally preceded by a '+' or '-'
3891 bool isNegative = false;
3892 if (Parser.getTok().is(AsmToken::Minus)) {
3893 isNegative = true;
3894 Parser.Lex(); // Eat the '-'.
3895 } else if (Parser.getTok().is(AsmToken::Plus)) {
3896 // Nothing to do.
3897 Parser.Lex(); // Eat the '+'.
3898 }
3899
3900 E = Parser.getTok().getLoc();
3901 int OffsetRegNum = tryParseRegister();
3902 if (OffsetRegNum == -1)
3903 return Error(E, "register expected");
3904
3905 // If there's a shift operator, handle it.
3906 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003907 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003908 if (Parser.getTok().is(AsmToken::Comma)) {
3909 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003910 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003911 return true;
3912 }
3913
3914 // Now we should have the closing ']'
3915 E = Parser.getTok().getLoc();
3916 if (Parser.getTok().isNot(AsmToken::RBrac))
3917 return Error(E, "']' expected");
3918 Parser.Lex(); // Eat right bracket token.
3919
3920 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003921 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003922 S, E));
3923
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003924 // If there's a pre-indexing writeback marker, '!', just add it as a token
3925 // operand.
3926 if (Parser.getTok().is(AsmToken::Exclaim)) {
3927 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3928 Parser.Lex(); // Eat the '!'.
3929 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003930
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003931 return false;
3932}
3933
Jim Grosbach7ce05792011-08-03 23:50:40 +00003934/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003935/// ( lsl | lsr | asr | ror ) , # shift_amount
3936/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003937/// return true if it parses a shift otherwise it returns false.
3938bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3939 unsigned &Amount) {
3940 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003941 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003942 if (Tok.isNot(AsmToken::Identifier))
3943 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003944 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00003945 if (ShiftName == "lsl" || ShiftName == "LSL" ||
3946 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00003947 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003948 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003949 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003950 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003951 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003952 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003953 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003954 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003955 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003956 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003957 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003958 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003959
Jim Grosbach7ce05792011-08-03 23:50:40 +00003960 // rrx stands alone.
3961 Amount = 0;
3962 if (St != ARM_AM::rrx) {
3963 Loc = Parser.getTok().getLoc();
3964 // A '#' and a shift amount.
3965 const AsmToken &HashTok = Parser.getTok();
3966 if (HashTok.isNot(AsmToken::Hash))
3967 return Error(HashTok.getLoc(), "'#' expected");
3968 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003969
Jim Grosbach7ce05792011-08-03 23:50:40 +00003970 const MCExpr *Expr;
3971 if (getParser().ParseExpression(Expr))
3972 return true;
3973 // Range check the immediate.
3974 // lsl, ror: 0 <= imm <= 31
3975 // lsr, asr: 0 <= imm <= 32
3976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3977 if (!CE)
3978 return Error(Loc, "shift amount must be an immediate");
3979 int64_t Imm = CE->getValue();
3980 if (Imm < 0 ||
3981 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3982 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3983 return Error(Loc, "immediate shift value out of range");
3984 Amount = Imm;
3985 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003986
3987 return false;
3988}
3989
Jim Grosbach9d390362011-10-03 23:38:36 +00003990/// parseFPImm - A floating point immediate expression operand.
3991ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3992parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3993 SMLoc S = Parser.getTok().getLoc();
3994
3995 if (Parser.getTok().isNot(AsmToken::Hash))
3996 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003997
3998 // Disambiguate the VMOV forms that can accept an FP immediate.
3999 // vmov.f32 <sreg>, #imm
4000 // vmov.f64 <dreg>, #imm
4001 // vmov.f32 <dreg>, #imm @ vector f32x2
4002 // vmov.f32 <qreg>, #imm @ vector f32x4
4003 //
4004 // There are also the NEON VMOV instructions which expect an
4005 // integer constant. Make sure we don't try to parse an FPImm
4006 // for these:
4007 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4008 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4009 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4010 TyOp->getToken() != ".f64"))
4011 return MatchOperand_NoMatch;
4012
Jim Grosbach9d390362011-10-03 23:38:36 +00004013 Parser.Lex(); // Eat the '#'.
4014
4015 // Handle negation, as that still comes through as a separate token.
4016 bool isNegative = false;
4017 if (Parser.getTok().is(AsmToken::Minus)) {
4018 isNegative = true;
4019 Parser.Lex();
4020 }
4021 const AsmToken &Tok = Parser.getTok();
4022 if (Tok.is(AsmToken::Real)) {
4023 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4024 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4025 // If we had a '-' in front, toggle the sign bit.
4026 IntVal ^= (uint64_t)isNegative << 63;
4027 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4028 Parser.Lex(); // Eat the token.
4029 if (Val == -1) {
4030 TokError("floating point value out of range");
4031 return MatchOperand_ParseFail;
4032 }
4033 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4034 return MatchOperand_Success;
4035 }
4036 if (Tok.is(AsmToken::Integer)) {
4037 int64_t Val = Tok.getIntVal();
4038 Parser.Lex(); // Eat the token.
4039 if (Val > 255 || Val < 0) {
4040 TokError("encoded floating point value out of range");
4041 return MatchOperand_ParseFail;
4042 }
4043 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4044 return MatchOperand_Success;
4045 }
4046
4047 TokError("invalid floating point immediate");
4048 return MatchOperand_ParseFail;
4049}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004050/// Parse a arm instruction operand. For now this parses the operand regardless
4051/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004052bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004053 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004054 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004055
4056 // Check if the current operand has a custom associated parser, if so, try to
4057 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004058 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4059 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004060 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004061 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4062 // there was a match, but an error occurred, in which case, just return that
4063 // the operand parsing failed.
4064 if (ResTy == MatchOperand_ParseFail)
4065 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004066
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004067 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004068 default:
4069 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004070 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004071 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004072 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004073 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004074 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004075 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004076 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004077 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004078 else if (Res == -1) // irrecoverable error
4079 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004080 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4081 S = Parser.getTok().getLoc();
4082 Parser.Lex();
4083 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4084 return false;
4085 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004086
4087 // Fall though for the Identifier case that is not a register or a
4088 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004089 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004090 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004091 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004092 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004093 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004094 // This was not a register so parse other operands that start with an
4095 // identifier (like labels) as expressions and create them as immediates.
4096 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004097 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004098 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004099 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004100 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004101 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4102 return false;
4103 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004104 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004105 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004106 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004107 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00004108 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004109 // #42 -> immediate.
4110 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004111 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004112 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004113 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004114 const MCExpr *ImmVal;
4115 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004116 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004117 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004118 if (CE) {
4119 int32_t Val = CE->getValue();
4120 if (isNegative && Val == 0)
4121 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004122 }
Sean Callanan76264762010-04-02 22:27:05 +00004123 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004124 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4125 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004126 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004127 case AsmToken::Colon: {
4128 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004129 // FIXME: Check it's an expression prefix,
4130 // e.g. (FOO - :lower16:BAR) isn't legal.
4131 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004132 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004133 return true;
4134
Evan Cheng75972122011-01-13 07:58:56 +00004135 const MCExpr *SubExprVal;
4136 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004137 return true;
4138
Evan Cheng75972122011-01-13 07:58:56 +00004139 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4140 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004141 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004142 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004143 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004144 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004145 }
4146}
4147
Jim Grosbach1355cf12011-07-26 17:10:22 +00004148// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004149// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004150bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004151 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004152
4153 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004154 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004155 Parser.Lex(); // Eat ':'
4156
4157 if (getLexer().isNot(AsmToken::Identifier)) {
4158 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4159 return true;
4160 }
4161
4162 StringRef IDVal = Parser.getTok().getIdentifier();
4163 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004164 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004165 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004166 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004167 } else {
4168 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4169 return true;
4170 }
4171 Parser.Lex();
4172
4173 if (getLexer().isNot(AsmToken::Colon)) {
4174 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4175 return true;
4176 }
4177 Parser.Lex(); // Eat the last ':'
4178 return false;
4179}
4180
Daniel Dunbar352e1482011-01-11 15:59:50 +00004181/// \brief Given a mnemonic, split out possible predication code and carry
4182/// setting letters to form a canonical mnemonic and flags.
4183//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004184// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004185// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004186StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004187 unsigned &PredicationCode,
4188 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004189 unsigned &ProcessorIMod,
4190 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004191 PredicationCode = ARMCC::AL;
4192 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004193 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004194
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004195 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004196 //
4197 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004198 if ((Mnemonic == "movs" && isThumb()) ||
4199 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4200 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4201 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4202 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4203 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4204 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4205 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004206 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004207
Jim Grosbach3f00e312011-07-11 17:09:57 +00004208 // First, split out any predication code. Ignore mnemonics we know aren't
4209 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004210 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004211 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004212 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004213 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004214 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4215 .Case("eq", ARMCC::EQ)
4216 .Case("ne", ARMCC::NE)
4217 .Case("hs", ARMCC::HS)
4218 .Case("cs", ARMCC::HS)
4219 .Case("lo", ARMCC::LO)
4220 .Case("cc", ARMCC::LO)
4221 .Case("mi", ARMCC::MI)
4222 .Case("pl", ARMCC::PL)
4223 .Case("vs", ARMCC::VS)
4224 .Case("vc", ARMCC::VC)
4225 .Case("hi", ARMCC::HI)
4226 .Case("ls", ARMCC::LS)
4227 .Case("ge", ARMCC::GE)
4228 .Case("lt", ARMCC::LT)
4229 .Case("gt", ARMCC::GT)
4230 .Case("le", ARMCC::LE)
4231 .Case("al", ARMCC::AL)
4232 .Default(~0U);
4233 if (CC != ~0U) {
4234 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4235 PredicationCode = CC;
4236 }
Bill Wendling52925b62010-10-29 23:50:21 +00004237 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004238
Daniel Dunbar352e1482011-01-11 15:59:50 +00004239 // Next, determine if we have a carry setting bit. We explicitly ignore all
4240 // the instructions we know end in 's'.
4241 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004242 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004243 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4244 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4245 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004246 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach8254f022011-12-08 00:52:55 +00004247 Mnemonic == "fmrs" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004248 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004249 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4250 CarrySetting = true;
4251 }
4252
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004253 // The "cps" instruction can have a interrupt mode operand which is glued into
4254 // the mnemonic. Check if this is the case, split it and parse the imod op
4255 if (Mnemonic.startswith("cps")) {
4256 // Split out any imod code.
4257 unsigned IMod =
4258 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4259 .Case("ie", ARM_PROC::IE)
4260 .Case("id", ARM_PROC::ID)
4261 .Default(~0U);
4262 if (IMod != ~0U) {
4263 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4264 ProcessorIMod = IMod;
4265 }
4266 }
4267
Jim Grosbach89df9962011-08-26 21:43:41 +00004268 // The "it" instruction has the condition mask on the end of the mnemonic.
4269 if (Mnemonic.startswith("it")) {
4270 ITMask = Mnemonic.slice(2, Mnemonic.size());
4271 Mnemonic = Mnemonic.slice(0, 2);
4272 }
4273
Daniel Dunbar352e1482011-01-11 15:59:50 +00004274 return Mnemonic;
4275}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004276
4277/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4278/// inclusion of carry set or predication code operands.
4279//
4280// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004281void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004282getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004283 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004284 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4285 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004286 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004287 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004288 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004289 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004290 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004291 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004292 Mnemonic == "mla" || Mnemonic == "smlal" ||
4293 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004294 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004295 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004296 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004297
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004298 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4299 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4300 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4301 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004302 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4303 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004304 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004305 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4306 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4307 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004308 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4309 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004310 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004311 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004312 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004313 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004314
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004315 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004316 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004317 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004318 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004319 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004320}
4321
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004322bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4323 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004324 // FIXME: This is all horribly hacky. We really need a better way to deal
4325 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004326
4327 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4328 // another does not. Specifically, the MOVW instruction does not. So we
4329 // special case it here and remove the defaulted (non-setting) cc_out
4330 // operand if that's the instruction we're trying to match.
4331 //
4332 // We do this as post-processing of the explicit operands rather than just
4333 // conditionally adding the cc_out in the first place because we need
4334 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004335 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004336 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4337 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4338 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4339 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004340
4341 // Register-register 'add' for thumb does not have a cc_out operand
4342 // when there are only two register operands.
4343 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4344 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4345 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4346 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4347 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004348 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004349 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4350 // have to check the immediate range here since Thumb2 has a variant
4351 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004352 if (((isThumb() && Mnemonic == "add") ||
4353 (isThumbTwo() && Mnemonic == "sub")) &&
4354 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004355 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4356 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4357 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004358 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4359 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4360 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004361 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004362 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4363 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004364 // selecting via the generic "add" mnemonic, so to know that we
4365 // should remove the cc_out operand, we have to explicitly check that
4366 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004367 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4368 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004369 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4370 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4371 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4372 // Nest conditions rather than one big 'if' statement for readability.
4373 //
4374 // If either register is a high reg, it's either one of the SP
4375 // variants (handled above) or a 32-bit encoding, so we just
4376 // check against T3.
4377 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4378 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4379 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4380 return false;
4381 // If both registers are low, we're in an IT block, and the immediate is
4382 // in range, we should use encoding T1 instead, which has a cc_out.
4383 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004384 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004385 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4386 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4387 return false;
4388
4389 // Otherwise, we use encoding T4, which does not have a cc_out
4390 // operand.
4391 return true;
4392 }
4393
Jim Grosbach64944f42011-09-14 21:00:40 +00004394 // The thumb2 multiply instruction doesn't have a CCOut register, so
4395 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4396 // use the 16-bit encoding or not.
4397 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4398 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4399 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4400 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4401 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4402 // If the registers aren't low regs, the destination reg isn't the
4403 // same as one of the source regs, or the cc_out operand is zero
4404 // outside of an IT block, we have to use the 32-bit encoding, so
4405 // remove the cc_out operand.
4406 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4407 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004408 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004409 !inITBlock() ||
4410 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4411 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4412 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4413 static_cast<ARMOperand*>(Operands[4])->getReg())))
4414 return true;
4415
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004416 // Also check the 'mul' syntax variant that doesn't specify an explicit
4417 // destination register.
4418 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4419 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4420 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4421 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4422 // If the registers aren't low regs or the cc_out operand is zero
4423 // outside of an IT block, we have to use the 32-bit encoding, so
4424 // remove the cc_out operand.
4425 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4426 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4427 !inITBlock()))
4428 return true;
4429
Jim Grosbach64944f42011-09-14 21:00:40 +00004430
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004431
Jim Grosbachf69c8042011-08-24 21:42:27 +00004432 // Register-register 'add/sub' for thumb does not have a cc_out operand
4433 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4434 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4435 // right, this will result in better diagnostics (which operand is off)
4436 // anyway.
4437 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4438 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004439 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4440 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4441 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4442 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004443
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004444 return false;
4445}
4446
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004447static bool isDataTypeToken(StringRef Tok) {
4448 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4449 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4450 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4451 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4452 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4453 Tok == ".f" || Tok == ".d";
4454}
4455
4456// FIXME: This bit should probably be handled via an explicit match class
4457// in the .td files that matches the suffix instead of having it be
4458// a literal string token the way it is now.
4459static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4460 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4461}
4462
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004463/// Parse an arm instruction mnemonic followed by its operands.
4464bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4465 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4466 // Create the leading tokens for the mnemonic, split by '.' characters.
4467 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004468 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004469
Daniel Dunbar352e1482011-01-11 15:59:50 +00004470 // Split out the predication code and carry setting flag from the mnemonic.
4471 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004472 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004473 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004474 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004475 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004476 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004477
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004478 // In Thumb1, only the branch (B) instruction can be predicated.
4479 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4480 Parser.EatToEndOfStatement();
4481 return Error(NameLoc, "conditional execution not supported in Thumb1");
4482 }
4483
Jim Grosbachffa32252011-07-19 19:13:28 +00004484 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4485
Jim Grosbach89df9962011-08-26 21:43:41 +00004486 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4487 // is the mask as it will be for the IT encoding if the conditional
4488 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4489 // where the conditional bit0 is zero, the instruction post-processing
4490 // will adjust the mask accordingly.
4491 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004492 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4493 if (ITMask.size() > 3) {
4494 Parser.EatToEndOfStatement();
4495 return Error(Loc, "too many conditions on IT instruction");
4496 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004497 unsigned Mask = 8;
4498 for (unsigned i = ITMask.size(); i != 0; --i) {
4499 char pos = ITMask[i - 1];
4500 if (pos != 't' && pos != 'e') {
4501 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004502 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004503 }
4504 Mask >>= 1;
4505 if (ITMask[i - 1] == 't')
4506 Mask |= 8;
4507 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004508 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004509 }
4510
Jim Grosbachffa32252011-07-19 19:13:28 +00004511 // FIXME: This is all a pretty gross hack. We should automatically handle
4512 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004513
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004514 // Next, add the CCOut and ConditionCode operands, if needed.
4515 //
4516 // For mnemonics which can ever incorporate a carry setting bit or predication
4517 // code, our matching model involves us always generating CCOut and
4518 // ConditionCode operands to match the mnemonic "as written" and then we let
4519 // the matcher deal with finding the right instruction or generating an
4520 // appropriate error.
4521 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004522 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004523
Jim Grosbach33c16a22011-07-14 22:04:21 +00004524 // If we had a carry-set on an instruction that can't do that, issue an
4525 // error.
4526 if (!CanAcceptCarrySet && CarrySetting) {
4527 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004528 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004529 "' can not set flags, but 's' suffix specified");
4530 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004531 // If we had a predication code on an instruction that can't do that, issue an
4532 // error.
4533 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4534 Parser.EatToEndOfStatement();
4535 return Error(NameLoc, "instruction '" + Mnemonic +
4536 "' is not predicable, but condition code specified");
4537 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004538
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004539 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004540 if (CanAcceptCarrySet) {
4541 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004542 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004543 Loc));
4544 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004545
4546 // Add the predication code operand, if necessary.
4547 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004548 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4549 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004550 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004551 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004552 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004553
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004554 // Add the processor imod operand, if necessary.
4555 if (ProcessorIMod) {
4556 Operands.push_back(ARMOperand::CreateImm(
4557 MCConstantExpr::Create(ProcessorIMod, getContext()),
4558 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004559 }
4560
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004561 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004562 while (Next != StringRef::npos) {
4563 Start = Next;
4564 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004565 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004566
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004567 // Some NEON instructions have an optional datatype suffix that is
4568 // completely ignored. Check for that.
4569 if (isDataTypeToken(ExtraToken) &&
4570 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4571 continue;
4572
Jim Grosbach81d2e392011-09-07 16:06:04 +00004573 if (ExtraToken != ".n") {
4574 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4575 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4576 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004577 }
4578
4579 // Read the remaining operands.
4580 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004581 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004582 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004583 Parser.EatToEndOfStatement();
4584 return true;
4585 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004586
4587 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004588 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004589
4590 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004591 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004592 Parser.EatToEndOfStatement();
4593 return true;
4594 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004595 }
4596 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004597
Chris Lattnercbf8a982010-09-11 16:18:25 +00004598 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004599 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004600 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004601 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004602 }
Bill Wendling146018f2010-11-06 21:42:12 +00004603
Chris Lattner34e53142010-09-08 05:10:46 +00004604 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004605
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004606 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4607 // do and don't have a cc_out optional-def operand. With some spot-checks
4608 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004609 // parse and adjust accordingly before actually matching. We shouldn't ever
4610 // try to remove a cc_out operand that was explicitly set on the the
4611 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4612 // table driven matcher doesn't fit well with the ARM instruction set.
4613 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004614 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4615 Operands.erase(Operands.begin() + 1);
4616 delete Op;
4617 }
4618
Jim Grosbachcf121c32011-07-28 21:57:55 +00004619 // ARM mode 'blx' need special handling, as the register operand version
4620 // is predicable, but the label operand version is not. So, we can't rely
4621 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004622 // a k_CondCode operand in the list. If we're trying to match the label
4623 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004624 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4625 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4626 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4627 Operands.erase(Operands.begin() + 1);
4628 delete Op;
4629 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004630
4631 // The vector-compare-to-zero instructions have a literal token "#0" at
4632 // the end that comes to here as an immediate operand. Convert it to a
4633 // token to play nicely with the matcher.
4634 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4635 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4636 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4637 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4639 if (CE && CE->getValue() == 0) {
4640 Operands.erase(Operands.begin() + 5);
4641 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4642 delete Op;
4643 }
4644 }
Jim Grosbach68259142011-10-03 22:30:24 +00004645 // VCMP{E} does the same thing, but with a different operand count.
4646 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4647 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4648 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4649 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4650 if (CE && CE->getValue() == 0) {
4651 Operands.erase(Operands.begin() + 4);
4652 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4653 delete Op;
4654 }
4655 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004656 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4657 // end. Convert it to a token here.
4658 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4659 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4660 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4661 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4662 if (CE && CE->getValue() == 0) {
4663 Operands.erase(Operands.begin() + 5);
4664 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4665 delete Op;
4666 }
4667 }
4668
Chris Lattner98986712010-01-14 22:21:20 +00004669 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004670}
4671
Jim Grosbach189610f2011-07-26 18:25:39 +00004672// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004673
4674// return 'true' if register list contains non-low GPR registers,
4675// 'false' otherwise. If Reg is in the register list or is HiReg, set
4676// 'containsReg' to true.
4677static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4678 unsigned HiReg, bool &containsReg) {
4679 containsReg = false;
4680 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4681 unsigned OpReg = Inst.getOperand(i).getReg();
4682 if (OpReg == Reg)
4683 containsReg = true;
4684 // Anything other than a low register isn't legal here.
4685 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4686 return true;
4687 }
4688 return false;
4689}
4690
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004691// Check if the specified regisgter is in the register list of the inst,
4692// starting at the indicated operand number.
4693static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4694 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4695 unsigned OpReg = Inst.getOperand(i).getReg();
4696 if (OpReg == Reg)
4697 return true;
4698 }
4699 return false;
4700}
4701
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004702// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4703// the ARMInsts array) instead. Getting that here requires awkward
4704// API changes, though. Better way?
4705namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004706extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004707}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004708static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004709 return ARMInsts[Opcode];
4710}
4711
Jim Grosbach189610f2011-07-26 18:25:39 +00004712// FIXME: We would really like to be able to tablegen'erate this.
4713bool ARMAsmParser::
4714validateInstruction(MCInst &Inst,
4715 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004716 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004717 SMLoc Loc = Operands[0]->getStartLoc();
4718 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004719 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4720 // being allowed in IT blocks, but not being predicable. It just always
4721 // executes.
4722 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004723 unsigned bit = 1;
4724 if (ITState.FirstCond)
4725 ITState.FirstCond = false;
4726 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004727 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004728 // The instruction must be predicable.
4729 if (!MCID.isPredicable())
4730 return Error(Loc, "instructions in IT block must be predicable");
4731 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4732 unsigned ITCond = bit ? ITState.Cond :
4733 ARMCC::getOppositeCondition(ITState.Cond);
4734 if (Cond != ITCond) {
4735 // Find the condition code Operand to get its SMLoc information.
4736 SMLoc CondLoc;
4737 for (unsigned i = 1; i < Operands.size(); ++i)
4738 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4739 CondLoc = Operands[i]->getStartLoc();
4740 return Error(CondLoc, "incorrect condition in IT block; got '" +
4741 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4742 "', but expected '" +
4743 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4744 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004745 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004746 } else if (isThumbTwo() && MCID.isPredicable() &&
4747 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004748 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4749 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004750 return Error(Loc, "predicated instructions must be in IT block");
4751
Jim Grosbach189610f2011-07-26 18:25:39 +00004752 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004753 case ARM::LDRD:
4754 case ARM::LDRD_PRE:
4755 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004756 case ARM::LDREXD: {
4757 // Rt2 must be Rt + 1.
4758 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4759 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4760 if (Rt2 != Rt + 1)
4761 return Error(Operands[3]->getStartLoc(),
4762 "destination operands must be sequential");
4763 return false;
4764 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004765 case ARM::STRD: {
4766 // Rt2 must be Rt + 1.
4767 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4768 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4769 if (Rt2 != Rt + 1)
4770 return Error(Operands[3]->getStartLoc(),
4771 "source operands must be sequential");
4772 return false;
4773 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004774 case ARM::STRD_PRE:
4775 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004776 case ARM::STREXD: {
4777 // Rt2 must be Rt + 1.
4778 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4779 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4780 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004781 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004782 "source operands must be sequential");
4783 return false;
4784 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004785 case ARM::SBFX:
4786 case ARM::UBFX: {
4787 // width must be in range [1, 32-lsb]
4788 unsigned lsb = Inst.getOperand(2).getImm();
4789 unsigned widthm1 = Inst.getOperand(3).getImm();
4790 if (widthm1 >= 32 - lsb)
4791 return Error(Operands[5]->getStartLoc(),
4792 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004793 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004794 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004795 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004796 // If we're parsing Thumb2, the .w variant is available and handles
4797 // most cases that are normally illegal for a Thumb1 LDM
4798 // instruction. We'll make the transformation in processInstruction()
4799 // if necessary.
4800 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004801 // Thumb LDM instructions are writeback iff the base register is not
4802 // in the register list.
4803 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004804 bool hasWritebackToken =
4805 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4806 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004807 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004808 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004809 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4810 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004811 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004812 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004813 return Error(Operands[2]->getStartLoc(),
4814 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004815 // If we should not have writeback, there must not be a '!'. This is
4816 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004817 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004818 return Error(Operands[3]->getStartLoc(),
4819 "writeback operator '!' not allowed when base register "
4820 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004821
4822 break;
4823 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004824 case ARM::t2LDMIA_UPD: {
4825 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4826 return Error(Operands[4]->getStartLoc(),
4827 "writeback operator '!' not allowed when base register "
4828 "in register list");
4829 break;
4830 }
Jim Grosbach54026372011-11-10 23:17:11 +00004831 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4832 // so only issue a diagnostic for thumb1. The instructions will be
4833 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004834 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004835 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004836 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4837 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004838 return Error(Operands[2]->getStartLoc(),
4839 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004840 break;
4841 }
4842 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004843 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004844 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4845 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004846 return Error(Operands[2]->getStartLoc(),
4847 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004848 break;
4849 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004850 case ARM::tSTMIA_UPD: {
4851 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004852 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004853 return Error(Operands[4]->getStartLoc(),
4854 "registers must be in range r0-r7");
4855 break;
4856 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004857 }
4858
4859 return false;
4860}
4861
Jim Grosbach84defb52011-12-02 22:34:51 +00004862static unsigned getRealVSTLNOpcode(unsigned Opc) {
4863 switch(Opc) {
4864 default: assert(0 && "unexpected opcode!");
4865 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4866 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4867 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4868 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4869 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4870 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4871 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4872 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4873 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4874 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4875 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4876 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4877 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4878 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4879 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4880 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4881 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4882 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4883 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4884 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4885 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4886 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4887 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4888 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4889 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4890 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4891 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4892 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4893 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4894 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4895 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4896 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4897 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4898 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4899 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4900 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4901 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4902 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4903 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4904 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4905 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4906 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4907 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4908 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4909 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
4910 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
4911 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
4912 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
4913 }
4914}
4915
4916static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004917 switch(Opc) {
4918 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00004919 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
4920 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
4921 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
4922 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
4923 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
4924 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
4925 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
4926 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
4927 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
4928 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
4929 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
4930 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
4931 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
4932 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
4933 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
4934 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
4935 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
4936 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
4937 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
4938 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
4939 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
4940 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
4941 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
4942 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
4943 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
4944 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
4945 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
4946 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
4947 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
4948 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
4949 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
4950 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004951 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
4952 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
4953 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
4954 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
4955 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00004956 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
4957 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
4958 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
4959 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
4960 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004961 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
4962 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
4963 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
4964 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
4965 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
4966 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00004967 }
4968}
4969
Jim Grosbach83ec8772011-11-10 23:42:14 +00004970bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004971processInstruction(MCInst &Inst,
4972 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4973 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00004974 // Handle NEON VST1 complex aliases.
4975 case ARM::VST1LNdWB_register_Asm_8:
4976 case ARM::VST1LNdWB_register_Asm_P8:
4977 case ARM::VST1LNdWB_register_Asm_I8:
4978 case ARM::VST1LNdWB_register_Asm_S8:
4979 case ARM::VST1LNdWB_register_Asm_U8:
4980 case ARM::VST1LNdWB_register_Asm_16:
4981 case ARM::VST1LNdWB_register_Asm_P16:
4982 case ARM::VST1LNdWB_register_Asm_I16:
4983 case ARM::VST1LNdWB_register_Asm_S16:
4984 case ARM::VST1LNdWB_register_Asm_U16:
4985 case ARM::VST1LNdWB_register_Asm_32:
4986 case ARM::VST1LNdWB_register_Asm_F:
4987 case ARM::VST1LNdWB_register_Asm_F32:
4988 case ARM::VST1LNdWB_register_Asm_I32:
4989 case ARM::VST1LNdWB_register_Asm_S32:
4990 case ARM::VST1LNdWB_register_Asm_U32: {
4991 MCInst TmpInst;
4992 // Shuffle the operands around so the lane index operand is in the
4993 // right place.
4994 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
4995 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
4996 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4997 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4998 TmpInst.addOperand(Inst.getOperand(4)); // Rm
4999 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5000 TmpInst.addOperand(Inst.getOperand(1)); // lane
5001 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5002 TmpInst.addOperand(Inst.getOperand(6));
5003 Inst = TmpInst;
5004 return true;
5005 }
5006 case ARM::VST1LNdWB_fixed_Asm_8:
5007 case ARM::VST1LNdWB_fixed_Asm_P8:
5008 case ARM::VST1LNdWB_fixed_Asm_I8:
5009 case ARM::VST1LNdWB_fixed_Asm_S8:
5010 case ARM::VST1LNdWB_fixed_Asm_U8:
5011 case ARM::VST1LNdWB_fixed_Asm_16:
5012 case ARM::VST1LNdWB_fixed_Asm_P16:
5013 case ARM::VST1LNdWB_fixed_Asm_I16:
5014 case ARM::VST1LNdWB_fixed_Asm_S16:
5015 case ARM::VST1LNdWB_fixed_Asm_U16:
5016 case ARM::VST1LNdWB_fixed_Asm_32:
5017 case ARM::VST1LNdWB_fixed_Asm_F:
5018 case ARM::VST1LNdWB_fixed_Asm_F32:
5019 case ARM::VST1LNdWB_fixed_Asm_I32:
5020 case ARM::VST1LNdWB_fixed_Asm_S32:
5021 case ARM::VST1LNdWB_fixed_Asm_U32: {
5022 MCInst TmpInst;
5023 // Shuffle the operands around so the lane index operand is in the
5024 // right place.
5025 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5026 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5027 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5028 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5029 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5030 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5031 TmpInst.addOperand(Inst.getOperand(1)); // lane
5032 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5033 TmpInst.addOperand(Inst.getOperand(5));
5034 Inst = TmpInst;
5035 return true;
5036 }
5037 case ARM::VST1LNdAsm_8:
5038 case ARM::VST1LNdAsm_P8:
5039 case ARM::VST1LNdAsm_I8:
5040 case ARM::VST1LNdAsm_S8:
5041 case ARM::VST1LNdAsm_U8:
5042 case ARM::VST1LNdAsm_16:
5043 case ARM::VST1LNdAsm_P16:
5044 case ARM::VST1LNdAsm_I16:
5045 case ARM::VST1LNdAsm_S16:
5046 case ARM::VST1LNdAsm_U16:
5047 case ARM::VST1LNdAsm_32:
5048 case ARM::VST1LNdAsm_F:
5049 case ARM::VST1LNdAsm_F32:
5050 case ARM::VST1LNdAsm_I32:
5051 case ARM::VST1LNdAsm_S32:
5052 case ARM::VST1LNdAsm_U32: {
5053 MCInst TmpInst;
5054 // Shuffle the operands around so the lane index operand is in the
5055 // right place.
5056 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5057 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5058 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5059 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5060 TmpInst.addOperand(Inst.getOperand(1)); // lane
5061 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5062 TmpInst.addOperand(Inst.getOperand(5));
5063 Inst = TmpInst;
5064 return true;
5065 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005066 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005067 case ARM::VLD1LNdWB_register_Asm_8:
5068 case ARM::VLD1LNdWB_register_Asm_P8:
5069 case ARM::VLD1LNdWB_register_Asm_I8:
5070 case ARM::VLD1LNdWB_register_Asm_S8:
5071 case ARM::VLD1LNdWB_register_Asm_U8:
5072 case ARM::VLD1LNdWB_register_Asm_16:
5073 case ARM::VLD1LNdWB_register_Asm_P16:
5074 case ARM::VLD1LNdWB_register_Asm_I16:
5075 case ARM::VLD1LNdWB_register_Asm_S16:
5076 case ARM::VLD1LNdWB_register_Asm_U16:
5077 case ARM::VLD1LNdWB_register_Asm_32:
5078 case ARM::VLD1LNdWB_register_Asm_F:
5079 case ARM::VLD1LNdWB_register_Asm_F32:
5080 case ARM::VLD1LNdWB_register_Asm_I32:
5081 case ARM::VLD1LNdWB_register_Asm_S32:
5082 case ARM::VLD1LNdWB_register_Asm_U32: {
5083 MCInst TmpInst;
5084 // Shuffle the operands around so the lane index operand is in the
5085 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005086 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005087 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5088 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5089 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5090 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5091 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5092 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5093 TmpInst.addOperand(Inst.getOperand(1)); // lane
5094 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5095 TmpInst.addOperand(Inst.getOperand(6));
5096 Inst = TmpInst;
5097 return true;
5098 }
5099 case ARM::VLD1LNdWB_fixed_Asm_8:
5100 case ARM::VLD1LNdWB_fixed_Asm_P8:
5101 case ARM::VLD1LNdWB_fixed_Asm_I8:
5102 case ARM::VLD1LNdWB_fixed_Asm_S8:
5103 case ARM::VLD1LNdWB_fixed_Asm_U8:
5104 case ARM::VLD1LNdWB_fixed_Asm_16:
5105 case ARM::VLD1LNdWB_fixed_Asm_P16:
5106 case ARM::VLD1LNdWB_fixed_Asm_I16:
5107 case ARM::VLD1LNdWB_fixed_Asm_S16:
5108 case ARM::VLD1LNdWB_fixed_Asm_U16:
5109 case ARM::VLD1LNdWB_fixed_Asm_32:
5110 case ARM::VLD1LNdWB_fixed_Asm_F:
5111 case ARM::VLD1LNdWB_fixed_Asm_F32:
5112 case ARM::VLD1LNdWB_fixed_Asm_I32:
5113 case ARM::VLD1LNdWB_fixed_Asm_S32:
5114 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5115 MCInst TmpInst;
5116 // Shuffle the operands around so the lane index operand is in the
5117 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005118 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005119 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5120 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5121 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5122 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5123 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5124 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5125 TmpInst.addOperand(Inst.getOperand(1)); // lane
5126 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5127 TmpInst.addOperand(Inst.getOperand(5));
5128 Inst = TmpInst;
5129 return true;
5130 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005131 case ARM::VLD1LNdAsm_8:
5132 case ARM::VLD1LNdAsm_P8:
5133 case ARM::VLD1LNdAsm_I8:
5134 case ARM::VLD1LNdAsm_S8:
5135 case ARM::VLD1LNdAsm_U8:
5136 case ARM::VLD1LNdAsm_16:
5137 case ARM::VLD1LNdAsm_P16:
5138 case ARM::VLD1LNdAsm_I16:
5139 case ARM::VLD1LNdAsm_S16:
5140 case ARM::VLD1LNdAsm_U16:
5141 case ARM::VLD1LNdAsm_32:
5142 case ARM::VLD1LNdAsm_F:
5143 case ARM::VLD1LNdAsm_F32:
5144 case ARM::VLD1LNdAsm_I32:
5145 case ARM::VLD1LNdAsm_S32:
5146 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005147 MCInst TmpInst;
5148 // Shuffle the operands around so the lane index operand is in the
5149 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005150 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005151 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5152 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5153 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5154 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5155 TmpInst.addOperand(Inst.getOperand(1)); // lane
5156 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5157 TmpInst.addOperand(Inst.getOperand(5));
5158 Inst = TmpInst;
5159 return true;
5160 }
Jim Grosbach71810ab2011-11-10 16:44:55 +00005161 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005162 case ARM::ASRr:
5163 case ARM::LSRr:
5164 case ARM::LSLr:
5165 case ARM::RORr: {
5166 ARM_AM::ShiftOpc ShiftTy;
5167 switch(Inst.getOpcode()) {
5168 default: llvm_unreachable("unexpected opcode!");
5169 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5170 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5171 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5172 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5173 }
5174 // A shift by zero is a plain MOVr, not a MOVsi.
5175 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5176 MCInst TmpInst;
5177 TmpInst.setOpcode(ARM::MOVsr);
5178 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5179 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5180 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5181 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5182 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5183 TmpInst.addOperand(Inst.getOperand(4));
5184 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5185 Inst = TmpInst;
5186 return true;
5187 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005188 case ARM::ASRi:
5189 case ARM::LSRi:
5190 case ARM::LSLi:
5191 case ARM::RORi: {
5192 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005193 switch(Inst.getOpcode()) {
5194 default: llvm_unreachable("unexpected opcode!");
5195 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5196 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5197 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5198 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5199 }
5200 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005201 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005202 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5203 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005204 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005205 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005206 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5207 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005208 if (Opc == ARM::MOVsi)
5209 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005210 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5211 TmpInst.addOperand(Inst.getOperand(4));
5212 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5213 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005214 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005215 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005216 case ARM::RRXi: {
5217 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5218 MCInst TmpInst;
5219 TmpInst.setOpcode(ARM::MOVsi);
5220 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5221 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5222 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5223 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5224 TmpInst.addOperand(Inst.getOperand(3));
5225 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5226 Inst = TmpInst;
5227 return true;
5228 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005229 case ARM::t2LDMIA_UPD: {
5230 // If this is a load of a single register, then we should use
5231 // a post-indexed LDR instruction instead, per the ARM ARM.
5232 if (Inst.getNumOperands() != 5)
5233 return false;
5234 MCInst TmpInst;
5235 TmpInst.setOpcode(ARM::t2LDR_POST);
5236 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5237 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5238 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5239 TmpInst.addOperand(MCOperand::CreateImm(4));
5240 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5241 TmpInst.addOperand(Inst.getOperand(3));
5242 Inst = TmpInst;
5243 return true;
5244 }
5245 case ARM::t2STMDB_UPD: {
5246 // If this is a store of a single register, then we should use
5247 // a pre-indexed STR instruction instead, per the ARM ARM.
5248 if (Inst.getNumOperands() != 5)
5249 return false;
5250 MCInst TmpInst;
5251 TmpInst.setOpcode(ARM::t2STR_PRE);
5252 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5253 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5254 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5255 TmpInst.addOperand(MCOperand::CreateImm(-4));
5256 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5257 TmpInst.addOperand(Inst.getOperand(3));
5258 Inst = TmpInst;
5259 return true;
5260 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005261 case ARM::LDMIA_UPD:
5262 // If this is a load of a single register via a 'pop', then we should use
5263 // a post-indexed LDR instruction instead, per the ARM ARM.
5264 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5265 Inst.getNumOperands() == 5) {
5266 MCInst TmpInst;
5267 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5268 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5269 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5270 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5271 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5272 TmpInst.addOperand(MCOperand::CreateImm(4));
5273 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5274 TmpInst.addOperand(Inst.getOperand(3));
5275 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005276 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005277 }
5278 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005279 case ARM::STMDB_UPD:
5280 // If this is a store of a single register via a 'push', then we should use
5281 // a pre-indexed STR instruction instead, per the ARM ARM.
5282 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5283 Inst.getNumOperands() == 5) {
5284 MCInst TmpInst;
5285 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5286 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5287 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5288 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5289 TmpInst.addOperand(MCOperand::CreateImm(-4));
5290 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5291 TmpInst.addOperand(Inst.getOperand(3));
5292 Inst = TmpInst;
5293 }
5294 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005295 case ARM::t2ADDri12:
5296 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5297 // mnemonic was used (not "addw"), encoding T3 is preferred.
5298 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5299 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5300 break;
5301 Inst.setOpcode(ARM::t2ADDri);
5302 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5303 break;
5304 case ARM::t2SUBri12:
5305 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5306 // mnemonic was used (not "subw"), encoding T3 is preferred.
5307 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5308 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5309 break;
5310 Inst.setOpcode(ARM::t2SUBri);
5311 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5312 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005313 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005314 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5315 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5316 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5317 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005318 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005319 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005320 return true;
5321 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005322 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005323 case ARM::tSUBi8:
5324 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5325 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5326 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5327 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005328 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005329 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005330 return true;
5331 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005332 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005333 case ARM::t2ADDrr: {
5334 // If the destination and first source operand are the same, and
5335 // there's no setting of the flags, use encoding T2 instead of T3.
5336 // Note that this is only for ADD, not SUB. This mirrors the system
5337 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5338 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5339 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005340 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5341 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005342 break;
5343 MCInst TmpInst;
5344 TmpInst.setOpcode(ARM::tADDhirr);
5345 TmpInst.addOperand(Inst.getOperand(0));
5346 TmpInst.addOperand(Inst.getOperand(0));
5347 TmpInst.addOperand(Inst.getOperand(2));
5348 TmpInst.addOperand(Inst.getOperand(3));
5349 TmpInst.addOperand(Inst.getOperand(4));
5350 Inst = TmpInst;
5351 return true;
5352 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005353 case ARM::tB:
5354 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005355 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005356 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005357 return true;
5358 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005359 break;
5360 case ARM::t2B:
5361 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005362 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005363 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005364 return true;
5365 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005366 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005367 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005368 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005369 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005370 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005371 return true;
5372 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005373 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005374 case ARM::tBcc:
5375 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005376 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005377 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005378 return true;
5379 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005380 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005381 case ARM::tLDMIA: {
5382 // If the register list contains any high registers, or if the writeback
5383 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5384 // instead if we're in Thumb2. Otherwise, this should have generated
5385 // an error in validateInstruction().
5386 unsigned Rn = Inst.getOperand(0).getReg();
5387 bool hasWritebackToken =
5388 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5389 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5390 bool listContainsBase;
5391 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5392 (!listContainsBase && !hasWritebackToken) ||
5393 (listContainsBase && hasWritebackToken)) {
5394 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5395 assert (isThumbTwo());
5396 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5397 // If we're switching to the updating version, we need to insert
5398 // the writeback tied operand.
5399 if (hasWritebackToken)
5400 Inst.insert(Inst.begin(),
5401 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005402 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005403 }
5404 break;
5405 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005406 case ARM::tSTMIA_UPD: {
5407 // If the register list contains any high registers, we need to use
5408 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5409 // should have generated an error in validateInstruction().
5410 unsigned Rn = Inst.getOperand(0).getReg();
5411 bool listContainsBase;
5412 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5413 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5414 assert (isThumbTwo());
5415 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005416 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005417 }
5418 break;
5419 }
Jim Grosbach54026372011-11-10 23:17:11 +00005420 case ARM::tPOP: {
5421 bool listContainsBase;
5422 // If the register list contains any high registers, we need to use
5423 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5424 // should have generated an error in validateInstruction().
5425 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005426 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005427 assert (isThumbTwo());
5428 Inst.setOpcode(ARM::t2LDMIA_UPD);
5429 // Add the base register and writeback operands.
5430 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5431 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005432 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005433 }
5434 case ARM::tPUSH: {
5435 bool listContainsBase;
5436 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005437 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005438 assert (isThumbTwo());
5439 Inst.setOpcode(ARM::t2STMDB_UPD);
5440 // Add the base register and writeback operands.
5441 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5442 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005443 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005444 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005445 case ARM::t2MOVi: {
5446 // If we can use the 16-bit encoding and the user didn't explicitly
5447 // request the 32-bit variant, transform it here.
5448 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5449 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005450 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5451 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5452 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005453 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5454 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5455 // The operands aren't in the same order for tMOVi8...
5456 MCInst TmpInst;
5457 TmpInst.setOpcode(ARM::tMOVi8);
5458 TmpInst.addOperand(Inst.getOperand(0));
5459 TmpInst.addOperand(Inst.getOperand(4));
5460 TmpInst.addOperand(Inst.getOperand(1));
5461 TmpInst.addOperand(Inst.getOperand(2));
5462 TmpInst.addOperand(Inst.getOperand(3));
5463 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005464 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005465 }
5466 break;
5467 }
5468 case ARM::t2MOVr: {
5469 // If we can use the 16-bit encoding and the user didn't explicitly
5470 // request the 32-bit variant, transform it here.
5471 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5472 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5473 Inst.getOperand(2).getImm() == ARMCC::AL &&
5474 Inst.getOperand(4).getReg() == ARM::CPSR &&
5475 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5476 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5477 // The operands aren't the same for tMOV[S]r... (no cc_out)
5478 MCInst TmpInst;
5479 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5480 TmpInst.addOperand(Inst.getOperand(0));
5481 TmpInst.addOperand(Inst.getOperand(1));
5482 TmpInst.addOperand(Inst.getOperand(2));
5483 TmpInst.addOperand(Inst.getOperand(3));
5484 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005485 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005486 }
5487 break;
5488 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005489 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005490 case ARM::t2SXTB:
5491 case ARM::t2UXTH:
5492 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005493 // If we can use the 16-bit encoding and the user didn't explicitly
5494 // request the 32-bit variant, transform it here.
5495 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5496 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5497 Inst.getOperand(2).getImm() == 0 &&
5498 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5499 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005500 unsigned NewOpc;
5501 switch (Inst.getOpcode()) {
5502 default: llvm_unreachable("Illegal opcode!");
5503 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5504 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5505 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5506 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5507 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005508 // The operands aren't the same for thumb1 (no rotate operand).
5509 MCInst TmpInst;
5510 TmpInst.setOpcode(NewOpc);
5511 TmpInst.addOperand(Inst.getOperand(0));
5512 TmpInst.addOperand(Inst.getOperand(1));
5513 TmpInst.addOperand(Inst.getOperand(3));
5514 TmpInst.addOperand(Inst.getOperand(4));
5515 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005516 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005517 }
5518 break;
5519 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005520 case ARM::t2IT: {
5521 // The mask bits for all but the first condition are represented as
5522 // the low bit of the condition code value implies 't'. We currently
5523 // always have 1 implies 't', so XOR toggle the bits if the low bit
5524 // of the condition code is zero. The encoding also expects the low
5525 // bit of the condition to be encoded as bit 4 of the mask operand,
5526 // so mask that in if needed
5527 MCOperand &MO = Inst.getOperand(1);
5528 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005529 unsigned OrigMask = Mask;
5530 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005531 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005532 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5533 for (unsigned i = 3; i != TZ; --i)
5534 Mask ^= 1 << i;
5535 } else
5536 Mask |= 0x10;
5537 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005538
5539 // Set up the IT block state according to the IT instruction we just
5540 // matched.
5541 assert(!inITBlock() && "nested IT blocks?!");
5542 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5543 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5544 ITState.CurPosition = 0;
5545 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005546 break;
5547 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005548 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005549 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005550}
5551
Jim Grosbach47a0d522011-08-16 20:45:50 +00005552unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5553 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5554 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005555 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005556 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005557 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5558 assert(MCID.hasOptionalDef() &&
5559 "optionally flag setting instruction missing optional def operand");
5560 assert(MCID.NumOperands == Inst.getNumOperands() &&
5561 "operand count mismatch!");
5562 // Find the optional-def operand (cc_out).
5563 unsigned OpNo;
5564 for (OpNo = 0;
5565 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5566 ++OpNo)
5567 ;
5568 // If we're parsing Thumb1, reject it completely.
5569 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5570 return Match_MnemonicFail;
5571 // If we're parsing Thumb2, which form is legal depends on whether we're
5572 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005573 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5574 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005575 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005576 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5577 inITBlock())
5578 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005579 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005580 // Some high-register supporting Thumb1 encodings only allow both registers
5581 // to be from r0-r7 when in Thumb2.
5582 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5583 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5584 isARMLowRegister(Inst.getOperand(2).getReg()))
5585 return Match_RequiresThumb2;
5586 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005587 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005588 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5589 isARMLowRegister(Inst.getOperand(1).getReg()))
5590 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005591 return Match_Success;
5592}
5593
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005594bool ARMAsmParser::
5595MatchAndEmitInstruction(SMLoc IDLoc,
5596 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5597 MCStreamer &Out) {
5598 MCInst Inst;
5599 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005600 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005601 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005602 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005603 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005604 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005605 // Context sensitive operand constraints aren't handled by the matcher,
5606 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005607 if (validateInstruction(Inst, Operands)) {
5608 // Still progress the IT block, otherwise one wrong condition causes
5609 // nasty cascading errors.
5610 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005611 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005612 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005613
Jim Grosbachf8fce712011-08-11 17:35:48 +00005614 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005615 // encoding is selected. Loop on it while changes happen so the
5616 // individual transformations can chain off each other. E.g.,
5617 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5618 while (processInstruction(Inst, Operands))
5619 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005620
Jim Grosbacha1109882011-09-02 23:22:08 +00005621 // Only move forward at the very end so that everything in validate
5622 // and process gets a consistent answer about whether we're in an IT
5623 // block.
5624 forwardITPosition();
5625
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005626 Out.EmitInstruction(Inst);
5627 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005628 case Match_MissingFeature:
5629 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5630 return true;
5631 case Match_InvalidOperand: {
5632 SMLoc ErrorLoc = IDLoc;
5633 if (ErrorInfo != ~0U) {
5634 if (ErrorInfo >= Operands.size())
5635 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005636
Chris Lattnere73d4f82010-10-28 21:41:58 +00005637 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5638 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5639 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005640
Chris Lattnere73d4f82010-10-28 21:41:58 +00005641 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005642 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005643 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005644 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005645 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005646 // The converter function will have already emited a diagnostic.
5647 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005648 case Match_RequiresNotITBlock:
5649 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005650 case Match_RequiresITBlock:
5651 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005652 case Match_RequiresV6:
5653 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5654 case Match_RequiresThumb2:
5655 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005656 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005657
Eric Christopherc223e2b2010-10-29 09:26:59 +00005658 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005659 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005660}
5661
Jim Grosbach1355cf12011-07-26 17:10:22 +00005662/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005663bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5664 StringRef IDVal = DirectiveID.getIdentifier();
5665 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005666 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005667 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005668 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00005669 else if (IDVal == ".arm")
5670 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005671 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005672 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005673 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005674 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005675 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005676 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005677 return true;
5678}
5679
Jim Grosbach1355cf12011-07-26 17:10:22 +00005680/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005681/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005682bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005683 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5684 for (;;) {
5685 const MCExpr *Value;
5686 if (getParser().ParseExpression(Value))
5687 return true;
5688
Chris Lattneraaec2052010-01-19 19:46:13 +00005689 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005690
5691 if (getLexer().is(AsmToken::EndOfStatement))
5692 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005693
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005694 // FIXME: Improve diagnostic.
5695 if (getLexer().isNot(AsmToken::Comma))
5696 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005697 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005698 }
5699 }
5700
Sean Callananb9a25b72010-01-19 20:27:46 +00005701 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005702 return false;
5703}
5704
Jim Grosbach1355cf12011-07-26 17:10:22 +00005705/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005706/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005707bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005708 if (getLexer().isNot(AsmToken::EndOfStatement))
5709 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005710 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005711
Jim Grosbach9a70df92011-12-07 18:04:19 +00005712 if (!isThumb())
5713 SwitchMode();
5714 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5715 return false;
5716}
5717
5718/// parseDirectiveARM
5719/// ::= .arm
5720bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5721 if (getLexer().isNot(AsmToken::EndOfStatement))
5722 return Error(L, "unexpected token in directive");
5723 Parser.Lex();
5724
5725 if (isThumb())
5726 SwitchMode();
5727 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00005728 return false;
5729}
5730
Jim Grosbach1355cf12011-07-26 17:10:22 +00005731/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005732/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005733bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005734 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5735 bool isMachO = MAI.hasSubsectionsViaSymbols();
5736 StringRef Name;
5737
5738 // Darwin asm has function name after .thumb_func direction
5739 // ELF doesn't
5740 if (isMachO) {
5741 const AsmToken &Tok = Parser.getTok();
5742 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5743 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005744 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005745 Parser.Lex(); // Consume the identifier token.
5746 }
5747
Jim Grosbachd475f862011-11-10 20:48:53 +00005748 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005749 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005750 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005751
Rafael Espindola64695402011-05-16 16:17:21 +00005752 // FIXME: assuming function name will be the line following .thumb_func
5753 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005754 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005755 }
5756
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005757 // Mark symbol as a thumb symbol.
5758 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5759 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005760 return false;
5761}
5762
Jim Grosbach1355cf12011-07-26 17:10:22 +00005763/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005764/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005765bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005766 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005767 if (Tok.isNot(AsmToken::Identifier))
5768 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005769 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005770 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005771 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005772 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005773 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005774 else
5775 return Error(L, "unrecognized syntax mode in .syntax directive");
5776
5777 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005778 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005779 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005780
5781 // TODO tell the MC streamer the mode
5782 // getParser().getStreamer().Emit???();
5783 return false;
5784}
5785
Jim Grosbach1355cf12011-07-26 17:10:22 +00005786/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005787/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005788bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005789 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005790 if (Tok.isNot(AsmToken::Integer))
5791 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005792 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005793 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005794 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005795 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005796 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005797 else
5798 return Error(L, "invalid operand to .code directive");
5799
5800 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005801 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005802 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005803
Evan Cheng32869202011-07-08 22:36:29 +00005804 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005805 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005806 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005807 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005808 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005809 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005810 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005811 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005812 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005813
Kevin Enderby515d5092009-10-15 20:48:48 +00005814 return false;
5815}
5816
Sean Callanan90b70972010-04-07 20:29:34 +00005817extern "C" void LLVMInitializeARMAsmLexer();
5818
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005819/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005820extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005821 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5822 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005823 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005824}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005825
Chris Lattner0692ee62010-09-06 19:11:01 +00005826#define GET_REGISTER_MATCHER
5827#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005828#include "ARMGenAsmMatcher.inc"