blob: a1b13483311b75c22a91c520695f296a85ea97c0 [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 Grosbach3b8991c2011-12-07 01:07:24 +0000614 bool isImm8() 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 == 8;
621 }
622 bool isImm16() 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 == 16;
629 }
630 bool isImm32() 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 == 32;
637 }
638 bool isImm1_7() 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 > 0 && Value < 8;
645 }
646 bool isImm1_15() 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 < 16;
653 }
654 bool isImm1_31() 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 < 32;
661 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000662 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000663 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000664 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 < 17;
669 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000670 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000671 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +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 < 33;
677 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000678 bool isImm0_32() const {
679 if (Kind != k_Immediate)
680 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 Grosbachfff76ee2011-07-13 20:10:10 +0000686 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000687 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000688 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 < 65536;
693 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000694 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000695 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 // If it's not a constant expression, it'll generate a fixup and be
699 // handled later.
700 if (!CE) return true;
701 int64_t Value = CE->getValue();
702 return Value >= 0 && Value < 65536;
703 }
Jim Grosbached838482011-07-26 16:24:27 +0000704 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000705 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000706 return false;
707 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
708 if (!CE) return false;
709 int64_t Value = CE->getValue();
710 return Value >= 0 && Value <= 0xffffff;
711 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000712 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000713 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51: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 < 33;
719 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000720 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000721 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +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 < 32;
727 }
728 bool isPKHASRImm() 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 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000736 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000737 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000738 return false;
739 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
740 if (!CE) return false;
741 int64_t Value = CE->getValue();
742 return ARM_AM::getSOImmVal(Value) != -1;
743 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000744 bool isARMSOImmNot() const {
745 if (Kind != k_Immediate)
746 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 Grosbach3bc8a3d2011-12-08 00:31:07 +0000752 bool isARMSOImmNeg() 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 Grosbach6b8f1e32011-06-27 23:54:06 +0000760 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000762 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::getT2SOImmVal(Value) != -1;
767 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000768 bool isT2SOImmNot() const {
769 if (Kind != k_Immediate)
770 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 Grosbach3bc8a3d2011-12-08 00:31:07 +0000776 bool isT2SOImmNeg() 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 Grosbachc27d4f92011-07-22 17:44:50 +0000784 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000785 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return Value == 1 || Value == 0;
791 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000792 bool isReg() const { return Kind == k_Register; }
793 bool isRegList() const { return Kind == k_RegisterList; }
794 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
795 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
796 bool isToken() const { return Kind == k_Token; }
797 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
798 bool isMemory() const { return Kind == k_Memory; }
799 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
800 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
801 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
802 bool isRotImm() const { return Kind == k_RotateImmediate; }
803 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
804 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000805 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000806 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000807 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000808 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000809 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000810 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000811 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000812 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
813 (alignOK || Memory.Alignment == 0);
814 }
815 bool isAlignedMemory() const {
816 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000817 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000818 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000819 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000820 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000821 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000822 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000823 if (!Memory.OffsetImm) return true;
824 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000825 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000826 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000827 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000828 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000829 return false;
830 // Immediate offset in range [-4095, 4095].
831 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
832 if (!CE) return false;
833 int64_t Val = CE->getValue();
834 return Val > -4096 && Val < 4096;
835 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000836 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000837 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000838 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000839 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000840 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000841 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000842 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000843 if (!Memory.OffsetImm) return true;
844 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000845 return Val > -256 && Val < 256;
846 }
847 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000848 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000849 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000850 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000851 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
852 // Immediate offset in range [-255, 255].
853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
854 if (!CE) return false;
855 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000856 // Special case, #-0 is INT32_MIN.
857 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000858 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000860 // If we have an immediate that's not a constant, treat it as a label
861 // reference needing a fixup. If it is a constant, it's something else
862 // and we reject it.
863 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
864 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000865 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000867 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000869 if (!Memory.OffsetImm) return true;
870 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000871 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000872 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000873 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000874 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000875 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000876 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000877 return false;
878 return true;
879 }
880 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000881 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000882 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
883 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000884 return false;
885 return true;
886 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000887 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000888 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000889 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000890 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000891 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000892 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000893 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
894 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000895 return false;
896 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000897 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000898 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000899 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000900 return false;
901 return true;
902 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000903 bool isMemThumbRR() const {
904 // Thumb reg+reg addressing is simple. Just two registers, a base and
905 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000906 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000907 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000908 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000909 return isARMLowRegister(Memory.BaseRegNum) &&
910 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000911 }
912 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000913 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000914 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000915 return false;
916 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000917 if (!Memory.OffsetImm) return true;
918 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000919 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
920 }
Jim Grosbach38466302011-08-19 18:55:51 +0000921 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000923 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000924 return false;
925 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000926 if (!Memory.OffsetImm) return true;
927 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000928 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
929 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000930 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000931 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000932 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000933 return false;
934 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000935 if (!Memory.OffsetImm) return true;
936 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000937 return Val >= 0 && Val <= 31;
938 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000939 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000940 if (!isMemory() || Memory.OffsetRegNum != 0 ||
941 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000942 return false;
943 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (!Memory.OffsetImm) return true;
945 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000946 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000947 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000948 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000949 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000950 return false;
951 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (!Memory.OffsetImm) return true;
953 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000954 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
955 }
Jim Grosbachb6aed502011-09-09 18:37:27 +0000956 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000957 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +0000958 return false;
959 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000960 if (!Memory.OffsetImm) return true;
961 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +0000962 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
963 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000964 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000966 return false;
967 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000968 if (!Memory.OffsetImm) return true;
969 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +0000970 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000971 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000972 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000973 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000974 return false;
975 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (!Memory.OffsetImm) return true;
977 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +0000978 return Val >= 0 && Val < 256;
979 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000980 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000981 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000982 return false;
983 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000984 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000985 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +0000986 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000987 }
988 bool isMemUImm12Offset() 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 [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000992 if (!Memory.OffsetImm) return true;
993 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +0000994 return (Val >= 0 && Val < 4096);
995 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000996 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +0000997 // If we have an immediate that's not a constant, treat it as a label
998 // reference needing a fixup. If it is a constant, it's something else
999 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001000 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001001 return true;
1002
Jim Grosbach57dcb852011-10-11 17:29:55 +00001003 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001004 return false;
1005 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001006 if (!Memory.OffsetImm) return true;
1007 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001008 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001009 }
1010 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001011 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001012 return false;
1013 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1014 if (!CE) return false;
1015 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001016 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001017 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001018 bool isPostIdxImm8s4() const {
1019 if (Kind != k_Immediate)
1020 return false;
1021 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1022 if (!CE) return false;
1023 int64_t Val = CE->getValue();
1024 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1025 (Val == INT32_MIN);
1026 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001027
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001028 bool isMSRMask() const { return Kind == k_MSRMask; }
1029 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001030
Jim Grosbach0e387b22011-10-17 22:26:03 +00001031 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +00001032 bool isVecListOneD() const {
1033 if (Kind != k_VectorList) return false;
1034 return VectorList.Count == 1;
1035 }
1036
Jim Grosbach280dfad2011-10-21 18:54:25 +00001037 bool isVecListTwoD() const {
1038 if (Kind != k_VectorList) return false;
1039 return VectorList.Count == 2;
1040 }
1041
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001042 bool isVecListThreeD() const {
1043 if (Kind != k_VectorList) return false;
1044 return VectorList.Count == 3;
1045 }
1046
Jim Grosbachb6310312011-10-21 20:35:01 +00001047 bool isVecListFourD() const {
1048 if (Kind != k_VectorList) return false;
1049 return VectorList.Count == 4;
1050 }
1051
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001052 bool isVecListTwoQ() const {
1053 if (Kind != k_VectorList) return false;
1054 //FIXME: We haven't taught the parser to handle by-two register lists
1055 // yet, so don't pretend to know one.
1056 return VectorList.Count == 2 && false;
1057 }
1058
Jim Grosbach98b05a52011-11-30 01:09:44 +00001059 bool isVecListOneDAllLanes() const {
1060 if (Kind != k_VectorListAllLanes) return false;
1061 return VectorList.Count == 1;
1062 }
1063
Jim Grosbach13af2222011-11-30 18:21:25 +00001064 bool isVecListTwoDAllLanes() const {
1065 if (Kind != k_VectorListAllLanes) return false;
1066 return VectorList.Count == 2;
1067 }
1068
Jim Grosbach7636bf62011-12-02 00:35:16 +00001069 bool isVecListOneDByteIndexed() const {
1070 if (Kind != k_VectorListIndexed) return false;
1071 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1072 }
1073
Jim Grosbach460a9052011-10-07 23:56:00 +00001074 bool isVectorIndex8() const {
1075 if (Kind != k_VectorIndex) return false;
1076 return VectorIndex.Val < 8;
1077 }
1078 bool isVectorIndex16() const {
1079 if (Kind != k_VectorIndex) return false;
1080 return VectorIndex.Val < 4;
1081 }
1082 bool isVectorIndex32() const {
1083 if (Kind != k_VectorIndex) return false;
1084 return VectorIndex.Val < 2;
1085 }
1086
Jim Grosbach0e387b22011-10-17 22:26:03 +00001087 bool isNEONi8splat() const {
1088 if (Kind != k_Immediate)
1089 return false;
1090 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1091 // Must be a constant.
1092 if (!CE) return false;
1093 int64_t Value = CE->getValue();
1094 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1095 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001096 return Value >= 0 && Value < 256;
1097 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001098
Jim Grosbachea461102011-10-17 23:09:09 +00001099 bool isNEONi16splat() const {
1100 if (Kind != k_Immediate)
1101 return false;
1102 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1103 // Must be a constant.
1104 if (!CE) return false;
1105 int64_t Value = CE->getValue();
1106 // i16 value in the range [0,255] or [0x0100, 0xff00]
1107 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1108 }
1109
Jim Grosbach6248a542011-10-18 00:22:00 +00001110 bool isNEONi32splat() const {
1111 if (Kind != k_Immediate)
1112 return false;
1113 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1114 // Must be a constant.
1115 if (!CE) return false;
1116 int64_t Value = CE->getValue();
1117 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1118 return (Value >= 0 && Value < 256) ||
1119 (Value >= 0x0100 && Value <= 0xff00) ||
1120 (Value >= 0x010000 && Value <= 0xff0000) ||
1121 (Value >= 0x01000000 && Value <= 0xff000000);
1122 }
1123
1124 bool isNEONi32vmov() const {
1125 if (Kind != k_Immediate)
1126 return false;
1127 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1128 // Must be a constant.
1129 if (!CE) return false;
1130 int64_t Value = CE->getValue();
1131 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1132 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1133 return (Value >= 0 && Value < 256) ||
1134 (Value >= 0x0100 && Value <= 0xff00) ||
1135 (Value >= 0x010000 && Value <= 0xff0000) ||
1136 (Value >= 0x01000000 && Value <= 0xff000000) ||
1137 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1138 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1139 }
1140
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001141 bool isNEONi64splat() const {
1142 if (Kind != k_Immediate)
1143 return false;
1144 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1145 // Must be a constant.
1146 if (!CE) return false;
1147 uint64_t Value = CE->getValue();
1148 // i64 value with each byte being either 0 or 0xff.
1149 for (unsigned i = 0; i < 8; ++i)
1150 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1151 return true;
1152 }
1153
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001154 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001155 // Add as immediates when possible. Null MCExpr = 0.
1156 if (Expr == 0)
1157 Inst.addOperand(MCOperand::CreateImm(0));
1158 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001159 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1160 else
1161 Inst.addOperand(MCOperand::CreateExpr(Expr));
1162 }
1163
Daniel Dunbar8462b302010-08-11 06:36:53 +00001164 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001165 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001166 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001167 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1168 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001169 }
1170
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001171 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1172 assert(N == 1 && "Invalid number of operands!");
1173 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1174 }
1175
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001176 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1177 assert(N == 1 && "Invalid number of operands!");
1178 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1179 }
1180
1181 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1182 assert(N == 1 && "Invalid number of operands!");
1183 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1184 }
1185
Jim Grosbach89df9962011-08-26 21:43:41 +00001186 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1187 assert(N == 1 && "Invalid number of operands!");
1188 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1189 }
1190
1191 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1192 assert(N == 1 && "Invalid number of operands!");
1193 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1194 }
1195
Jim Grosbachd67641b2010-12-06 18:21:12 +00001196 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1197 assert(N == 1 && "Invalid number of operands!");
1198 Inst.addOperand(MCOperand::CreateReg(getReg()));
1199 }
1200
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001201 void addRegOperands(MCInst &Inst, unsigned N) const {
1202 assert(N == 1 && "Invalid number of operands!");
1203 Inst.addOperand(MCOperand::CreateReg(getReg()));
1204 }
1205
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001206 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001207 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001208 assert(isRegShiftedReg() &&
1209 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001210 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1211 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001212 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001213 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001214 }
1215
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001216 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001217 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001218 assert(isRegShiftedImm() &&
1219 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001220 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001221 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001222 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001223 }
1224
Jim Grosbach580f4a92011-07-25 22:20:28 +00001225 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001226 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001227 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1228 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001229 }
1230
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001231 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001232 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001233 const SmallVectorImpl<unsigned> &RegList = getRegList();
1234 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001235 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1236 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001237 }
1238
Bill Wendling0f630752010-11-17 04:32:08 +00001239 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1240 addRegListOperands(Inst, N);
1241 }
1242
1243 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1244 addRegListOperands(Inst, N);
1245 }
1246
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001247 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1248 assert(N == 1 && "Invalid number of operands!");
1249 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1250 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1251 }
1252
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001253 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1254 assert(N == 1 && "Invalid number of operands!");
1255 // Munge the lsb/width into a bitfield mask.
1256 unsigned lsb = Bitfield.LSB;
1257 unsigned width = Bitfield.Width;
1258 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1259 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1260 (32 - (lsb + width)));
1261 Inst.addOperand(MCOperand::CreateImm(Mask));
1262 }
1263
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001264 void addImmOperands(MCInst &Inst, unsigned N) const {
1265 assert(N == 1 && "Invalid number of operands!");
1266 addExpr(Inst, getImm());
1267 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001268
Jim Grosbach9d390362011-10-03 23:38:36 +00001269 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1270 assert(N == 1 && "Invalid number of operands!");
1271 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1272 }
1273
Jim Grosbacha77295d2011-09-08 22:07:06 +00001274 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1275 assert(N == 1 && "Invalid number of operands!");
1276 // FIXME: We really want to scale the value here, but the LDRD/STRD
1277 // instruction don't encode operands that way yet.
1278 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1279 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1280 }
1281
Jim Grosbach72f39f82011-08-24 21:22:15 +00001282 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1283 assert(N == 1 && "Invalid number of operands!");
1284 // The immediate is scaled by four in the encoding and is stored
1285 // in the MCInst as such. Lop off the low two bits here.
1286 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1287 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1288 }
1289
1290 void addImm0_508s4Operands(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
Jim Grosbachf4943352011-07-25 23:09:14 +00001298 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
1300 // The constant encodes as the immediate-1, and we store in the instruction
1301 // the bits as encoded, so subtract off one here.
1302 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1303 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1304 }
1305
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001306 void addImm1_32Operands(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 Grosbach70939ee2011-08-17 21:51:27 +00001314 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
1316 // The constant encodes as the immediate, except for 32, which encodes as
1317 // zero.
1318 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319 unsigned Imm = CE->getValue();
1320 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1321 }
1322
Jim Grosbachf6c05252011-07-21 17:23:04 +00001323 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1324 assert(N == 1 && "Invalid number of operands!");
1325 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1326 // the instruction as well.
1327 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1328 int Val = CE->getValue();
1329 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1330 }
1331
Jim Grosbach89a63372011-10-28 22:36:30 +00001332 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1333 assert(N == 1 && "Invalid number of operands!");
1334 // The operand is actually a t2_so_imm, but we have its bitwise
1335 // negation in the assembly source, so twiddle it here.
1336 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1337 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1338 }
1339
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001340 void addT2SOImmNegOperands(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
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 Grosbache70ec842011-10-28 22:50:54 +00001348 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1349 assert(N == 1 && "Invalid number of operands!");
1350 // The operand is actually a so_imm, but we have its bitwise
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 Grosbach3bc8a3d2011-12-08 00:31:07 +00001356 void addARMSOImmNegOperands(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
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
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001364 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
1366 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1367 }
1368
Jim Grosbach7ce05792011-08-03 23:50:40 +00001369 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1370 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001371 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001372 }
1373
Jim Grosbach57dcb852011-10-11 17:29:55 +00001374 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1375 assert(N == 2 && "Invalid number of operands!");
1376 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1377 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1378 }
1379
Jim Grosbach7ce05792011-08-03 23:50:40 +00001380 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1381 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001382 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1383 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001384 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1385 // Special case for #-0
1386 if (Val == INT32_MIN) Val = 0;
1387 if (Val < 0) Val = -Val;
1388 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1389 } else {
1390 // For register offset, we encode the shift type and negation flag
1391 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001392 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1393 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001394 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001395 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1396 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001397 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001398 }
1399
Jim Grosbach039c2e12011-08-04 23:01:30 +00001400 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1401 assert(N == 2 && "Invalid number of operands!");
1402 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1403 assert(CE && "non-constant AM2OffsetImm operand!");
1404 int32_t Val = CE->getValue();
1405 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1406 // Special case for #-0
1407 if (Val == INT32_MIN) Val = 0;
1408 if (Val < 0) Val = -Val;
1409 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1410 Inst.addOperand(MCOperand::CreateReg(0));
1411 Inst.addOperand(MCOperand::CreateImm(Val));
1412 }
1413
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001414 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1415 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001416 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1417 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001418 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1419 // Special case for #-0
1420 if (Val == INT32_MIN) Val = 0;
1421 if (Val < 0) Val = -Val;
1422 Val = ARM_AM::getAM3Opc(AddSub, Val);
1423 } else {
1424 // For register offset, we encode the shift type and negation flag
1425 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001426 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001427 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001428 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1429 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001430 Inst.addOperand(MCOperand::CreateImm(Val));
1431 }
1432
1433 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001435 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001436 int32_t Val =
1437 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1438 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1439 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001440 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001441 }
1442
1443 // Constant offset.
1444 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1445 int32_t Val = CE->getValue();
1446 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1447 // Special case for #-0
1448 if (Val == INT32_MIN) Val = 0;
1449 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001450 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001451 Inst.addOperand(MCOperand::CreateReg(0));
1452 Inst.addOperand(MCOperand::CreateImm(Val));
1453 }
1454
Jim Grosbach7ce05792011-08-03 23:50:40 +00001455 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1456 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001457 // If we have an immediate that's not a constant, treat it as a label
1458 // reference needing a fixup. If it is a constant, it's something else
1459 // and we reject it.
1460 if (isImm()) {
1461 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1462 Inst.addOperand(MCOperand::CreateImm(0));
1463 return;
1464 }
1465
Jim Grosbach7ce05792011-08-03 23:50:40 +00001466 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001467 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001468 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1469 // Special case for #-0
1470 if (Val == INT32_MIN) Val = 0;
1471 if (Val < 0) Val = -Val;
1472 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001473 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001474 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001475 }
1476
Jim Grosbacha77295d2011-09-08 22:07:06 +00001477 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1478 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001479 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1480 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001481 Inst.addOperand(MCOperand::CreateImm(Val));
1482 }
1483
Jim Grosbachb6aed502011-09-09 18:37:27 +00001484 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 2 && "Invalid number of operands!");
1486 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001487 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1488 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001489 Inst.addOperand(MCOperand::CreateImm(Val));
1490 }
1491
Jim Grosbach7ce05792011-08-03 23:50:40 +00001492 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1493 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001494 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1495 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001496 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001497 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001498
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001499 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1500 addMemImm8OffsetOperands(Inst, N);
1501 }
1502
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001503 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001504 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001505 }
1506
1507 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 2 && "Invalid number of operands!");
1509 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001510 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001511 addExpr(Inst, getImm());
1512 Inst.addOperand(MCOperand::CreateImm(0));
1513 return;
1514 }
1515
1516 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001517 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1518 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001519 Inst.addOperand(MCOperand::CreateImm(Val));
1520 }
1521
Jim Grosbach7ce05792011-08-03 23:50:40 +00001522 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001524 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001525 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001526 addExpr(Inst, getImm());
1527 Inst.addOperand(MCOperand::CreateImm(0));
1528 return;
1529 }
1530
1531 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001532 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1533 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001534 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001535 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001536
Jim Grosbach7f739be2011-09-19 22:21:13 +00001537 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001539 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1540 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001541 }
1542
1543 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001545 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1546 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001547 }
1548
Jim Grosbach7ce05792011-08-03 23:50:40 +00001549 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001551 unsigned Val =
1552 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1553 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001554 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1555 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001556 Inst.addOperand(MCOperand::CreateImm(Val));
1557 }
1558
Jim Grosbachab899c12011-09-07 23:10:15 +00001559 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1560 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001561 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1562 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1563 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001564 }
1565
Jim Grosbach7ce05792011-08-03 23:50:40 +00001566 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001568 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1569 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001570 }
1571
Jim Grosbach60f91a32011-08-19 17:55:24 +00001572 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1573 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001574 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1575 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001576 Inst.addOperand(MCOperand::CreateImm(Val));
1577 }
1578
Jim Grosbach38466302011-08-19 18:55:51 +00001579 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1580 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001581 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1582 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001583 Inst.addOperand(MCOperand::CreateImm(Val));
1584 }
1585
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001586 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1587 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001588 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1589 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001590 Inst.addOperand(MCOperand::CreateImm(Val));
1591 }
1592
Jim Grosbachecd85892011-08-19 18:13:48 +00001593 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1594 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001595 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1596 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001597 Inst.addOperand(MCOperand::CreateImm(Val));
1598 }
1599
Jim Grosbach7ce05792011-08-03 23:50:40 +00001600 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1601 assert(N == 1 && "Invalid number of operands!");
1602 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1603 assert(CE && "non-constant post-idx-imm8 operand!");
1604 int Imm = CE->getValue();
1605 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001606 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001607 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1608 Inst.addOperand(MCOperand::CreateImm(Imm));
1609 }
1610
Jim Grosbach2bd01182011-10-11 21:55:36 +00001611 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1612 assert(N == 1 && "Invalid number of operands!");
1613 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1614 assert(CE && "non-constant post-idx-imm8s4 operand!");
1615 int Imm = CE->getValue();
1616 bool isAdd = Imm >= 0;
1617 if (Imm == INT32_MIN) Imm = 0;
1618 // Immediate is scaled by 4.
1619 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1620 Inst.addOperand(MCOperand::CreateImm(Imm));
1621 }
1622
Jim Grosbach7ce05792011-08-03 23:50:40 +00001623 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1624 assert(N == 2 && "Invalid number of operands!");
1625 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001626 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1627 }
1628
1629 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 2 && "Invalid number of operands!");
1631 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1632 // The sign, shift type, and shift amount are encoded in a single operand
1633 // using the AM2 encoding helpers.
1634 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1635 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1636 PostIdxReg.ShiftTy);
1637 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001638 }
1639
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001640 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1641 assert(N == 1 && "Invalid number of operands!");
1642 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1643 }
1644
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001645 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1646 assert(N == 1 && "Invalid number of operands!");
1647 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1648 }
1649
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001650 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001651 assert(N == 1 && "Invalid number of operands!");
1652 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1653 }
1654
Jim Grosbach7636bf62011-12-02 00:35:16 +00001655 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1656 assert(N == 2 && "Invalid number of operands!");
1657 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1658 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1659 }
1660
Jim Grosbach460a9052011-10-07 23:56:00 +00001661 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1662 assert(N == 1 && "Invalid number of operands!");
1663 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1664 }
1665
1666 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1667 assert(N == 1 && "Invalid number of operands!");
1668 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1669 }
1670
1671 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1672 assert(N == 1 && "Invalid number of operands!");
1673 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1674 }
1675
Jim Grosbach0e387b22011-10-17 22:26:03 +00001676 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1677 assert(N == 1 && "Invalid number of operands!");
1678 // The immediate encodes the type of constant as well as the value.
1679 // Mask in that this is an i8 splat.
1680 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1681 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1682 }
1683
Jim Grosbachea461102011-10-17 23:09:09 +00001684 void addNEONi16splatOperands(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 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1688 unsigned Value = CE->getValue();
1689 if (Value >= 256)
1690 Value = (Value >> 8) | 0xa00;
1691 else
1692 Value |= 0x800;
1693 Inst.addOperand(MCOperand::CreateImm(Value));
1694 }
1695
Jim Grosbach6248a542011-10-18 00:22:00 +00001696 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1697 assert(N == 1 && "Invalid number of operands!");
1698 // The immediate encodes the type of constant as well as the value.
1699 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1700 unsigned Value = CE->getValue();
1701 if (Value >= 256 && Value <= 0xff00)
1702 Value = (Value >> 8) | 0x200;
1703 else if (Value > 0xffff && Value <= 0xff0000)
1704 Value = (Value >> 16) | 0x400;
1705 else if (Value > 0xffffff)
1706 Value = (Value >> 24) | 0x600;
1707 Inst.addOperand(MCOperand::CreateImm(Value));
1708 }
1709
1710 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1711 assert(N == 1 && "Invalid number of operands!");
1712 // The immediate encodes the type of constant as well as the value.
1713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1714 unsigned Value = CE->getValue();
1715 if (Value >= 256 && Value <= 0xffff)
1716 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1717 else if (Value > 0xffff && Value <= 0xffffff)
1718 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1719 else if (Value > 0xffffff)
1720 Value = (Value >> 24) | 0x600;
1721 Inst.addOperand(MCOperand::CreateImm(Value));
1722 }
1723
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001724 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1725 assert(N == 1 && "Invalid number of operands!");
1726 // The immediate encodes the type of constant as well as the value.
1727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1728 uint64_t Value = CE->getValue();
1729 unsigned Imm = 0;
1730 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1731 Imm |= (Value & 1) << i;
1732 }
1733 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1734 }
1735
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001736 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001737
Jim Grosbach89df9962011-08-26 21:43:41 +00001738 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001739 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001740 Op->ITMask.Mask = Mask;
1741 Op->StartLoc = S;
1742 Op->EndLoc = S;
1743 return Op;
1744 }
1745
Chris Lattner3a697562010-10-28 17:20:03 +00001746 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001747 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001748 Op->CC.Val = CC;
1749 Op->StartLoc = S;
1750 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001751 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001752 }
1753
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001754 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001755 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001756 Op->Cop.Val = CopVal;
1757 Op->StartLoc = S;
1758 Op->EndLoc = S;
1759 return Op;
1760 }
1761
1762 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001763 ARMOperand *Op = new ARMOperand(k_CoprocReg);
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
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001770 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1771 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1772 Op->Cop.Val = Val;
1773 Op->StartLoc = S;
1774 Op->EndLoc = E;
1775 return Op;
1776 }
1777
Jim Grosbachd67641b2010-12-06 18:21:12 +00001778 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001779 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001780 Op->Reg.RegNum = RegNum;
1781 Op->StartLoc = S;
1782 Op->EndLoc = S;
1783 return Op;
1784 }
1785
Chris Lattner3a697562010-10-28 17:20:03 +00001786 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001787 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001788 Op->Tok.Data = Str.data();
1789 Op->Tok.Length = Str.size();
1790 Op->StartLoc = S;
1791 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001792 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001793 }
1794
Bill Wendling50d0f582010-11-18 23:43:05 +00001795 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001796 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001797 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001798 Op->StartLoc = S;
1799 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001800 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001801 }
1802
Jim Grosbache8606dc2011-07-13 17:50:29 +00001803 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1804 unsigned SrcReg,
1805 unsigned ShiftReg,
1806 unsigned ShiftImm,
1807 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001808 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001809 Op->RegShiftedReg.ShiftTy = ShTy;
1810 Op->RegShiftedReg.SrcReg = SrcReg;
1811 Op->RegShiftedReg.ShiftReg = ShiftReg;
1812 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001813 Op->StartLoc = S;
1814 Op->EndLoc = E;
1815 return Op;
1816 }
1817
Owen Anderson92a20222011-07-21 18:54:16 +00001818 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1819 unsigned SrcReg,
1820 unsigned ShiftImm,
1821 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001822 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001823 Op->RegShiftedImm.ShiftTy = ShTy;
1824 Op->RegShiftedImm.SrcReg = SrcReg;
1825 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001826 Op->StartLoc = S;
1827 Op->EndLoc = E;
1828 return Op;
1829 }
1830
Jim Grosbach580f4a92011-07-25 22:20:28 +00001831 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001832 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001833 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001834 Op->ShifterImm.isASR = isASR;
1835 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001836 Op->StartLoc = S;
1837 Op->EndLoc = E;
1838 return Op;
1839 }
1840
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001841 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001842 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001843 Op->RotImm.Imm = Imm;
1844 Op->StartLoc = S;
1845 Op->EndLoc = E;
1846 return Op;
1847 }
1848
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001849 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1850 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001851 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001852 Op->Bitfield.LSB = LSB;
1853 Op->Bitfield.Width = Width;
1854 Op->StartLoc = S;
1855 Op->EndLoc = E;
1856 return Op;
1857 }
1858
Bill Wendling7729e062010-11-09 22:44:22 +00001859 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001860 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001861 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001862 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001863
Jim Grosbachd300b942011-09-13 22:56:44 +00001864 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001865 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001866 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001867 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001868 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001869
1870 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001871 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001872 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001873 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001874 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001875 Op->StartLoc = StartLoc;
1876 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001877 return Op;
1878 }
1879
Jim Grosbach862019c2011-10-18 23:02:30 +00001880 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1881 SMLoc S, SMLoc E) {
1882 ARMOperand *Op = new ARMOperand(k_VectorList);
1883 Op->VectorList.RegNum = RegNum;
1884 Op->VectorList.Count = Count;
1885 Op->StartLoc = S;
1886 Op->EndLoc = E;
1887 return Op;
1888 }
1889
Jim Grosbach98b05a52011-11-30 01:09:44 +00001890 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1891 SMLoc S, SMLoc E) {
1892 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1893 Op->VectorList.RegNum = RegNum;
1894 Op->VectorList.Count = Count;
1895 Op->StartLoc = S;
1896 Op->EndLoc = E;
1897 return Op;
1898 }
1899
Jim Grosbach7636bf62011-12-02 00:35:16 +00001900 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1901 unsigned Index, SMLoc S, SMLoc E) {
1902 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1903 Op->VectorList.RegNum = RegNum;
1904 Op->VectorList.Count = Count;
1905 Op->VectorList.LaneIndex = Index;
1906 Op->StartLoc = S;
1907 Op->EndLoc = E;
1908 return Op;
1909 }
1910
Jim Grosbach460a9052011-10-07 23:56:00 +00001911 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1912 MCContext &Ctx) {
1913 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1914 Op->VectorIndex.Val = Idx;
1915 Op->StartLoc = S;
1916 Op->EndLoc = E;
1917 return Op;
1918 }
1919
Chris Lattner3a697562010-10-28 17:20:03 +00001920 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001921 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001922 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001923 Op->StartLoc = S;
1924 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001925 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001926 }
1927
Jim Grosbach9d390362011-10-03 23:38:36 +00001928 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001929 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001930 Op->FPImm.Val = Val;
1931 Op->StartLoc = S;
1932 Op->EndLoc = S;
1933 return Op;
1934 }
1935
Jim Grosbach7ce05792011-08-03 23:50:40 +00001936 static ARMOperand *CreateMem(unsigned BaseRegNum,
1937 const MCConstantExpr *OffsetImm,
1938 unsigned OffsetRegNum,
1939 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001940 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001941 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001942 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001943 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001944 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001945 Op->Memory.BaseRegNum = BaseRegNum;
1946 Op->Memory.OffsetImm = OffsetImm;
1947 Op->Memory.OffsetRegNum = OffsetRegNum;
1948 Op->Memory.ShiftType = ShiftType;
1949 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001950 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001951 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001952 Op->StartLoc = S;
1953 Op->EndLoc = E;
1954 return Op;
1955 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001956
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001957 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
1958 ARM_AM::ShiftOpc ShiftTy,
1959 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001960 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001961 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001962 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001963 Op->PostIdxReg.isAdd = isAdd;
1964 Op->PostIdxReg.ShiftTy = ShiftTy;
1965 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00001966 Op->StartLoc = S;
1967 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001968 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001969 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001970
1971 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001972 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001973 Op->MBOpt.Val = Opt;
1974 Op->StartLoc = S;
1975 Op->EndLoc = S;
1976 return Op;
1977 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001978
1979 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001980 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001981 Op->IFlags.Val = IFlags;
1982 Op->StartLoc = S;
1983 Op->EndLoc = S;
1984 return Op;
1985 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001986
1987 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001988 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001989 Op->MMask.Val = MMask;
1990 Op->StartLoc = S;
1991 Op->EndLoc = S;
1992 return Op;
1993 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001994};
1995
1996} // end anonymous namespace.
1997
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001998void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00001999 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002000 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002001 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2002 << ") >";
2003 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002004 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002005 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002006 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002007 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002008 OS << "<ccout " << getReg() << ">";
2009 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002010 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002011 static const char *MaskStr[] = {
2012 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2013 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2014 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002015 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2016 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2017 break;
2018 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002019 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002020 OS << "<coprocessor number: " << getCoproc() << ">";
2021 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002022 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002023 OS << "<coprocessor register: " << getCoproc() << ">";
2024 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002025 case k_CoprocOption:
2026 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2027 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002028 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002029 OS << "<mask: " << getMSRMask() << ">";
2030 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002031 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002032 getImm()->print(OS);
2033 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002034 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002035 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2036 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002037 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002038 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002039 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002040 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002041 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002042 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002043 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2044 << PostIdxReg.RegNum;
2045 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2046 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2047 << PostIdxReg.ShiftImm;
2048 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002049 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002050 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002051 OS << "<ARM_PROC::";
2052 unsigned IFlags = getProcIFlags();
2053 for (int i=2; i >= 0; --i)
2054 if (IFlags & (1 << i))
2055 OS << ARM_PROC::IFlagsToString(1 << i);
2056 OS << ">";
2057 break;
2058 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002059 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002060 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002061 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002062 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002063 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2064 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002065 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002066 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002067 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002068 << RegShiftedReg.SrcReg << " "
2069 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2070 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002071 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002072 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002073 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002074 << RegShiftedImm.SrcReg << " "
2075 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2076 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002077 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002078 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002079 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2080 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002081 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002082 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2083 << ", width: " << Bitfield.Width << ">";
2084 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002085 case k_RegisterList:
2086 case k_DPRRegisterList:
2087 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002088 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002089
Bill Wendling5fa22a12010-11-09 23:28:44 +00002090 const SmallVectorImpl<unsigned> &RegList = getRegList();
2091 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002092 I = RegList.begin(), E = RegList.end(); I != E; ) {
2093 OS << *I;
2094 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002095 }
2096
2097 OS << ">";
2098 break;
2099 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002100 case k_VectorList:
2101 OS << "<vector_list " << VectorList.Count << " * "
2102 << VectorList.RegNum << ">";
2103 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002104 case k_VectorListAllLanes:
2105 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2106 << VectorList.RegNum << ">";
2107 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002108 case k_VectorListIndexed:
2109 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2110 << VectorList.Count << " * " << VectorList.RegNum << ">";
2111 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002112 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002113 OS << "'" << getToken() << "'";
2114 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002115 case k_VectorIndex:
2116 OS << "<vectorindex " << getVectorIndex() << ">";
2117 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002118 }
2119}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002120
2121/// @name Auto-generated Match Functions
2122/// {
2123
2124static unsigned MatchRegisterName(StringRef Name);
2125
2126/// }
2127
Bob Wilson69df7232011-02-03 21:46:10 +00002128bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2129 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002130 RegNo = tryParseRegister();
Roman Divackybf755322011-01-27 17:14:22 +00002131
2132 return (RegNo == (unsigned)-1);
2133}
2134
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002135/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002136/// and if it is a register name the token is eaten and the register number is
2137/// returned. Otherwise return -1.
2138///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002139int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002140 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002141 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002142
Chris Lattnere5658fa2010-10-30 04:09:10 +00002143 // FIXME: Validate register for the current architecture; we have to do
2144 // validation later, so maybe there is no need for this here.
Benjamin Kramer59085362011-11-06 20:37:06 +00002145 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002146 unsigned RegNum = MatchRegisterName(lowerCase);
2147 if (!RegNum) {
2148 RegNum = StringSwitch<unsigned>(lowerCase)
2149 .Case("r13", ARM::SP)
2150 .Case("r14", ARM::LR)
2151 .Case("r15", ARM::PC)
2152 .Case("ip", ARM::R12)
2153 .Default(0);
2154 }
2155 if (!RegNum) return -1;
Bob Wilson69df7232011-02-03 21:46:10 +00002156
Chris Lattnere5658fa2010-10-30 04:09:10 +00002157 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002158
Chris Lattnere5658fa2010-10-30 04:09:10 +00002159 return RegNum;
2160}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002161
Jim Grosbach19906722011-07-13 18:49:30 +00002162// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2163// If a recoverable error occurs, return 1. If an irrecoverable error
2164// occurs, return -1. An irrecoverable error is one where tokens have been
2165// consumed in the process of trying to parse the shifter (i.e., when it is
2166// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002167int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002168 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2169 SMLoc S = Parser.getTok().getLoc();
2170 const AsmToken &Tok = Parser.getTok();
2171 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2172
Benjamin Kramer59085362011-11-06 20:37:06 +00002173 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002174 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002175 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002176 .Case("lsl", ARM_AM::lsl)
2177 .Case("lsr", ARM_AM::lsr)
2178 .Case("asr", ARM_AM::asr)
2179 .Case("ror", ARM_AM::ror)
2180 .Case("rrx", ARM_AM::rrx)
2181 .Default(ARM_AM::no_shift);
2182
2183 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002184 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002185
Jim Grosbache8606dc2011-07-13 17:50:29 +00002186 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002187
Jim Grosbache8606dc2011-07-13 17:50:29 +00002188 // The source register for the shift has already been added to the
2189 // operand list, so we need to pop it off and combine it into the shifted
2190 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002191 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002192 if (!PrevOp->isReg())
2193 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2194 int SrcReg = PrevOp->getReg();
2195 int64_t Imm = 0;
2196 int ShiftReg = 0;
2197 if (ShiftTy == ARM_AM::rrx) {
2198 // RRX Doesn't have an explicit shift amount. The encoder expects
2199 // the shift register to be the same as the source register. Seems odd,
2200 // but OK.
2201 ShiftReg = SrcReg;
2202 } else {
2203 // Figure out if this is shifted by a constant or a register (for non-RRX).
2204 if (Parser.getTok().is(AsmToken::Hash)) {
2205 Parser.Lex(); // Eat hash.
2206 SMLoc ImmLoc = Parser.getTok().getLoc();
2207 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002208 if (getParser().ParseExpression(ShiftExpr)) {
2209 Error(ImmLoc, "invalid immediate shift value");
2210 return -1;
2211 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002212 // The expression must be evaluatable as an immediate.
2213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002214 if (!CE) {
2215 Error(ImmLoc, "invalid immediate shift value");
2216 return -1;
2217 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002218 // Range check the immediate.
2219 // lsl, ror: 0 <= imm <= 31
2220 // lsr, asr: 0 <= imm <= 32
2221 Imm = CE->getValue();
2222 if (Imm < 0 ||
2223 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2224 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002225 Error(ImmLoc, "immediate shift value out of range");
2226 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002227 }
2228 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002229 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002230 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002231 if (ShiftReg == -1) {
2232 Error (L, "expected immediate or register in shift operand");
2233 return -1;
2234 }
2235 } else {
2236 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002237 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002238 return -1;
2239 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002240 }
2241
Owen Anderson92a20222011-07-21 18:54:16 +00002242 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2243 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002244 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002245 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002246 else
2247 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2248 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002249
Jim Grosbach19906722011-07-13 18:49:30 +00002250 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002251}
2252
2253
Bill Wendling50d0f582010-11-18 23:43:05 +00002254/// Try to parse a register name. The token must be an Identifier when called.
2255/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2256/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002257///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002258/// TODO this is likely to change to allow different register types and or to
2259/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002260bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002261tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002262 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002263 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002264 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002265 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002266
Bill Wendling50d0f582010-11-18 23:43:05 +00002267 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002268
Chris Lattnere5658fa2010-10-30 04:09:10 +00002269 const AsmToken &ExclaimTok = Parser.getTok();
2270 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002271 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2272 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002273 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002274 return false;
2275 }
2276
2277 // Also check for an index operand. This is only legal for vector registers,
2278 // but that'll get caught OK in operand matching, so we don't need to
2279 // explicitly filter everything else out here.
2280 if (Parser.getTok().is(AsmToken::LBrac)) {
2281 SMLoc SIdx = Parser.getTok().getLoc();
2282 Parser.Lex(); // Eat left bracket token.
2283
2284 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002285 if (getParser().ParseExpression(ImmVal))
2286 return MatchOperand_ParseFail;
2287 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2288 if (!MCE) {
2289 TokError("immediate value expected for vector index");
2290 return MatchOperand_ParseFail;
2291 }
2292
2293 SMLoc E = Parser.getTok().getLoc();
2294 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2295 Error(E, "']' expected");
2296 return MatchOperand_ParseFail;
2297 }
2298
2299 Parser.Lex(); // Eat right bracket token.
2300
2301 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2302 SIdx, E,
2303 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002304 }
2305
Bill Wendling50d0f582010-11-18 23:43:05 +00002306 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002307}
2308
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002309/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2310/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2311/// "c5", ...
2312static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002313 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2314 // but efficient.
2315 switch (Name.size()) {
2316 default: break;
2317 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002318 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002319 return -1;
2320 switch (Name[1]) {
2321 default: return -1;
2322 case '0': return 0;
2323 case '1': return 1;
2324 case '2': return 2;
2325 case '3': return 3;
2326 case '4': return 4;
2327 case '5': return 5;
2328 case '6': return 6;
2329 case '7': return 7;
2330 case '8': return 8;
2331 case '9': return 9;
2332 }
2333 break;
2334 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002335 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002336 return -1;
2337 switch (Name[2]) {
2338 default: return -1;
2339 case '0': return 10;
2340 case '1': return 11;
2341 case '2': return 12;
2342 case '3': return 13;
2343 case '4': return 14;
2344 case '5': return 15;
2345 }
2346 break;
2347 }
2348
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002349 return -1;
2350}
2351
Jim Grosbach89df9962011-08-26 21:43:41 +00002352/// parseITCondCode - Try to parse a condition code for an IT instruction.
2353ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2354parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2355 SMLoc S = Parser.getTok().getLoc();
2356 const AsmToken &Tok = Parser.getTok();
2357 if (!Tok.is(AsmToken::Identifier))
2358 return MatchOperand_NoMatch;
2359 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2360 .Case("eq", ARMCC::EQ)
2361 .Case("ne", ARMCC::NE)
2362 .Case("hs", ARMCC::HS)
2363 .Case("cs", ARMCC::HS)
2364 .Case("lo", ARMCC::LO)
2365 .Case("cc", ARMCC::LO)
2366 .Case("mi", ARMCC::MI)
2367 .Case("pl", ARMCC::PL)
2368 .Case("vs", ARMCC::VS)
2369 .Case("vc", ARMCC::VC)
2370 .Case("hi", ARMCC::HI)
2371 .Case("ls", ARMCC::LS)
2372 .Case("ge", ARMCC::GE)
2373 .Case("lt", ARMCC::LT)
2374 .Case("gt", ARMCC::GT)
2375 .Case("le", ARMCC::LE)
2376 .Case("al", ARMCC::AL)
2377 .Default(~0U);
2378 if (CC == ~0U)
2379 return MatchOperand_NoMatch;
2380 Parser.Lex(); // Eat the token.
2381
2382 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2383
2384 return MatchOperand_Success;
2385}
2386
Jim Grosbach43904292011-07-25 20:14:50 +00002387/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002388/// token must be an Identifier when called, and if it is a coprocessor
2389/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002390ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002391parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002392 SMLoc S = Parser.getTok().getLoc();
2393 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002394 if (Tok.isNot(AsmToken::Identifier))
2395 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002396
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002397 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002398 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002399 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002400
2401 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002402 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002403 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002404}
2405
Jim Grosbach43904292011-07-25 20:14:50 +00002406/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002407/// token must be an Identifier when called, and if it is a coprocessor
2408/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002409ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002410parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002411 SMLoc S = Parser.getTok().getLoc();
2412 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002413 if (Tok.isNot(AsmToken::Identifier))
2414 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002415
2416 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2417 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002418 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002419
2420 Parser.Lex(); // Eat identifier token.
2421 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002422 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002423}
2424
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002425/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2426/// coproc_option : '{' imm0_255 '}'
2427ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2428parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2429 SMLoc S = Parser.getTok().getLoc();
2430
2431 // If this isn't a '{', this isn't a coprocessor immediate operand.
2432 if (Parser.getTok().isNot(AsmToken::LCurly))
2433 return MatchOperand_NoMatch;
2434 Parser.Lex(); // Eat the '{'
2435
2436 const MCExpr *Expr;
2437 SMLoc Loc = Parser.getTok().getLoc();
2438 if (getParser().ParseExpression(Expr)) {
2439 Error(Loc, "illegal expression");
2440 return MatchOperand_ParseFail;
2441 }
2442 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2443 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2444 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2445 return MatchOperand_ParseFail;
2446 }
2447 int Val = CE->getValue();
2448
2449 // Check for and consume the closing '}'
2450 if (Parser.getTok().isNot(AsmToken::RCurly))
2451 return MatchOperand_ParseFail;
2452 SMLoc E = Parser.getTok().getLoc();
2453 Parser.Lex(); // Eat the '}'
2454
2455 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2456 return MatchOperand_Success;
2457}
2458
Jim Grosbachd0588e22011-09-14 18:08:35 +00002459// For register list parsing, we need to map from raw GPR register numbering
2460// to the enumeration values. The enumeration values aren't sorted by
2461// register number due to our using "sp", "lr" and "pc" as canonical names.
2462static unsigned getNextRegister(unsigned Reg) {
2463 // If this is a GPR, we need to do it manually, otherwise we can rely
2464 // on the sort ordering of the enumeration since the other reg-classes
2465 // are sane.
2466 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2467 return Reg + 1;
2468 switch(Reg) {
2469 default: assert(0 && "Invalid GPR number!");
2470 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2471 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2472 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2473 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2474 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2475 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2476 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2477 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2478 }
2479}
2480
Jim Grosbachce485e72011-11-11 21:27:40 +00002481// Return the low-subreg of a given Q register.
2482static unsigned getDRegFromQReg(unsigned QReg) {
2483 switch (QReg) {
2484 default: llvm_unreachable("expected a Q register!");
2485 case ARM::Q0: return ARM::D0;
2486 case ARM::Q1: return ARM::D2;
2487 case ARM::Q2: return ARM::D4;
2488 case ARM::Q3: return ARM::D6;
2489 case ARM::Q4: return ARM::D8;
2490 case ARM::Q5: return ARM::D10;
2491 case ARM::Q6: return ARM::D12;
2492 case ARM::Q7: return ARM::D14;
2493 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002494 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002495 case ARM::Q10: return ARM::D20;
2496 case ARM::Q11: return ARM::D22;
2497 case ARM::Q12: return ARM::D24;
2498 case ARM::Q13: return ARM::D26;
2499 case ARM::Q14: return ARM::D28;
2500 case ARM::Q15: return ARM::D30;
2501 }
2502}
2503
Jim Grosbachd0588e22011-09-14 18:08:35 +00002504/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002505bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002506parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002507 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002508 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002509 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002510 Parser.Lex(); // Eat '{' token.
2511 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002512
Jim Grosbachd0588e22011-09-14 18:08:35 +00002513 // Check the first register in the list to see what register class
2514 // this is a list of.
2515 int Reg = tryParseRegister();
2516 if (Reg == -1)
2517 return Error(RegLoc, "register expected");
2518
Jim Grosbachce485e72011-11-11 21:27:40 +00002519 // The reglist instructions have at most 16 registers, so reserve
2520 // space for that many.
2521 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2522
2523 // Allow Q regs and just interpret them as the two D sub-registers.
2524 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2525 Reg = getDRegFromQReg(Reg);
2526 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2527 ++Reg;
2528 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002529 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002530 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2531 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2532 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2533 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2534 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2535 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2536 else
2537 return Error(RegLoc, "invalid register in register list");
2538
Jim Grosbachce485e72011-11-11 21:27:40 +00002539 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002540 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002541
Jim Grosbachd0588e22011-09-14 18:08:35 +00002542 // This starts immediately after the first register token in the list,
2543 // so we can see either a comma or a minus (range separator) as a legal
2544 // next token.
2545 while (Parser.getTok().is(AsmToken::Comma) ||
2546 Parser.getTok().is(AsmToken::Minus)) {
2547 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002548 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002549 SMLoc EndLoc = Parser.getTok().getLoc();
2550 int EndReg = tryParseRegister();
2551 if (EndReg == -1)
2552 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002553 // Allow Q regs and just interpret them as the two D sub-registers.
2554 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2555 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002556 // If the register is the same as the start reg, there's nothing
2557 // more to do.
2558 if (Reg == EndReg)
2559 continue;
2560 // The register must be in the same register class as the first.
2561 if (!RC->contains(EndReg))
2562 return Error(EndLoc, "invalid register in register list");
2563 // Ranges must go from low to high.
2564 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2565 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002566
Jim Grosbachd0588e22011-09-14 18:08:35 +00002567 // Add all the registers in the range to the register list.
2568 while (Reg != EndReg) {
2569 Reg = getNextRegister(Reg);
2570 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2571 }
2572 continue;
2573 }
2574 Parser.Lex(); // Eat the comma.
2575 RegLoc = Parser.getTok().getLoc();
2576 int OldReg = Reg;
2577 Reg = tryParseRegister();
2578 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002579 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002580 // Allow Q regs and just interpret them as the two D sub-registers.
2581 bool isQReg = false;
2582 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2583 Reg = getDRegFromQReg(Reg);
2584 isQReg = true;
2585 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002586 // The register must be in the same register class as the first.
2587 if (!RC->contains(Reg))
2588 return Error(RegLoc, "invalid register in register list");
2589 // List must be monotonically increasing.
2590 if (getARMRegisterNumbering(Reg) <= getARMRegisterNumbering(OldReg))
2591 return Error(RegLoc, "register list not in ascending order");
2592 // VFP register lists must also be contiguous.
2593 // It's OK to use the enumeration values directly here rather, as the
2594 // VFP register classes have the enum sorted properly.
2595 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2596 Reg != OldReg + 1)
2597 return Error(RegLoc, "non-contiguous register range");
2598 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002599 if (isQReg)
2600 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002601 }
2602
Jim Grosbachd0588e22011-09-14 18:08:35 +00002603 SMLoc E = Parser.getTok().getLoc();
2604 if (Parser.getTok().isNot(AsmToken::RCurly))
2605 return Error(E, "'}' expected");
2606 Parser.Lex(); // Eat '}' token.
2607
Bill Wendling50d0f582010-11-18 23:43:05 +00002608 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2609 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002610}
2611
Jim Grosbach98b05a52011-11-30 01:09:44 +00002612// Helper function to parse the lane index for vector lists.
2613ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002614parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2615 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002616 if (Parser.getTok().is(AsmToken::LBrac)) {
2617 Parser.Lex(); // Eat the '['.
2618 if (Parser.getTok().is(AsmToken::RBrac)) {
2619 // "Dn[]" is the 'all lanes' syntax.
2620 LaneKind = AllLanes;
2621 Parser.Lex(); // Eat the ']'.
2622 return MatchOperand_Success;
2623 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002624 if (Parser.getTok().is(AsmToken::Integer)) {
2625 int64_t Val = Parser.getTok().getIntVal();
2626 // Make this range check context sensitive for .8, .16, .32.
2627 if (Val < 0 && Val > 7)
2628 Error(Parser.getTok().getLoc(), "lane index out of range");
2629 Index = Val;
2630 LaneKind = IndexedLane;
2631 Parser.Lex(); // Eat the token;
2632 if (Parser.getTok().isNot(AsmToken::RBrac))
2633 Error(Parser.getTok().getLoc(), "']' expected");
2634 Parser.Lex(); // Eat the ']'.
2635 return MatchOperand_Success;
2636 }
2637 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002638 return MatchOperand_ParseFail;
2639 }
2640 LaneKind = NoLanes;
2641 return MatchOperand_Success;
2642}
2643
Jim Grosbach862019c2011-10-18 23:02:30 +00002644// parse a vector register list
2645ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2646parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002647 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002648 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002649 SMLoc S = Parser.getTok().getLoc();
2650 // As an extension (to match gas), support a plain D register or Q register
2651 // (without encosing curly braces) as a single or double entry list,
2652 // respectively.
2653 if (Parser.getTok().is(AsmToken::Identifier)) {
2654 int Reg = tryParseRegister();
2655 if (Reg == -1)
2656 return MatchOperand_NoMatch;
2657 SMLoc E = Parser.getTok().getLoc();
2658 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002659 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002660 if (Res != MatchOperand_Success)
2661 return Res;
2662 switch (LaneKind) {
2663 default:
2664 assert(0 && "unexpected lane kind!");
2665 case NoLanes:
2666 E = Parser.getTok().getLoc();
2667 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2668 break;
2669 case AllLanes:
2670 E = Parser.getTok().getLoc();
2671 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2672 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002673 case IndexedLane:
2674 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2675 LaneIndex, S,E));
2676 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002677 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002678 return MatchOperand_Success;
2679 }
2680 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2681 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002682 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002683 if (Res != MatchOperand_Success)
2684 return Res;
2685 switch (LaneKind) {
2686 default:
2687 assert(0 && "unexpected lane kind!");
2688 case NoLanes:
2689 E = Parser.getTok().getLoc();
2690 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2691 break;
2692 case AllLanes:
2693 E = Parser.getTok().getLoc();
2694 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2695 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002696 case IndexedLane:
2697 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2698 LaneIndex, S,E));
2699 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002700 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002701 return MatchOperand_Success;
2702 }
2703 Error(S, "vector register expected");
2704 return MatchOperand_ParseFail;
2705 }
2706
2707 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002708 return MatchOperand_NoMatch;
2709
Jim Grosbach862019c2011-10-18 23:02:30 +00002710 Parser.Lex(); // Eat '{' token.
2711 SMLoc RegLoc = Parser.getTok().getLoc();
2712
2713 int Reg = tryParseRegister();
2714 if (Reg == -1) {
2715 Error(RegLoc, "register expected");
2716 return MatchOperand_ParseFail;
2717 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002718 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002719 unsigned FirstReg = Reg;
2720 // The list is of D registers, but we also allow Q regs and just interpret
2721 // them as the two D sub-registers.
2722 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2723 FirstReg = Reg = getDRegFromQReg(Reg);
2724 ++Reg;
2725 ++Count;
2726 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002727 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002728 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002729
Jim Grosbache43862b2011-11-15 23:19:15 +00002730 while (Parser.getTok().is(AsmToken::Comma) ||
2731 Parser.getTok().is(AsmToken::Minus)) {
2732 if (Parser.getTok().is(AsmToken::Minus)) {
2733 Parser.Lex(); // Eat the minus.
2734 SMLoc EndLoc = Parser.getTok().getLoc();
2735 int EndReg = tryParseRegister();
2736 if (EndReg == -1) {
2737 Error(EndLoc, "register expected");
2738 return MatchOperand_ParseFail;
2739 }
2740 // Allow Q regs and just interpret them as the two D sub-registers.
2741 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2742 EndReg = getDRegFromQReg(EndReg) + 1;
2743 // If the register is the same as the start reg, there's nothing
2744 // more to do.
2745 if (Reg == EndReg)
2746 continue;
2747 // The register must be in the same register class as the first.
2748 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2749 Error(EndLoc, "invalid register in register list");
2750 return MatchOperand_ParseFail;
2751 }
2752 // Ranges must go from low to high.
2753 if (Reg > EndReg) {
2754 Error(EndLoc, "bad range in register list");
2755 return MatchOperand_ParseFail;
2756 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002757 // Parse the lane specifier if present.
2758 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002759 unsigned NextLaneIndex;
2760 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002761 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002762 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002763 Error(EndLoc, "mismatched lane index in register list");
2764 return MatchOperand_ParseFail;
2765 }
2766 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002767
2768 // Add all the registers in the range to the register list.
2769 Count += EndReg - Reg;
2770 Reg = EndReg;
2771 continue;
2772 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002773 Parser.Lex(); // Eat the comma.
2774 RegLoc = Parser.getTok().getLoc();
2775 int OldReg = Reg;
2776 Reg = tryParseRegister();
2777 if (Reg == -1) {
2778 Error(RegLoc, "register expected");
2779 return MatchOperand_ParseFail;
2780 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002781 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002782 // It's OK to use the enumeration values directly here rather, as the
2783 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002784 //
2785 // The list is of D registers, but we also allow Q regs and just interpret
2786 // them as the two D sub-registers.
2787 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2788 Reg = getDRegFromQReg(Reg);
2789 if (Reg != OldReg + 1) {
2790 Error(RegLoc, "non-contiguous register range");
2791 return MatchOperand_ParseFail;
2792 }
2793 ++Reg;
2794 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002795 // Parse the lane specifier if present.
2796 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002797 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002798 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002799 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002800 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002801 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002802 Error(EndLoc, "mismatched lane index in register list");
2803 return MatchOperand_ParseFail;
2804 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002805 continue;
2806 }
2807 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002808 if (Reg != OldReg + 1) {
2809 Error(RegLoc, "non-contiguous register range");
2810 return MatchOperand_ParseFail;
2811 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002812 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002813 // Parse the lane specifier if present.
2814 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002815 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002816 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002817 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002818 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002819 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002820 Error(EndLoc, "mismatched lane index in register list");
2821 return MatchOperand_ParseFail;
2822 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002823 }
2824
2825 SMLoc E = Parser.getTok().getLoc();
2826 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2827 Error(E, "'}' expected");
2828 return MatchOperand_ParseFail;
2829 }
2830 Parser.Lex(); // Eat '}' token.
2831
Jim Grosbach98b05a52011-11-30 01:09:44 +00002832 switch (LaneKind) {
2833 default:
2834 assert(0 && "unexpected lane kind in register list.");
2835 case NoLanes:
2836 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2837 break;
2838 case AllLanes:
2839 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2840 S, E));
2841 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002842 case IndexedLane:
2843 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2844 LaneIndex, S, E));
2845 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002846 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002847 return MatchOperand_Success;
2848}
2849
Jim Grosbach43904292011-07-25 20:14:50 +00002850/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002851ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002852parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002853 SMLoc S = Parser.getTok().getLoc();
2854 const AsmToken &Tok = Parser.getTok();
2855 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2856 StringRef OptStr = Tok.getString();
2857
2858 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2859 .Case("sy", ARM_MB::SY)
2860 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002861 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002862 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002863 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002864 .Case("ishst", ARM_MB::ISHST)
2865 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002866 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002867 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002868 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002869 .Case("osh", ARM_MB::OSH)
2870 .Case("oshst", ARM_MB::OSHST)
2871 .Default(~0U);
2872
2873 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002874 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002875
2876 Parser.Lex(); // Eat identifier token.
2877 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002878 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002879}
2880
Jim Grosbach43904292011-07-25 20:14:50 +00002881/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002882ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002883parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002884 SMLoc S = Parser.getTok().getLoc();
2885 const AsmToken &Tok = Parser.getTok();
2886 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2887 StringRef IFlagsStr = Tok.getString();
2888
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002889 // An iflags string of "none" is interpreted to mean that none of the AIF
2890 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002891 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002892 if (IFlagsStr != "none") {
2893 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2894 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2895 .Case("a", ARM_PROC::A)
2896 .Case("i", ARM_PROC::I)
2897 .Case("f", ARM_PROC::F)
2898 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002899
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002900 // If some specific iflag is already set, it means that some letter is
2901 // present more than once, this is not acceptable.
2902 if (Flag == ~0U || (IFlags & Flag))
2903 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002904
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002905 IFlags |= Flag;
2906 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002907 }
2908
2909 Parser.Lex(); // Eat identifier token.
2910 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2911 return MatchOperand_Success;
2912}
2913
Jim Grosbach43904292011-07-25 20:14:50 +00002914/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002915ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002916parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002917 SMLoc S = Parser.getTok().getLoc();
2918 const AsmToken &Tok = Parser.getTok();
2919 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2920 StringRef Mask = Tok.getString();
2921
James Molloyacad68d2011-09-28 14:21:38 +00002922 if (isMClass()) {
2923 // See ARMv6-M 10.1.1
2924 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
2925 .Case("apsr", 0)
2926 .Case("iapsr", 1)
2927 .Case("eapsr", 2)
2928 .Case("xpsr", 3)
2929 .Case("ipsr", 5)
2930 .Case("epsr", 6)
2931 .Case("iepsr", 7)
2932 .Case("msp", 8)
2933 .Case("psp", 9)
2934 .Case("primask", 16)
2935 .Case("basepri", 17)
2936 .Case("basepri_max", 18)
2937 .Case("faultmask", 19)
2938 .Case("control", 20)
2939 .Default(~0U);
2940
2941 if (FlagsVal == ~0U)
2942 return MatchOperand_NoMatch;
2943
2944 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
2945 // basepri, basepri_max and faultmask only valid for V7m.
2946 return MatchOperand_NoMatch;
2947
2948 Parser.Lex(); // Eat identifier token.
2949 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
2950 return MatchOperand_Success;
2951 }
2952
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002953 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
2954 size_t Start = 0, Next = Mask.find('_');
2955 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00002956 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002957 if (Next != StringRef::npos)
2958 Flags = Mask.slice(Next+1, Mask.size());
2959
2960 // FlagsVal contains the complete mask:
2961 // 3-0: Mask
2962 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
2963 unsigned FlagsVal = 0;
2964
2965 if (SpecReg == "apsr") {
2966 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00002967 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002968 .Case("g", 0x4) // same as CPSR_s
2969 .Case("nzcvqg", 0xc) // same as CPSR_fs
2970 .Default(~0U);
2971
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002972 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002973 if (!Flags.empty())
2974 return MatchOperand_NoMatch;
2975 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00002976 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00002977 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002978 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00002979 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
2980 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002981 for (int i = 0, e = Flags.size(); i != e; ++i) {
2982 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
2983 .Case("c", 1)
2984 .Case("x", 2)
2985 .Case("s", 4)
2986 .Case("f", 8)
2987 .Default(~0U);
2988
2989 // If some specific flag is already set, it means that some letter is
2990 // present more than once, this is not acceptable.
2991 if (FlagsVal == ~0U || (FlagsVal & Flag))
2992 return MatchOperand_NoMatch;
2993 FlagsVal |= Flag;
2994 }
2995 } else // No match for special register.
2996 return MatchOperand_NoMatch;
2997
Owen Anderson7784f1d2011-10-21 18:43:28 +00002998 // Special register without flags is NOT equivalent to "fc" flags.
2999 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3000 // two lines would enable gas compatibility at the expense of breaking
3001 // round-tripping.
3002 //
3003 // if (!FlagsVal)
3004 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003005
3006 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3007 if (SpecReg == "spsr")
3008 FlagsVal |= 16;
3009
3010 Parser.Lex(); // Eat identifier token.
3011 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3012 return MatchOperand_Success;
3013}
3014
Jim Grosbachf6c05252011-07-21 17:23:04 +00003015ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3016parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3017 int Low, int High) {
3018 const AsmToken &Tok = Parser.getTok();
3019 if (Tok.isNot(AsmToken::Identifier)) {
3020 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3021 return MatchOperand_ParseFail;
3022 }
3023 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003024 std::string LowerOp = Op.lower();
3025 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003026 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3027 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3028 return MatchOperand_ParseFail;
3029 }
3030 Parser.Lex(); // Eat shift type token.
3031
3032 // There must be a '#' and a shift amount.
3033 if (Parser.getTok().isNot(AsmToken::Hash)) {
3034 Error(Parser.getTok().getLoc(), "'#' expected");
3035 return MatchOperand_ParseFail;
3036 }
3037 Parser.Lex(); // Eat hash token.
3038
3039 const MCExpr *ShiftAmount;
3040 SMLoc Loc = Parser.getTok().getLoc();
3041 if (getParser().ParseExpression(ShiftAmount)) {
3042 Error(Loc, "illegal expression");
3043 return MatchOperand_ParseFail;
3044 }
3045 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3046 if (!CE) {
3047 Error(Loc, "constant expression expected");
3048 return MatchOperand_ParseFail;
3049 }
3050 int Val = CE->getValue();
3051 if (Val < Low || Val > High) {
3052 Error(Loc, "immediate value out of range");
3053 return MatchOperand_ParseFail;
3054 }
3055
3056 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3057
3058 return MatchOperand_Success;
3059}
3060
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003061ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3062parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3063 const AsmToken &Tok = Parser.getTok();
3064 SMLoc S = Tok.getLoc();
3065 if (Tok.isNot(AsmToken::Identifier)) {
3066 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3067 return MatchOperand_ParseFail;
3068 }
3069 int Val = StringSwitch<int>(Tok.getString())
3070 .Case("be", 1)
3071 .Case("le", 0)
3072 .Default(-1);
3073 Parser.Lex(); // Eat the token.
3074
3075 if (Val == -1) {
3076 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3077 return MatchOperand_ParseFail;
3078 }
3079 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3080 getContext()),
3081 S, Parser.getTok().getLoc()));
3082 return MatchOperand_Success;
3083}
3084
Jim Grosbach580f4a92011-07-25 22:20:28 +00003085/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3086/// instructions. Legal values are:
3087/// lsl #n 'n' in [0,31]
3088/// asr #n 'n' in [1,32]
3089/// n == 32 encoded as n == 0.
3090ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3091parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3092 const AsmToken &Tok = Parser.getTok();
3093 SMLoc S = Tok.getLoc();
3094 if (Tok.isNot(AsmToken::Identifier)) {
3095 Error(S, "shift operator 'asr' or 'lsl' expected");
3096 return MatchOperand_ParseFail;
3097 }
3098 StringRef ShiftName = Tok.getString();
3099 bool isASR;
3100 if (ShiftName == "lsl" || ShiftName == "LSL")
3101 isASR = false;
3102 else if (ShiftName == "asr" || ShiftName == "ASR")
3103 isASR = true;
3104 else {
3105 Error(S, "shift operator 'asr' or 'lsl' expected");
3106 return MatchOperand_ParseFail;
3107 }
3108 Parser.Lex(); // Eat the operator.
3109
3110 // A '#' and a shift amount.
3111 if (Parser.getTok().isNot(AsmToken::Hash)) {
3112 Error(Parser.getTok().getLoc(), "'#' expected");
3113 return MatchOperand_ParseFail;
3114 }
3115 Parser.Lex(); // Eat hash token.
3116
3117 const MCExpr *ShiftAmount;
3118 SMLoc E = Parser.getTok().getLoc();
3119 if (getParser().ParseExpression(ShiftAmount)) {
3120 Error(E, "malformed shift expression");
3121 return MatchOperand_ParseFail;
3122 }
3123 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3124 if (!CE) {
3125 Error(E, "shift amount must be an immediate");
3126 return MatchOperand_ParseFail;
3127 }
3128
3129 int64_t Val = CE->getValue();
3130 if (isASR) {
3131 // Shift amount must be in [1,32]
3132 if (Val < 1 || Val > 32) {
3133 Error(E, "'asr' shift amount must be in range [1,32]");
3134 return MatchOperand_ParseFail;
3135 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003136 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3137 if (isThumb() && Val == 32) {
3138 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3139 return MatchOperand_ParseFail;
3140 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003141 if (Val == 32) Val = 0;
3142 } else {
3143 // Shift amount must be in [1,32]
3144 if (Val < 0 || Val > 31) {
3145 Error(E, "'lsr' shift amount must be in range [0,31]");
3146 return MatchOperand_ParseFail;
3147 }
3148 }
3149
3150 E = Parser.getTok().getLoc();
3151 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3152
3153 return MatchOperand_Success;
3154}
3155
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003156/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3157/// of instructions. Legal values are:
3158/// ror #n 'n' in {0, 8, 16, 24}
3159ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3160parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3161 const AsmToken &Tok = Parser.getTok();
3162 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003163 if (Tok.isNot(AsmToken::Identifier))
3164 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003165 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003166 if (ShiftName != "ror" && ShiftName != "ROR")
3167 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003168 Parser.Lex(); // Eat the operator.
3169
3170 // A '#' and a rotate amount.
3171 if (Parser.getTok().isNot(AsmToken::Hash)) {
3172 Error(Parser.getTok().getLoc(), "'#' expected");
3173 return MatchOperand_ParseFail;
3174 }
3175 Parser.Lex(); // Eat hash token.
3176
3177 const MCExpr *ShiftAmount;
3178 SMLoc E = Parser.getTok().getLoc();
3179 if (getParser().ParseExpression(ShiftAmount)) {
3180 Error(E, "malformed rotate expression");
3181 return MatchOperand_ParseFail;
3182 }
3183 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3184 if (!CE) {
3185 Error(E, "rotate amount must be an immediate");
3186 return MatchOperand_ParseFail;
3187 }
3188
3189 int64_t Val = CE->getValue();
3190 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3191 // normally, zero is represented in asm by omitting the rotate operand
3192 // entirely.
3193 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3194 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3195 return MatchOperand_ParseFail;
3196 }
3197
3198 E = Parser.getTok().getLoc();
3199 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3200
3201 return MatchOperand_Success;
3202}
3203
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003204ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3205parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3206 SMLoc S = Parser.getTok().getLoc();
3207 // The bitfield descriptor is really two operands, the LSB and the width.
3208 if (Parser.getTok().isNot(AsmToken::Hash)) {
3209 Error(Parser.getTok().getLoc(), "'#' expected");
3210 return MatchOperand_ParseFail;
3211 }
3212 Parser.Lex(); // Eat hash token.
3213
3214 const MCExpr *LSBExpr;
3215 SMLoc E = Parser.getTok().getLoc();
3216 if (getParser().ParseExpression(LSBExpr)) {
3217 Error(E, "malformed immediate expression");
3218 return MatchOperand_ParseFail;
3219 }
3220 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3221 if (!CE) {
3222 Error(E, "'lsb' operand must be an immediate");
3223 return MatchOperand_ParseFail;
3224 }
3225
3226 int64_t LSB = CE->getValue();
3227 // The LSB must be in the range [0,31]
3228 if (LSB < 0 || LSB > 31) {
3229 Error(E, "'lsb' operand must be in the range [0,31]");
3230 return MatchOperand_ParseFail;
3231 }
3232 E = Parser.getTok().getLoc();
3233
3234 // Expect another immediate operand.
3235 if (Parser.getTok().isNot(AsmToken::Comma)) {
3236 Error(Parser.getTok().getLoc(), "too few operands");
3237 return MatchOperand_ParseFail;
3238 }
3239 Parser.Lex(); // Eat hash token.
3240 if (Parser.getTok().isNot(AsmToken::Hash)) {
3241 Error(Parser.getTok().getLoc(), "'#' expected");
3242 return MatchOperand_ParseFail;
3243 }
3244 Parser.Lex(); // Eat hash token.
3245
3246 const MCExpr *WidthExpr;
3247 if (getParser().ParseExpression(WidthExpr)) {
3248 Error(E, "malformed immediate expression");
3249 return MatchOperand_ParseFail;
3250 }
3251 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3252 if (!CE) {
3253 Error(E, "'width' operand must be an immediate");
3254 return MatchOperand_ParseFail;
3255 }
3256
3257 int64_t Width = CE->getValue();
3258 // The LSB must be in the range [1,32-lsb]
3259 if (Width < 1 || Width > 32 - LSB) {
3260 Error(E, "'width' operand must be in the range [1,32-lsb]");
3261 return MatchOperand_ParseFail;
3262 }
3263 E = Parser.getTok().getLoc();
3264
3265 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3266
3267 return MatchOperand_Success;
3268}
3269
Jim Grosbach7ce05792011-08-03 23:50:40 +00003270ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3271parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3272 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003273 // postidx_reg := '+' register {, shift}
3274 // | '-' register {, shift}
3275 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003276
3277 // This method must return MatchOperand_NoMatch without consuming any tokens
3278 // in the case where there is no match, as other alternatives take other
3279 // parse methods.
3280 AsmToken Tok = Parser.getTok();
3281 SMLoc S = Tok.getLoc();
3282 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003283 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003284 int Reg = -1;
3285 if (Tok.is(AsmToken::Plus)) {
3286 Parser.Lex(); // Eat the '+' token.
3287 haveEaten = true;
3288 } else if (Tok.is(AsmToken::Minus)) {
3289 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003290 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003291 haveEaten = true;
3292 }
3293 if (Parser.getTok().is(AsmToken::Identifier))
3294 Reg = tryParseRegister();
3295 if (Reg == -1) {
3296 if (!haveEaten)
3297 return MatchOperand_NoMatch;
3298 Error(Parser.getTok().getLoc(), "register expected");
3299 return MatchOperand_ParseFail;
3300 }
3301 SMLoc E = Parser.getTok().getLoc();
3302
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003303 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3304 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003305 if (Parser.getTok().is(AsmToken::Comma)) {
3306 Parser.Lex(); // Eat the ','.
3307 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3308 return MatchOperand_ParseFail;
3309 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003310
3311 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3312 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003313
3314 return MatchOperand_Success;
3315}
3316
Jim Grosbach251bf252011-08-10 21:56:18 +00003317ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3318parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3319 // Check for a post-index addressing register operand. Specifically:
3320 // am3offset := '+' register
3321 // | '-' register
3322 // | register
3323 // | # imm
3324 // | # + imm
3325 // | # - imm
3326
3327 // This method must return MatchOperand_NoMatch without consuming any tokens
3328 // in the case where there is no match, as other alternatives take other
3329 // parse methods.
3330 AsmToken Tok = Parser.getTok();
3331 SMLoc S = Tok.getLoc();
3332
3333 // Do immediates first, as we always parse those if we have a '#'.
3334 if (Parser.getTok().is(AsmToken::Hash)) {
3335 Parser.Lex(); // Eat the '#'.
3336 // Explicitly look for a '-', as we need to encode negative zero
3337 // differently.
3338 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3339 const MCExpr *Offset;
3340 if (getParser().ParseExpression(Offset))
3341 return MatchOperand_ParseFail;
3342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3343 if (!CE) {
3344 Error(S, "constant expression expected");
3345 return MatchOperand_ParseFail;
3346 }
3347 SMLoc E = Tok.getLoc();
3348 // Negative zero is encoded as the flag value INT32_MIN.
3349 int32_t Val = CE->getValue();
3350 if (isNegative && Val == 0)
3351 Val = INT32_MIN;
3352
3353 Operands.push_back(
3354 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3355
3356 return MatchOperand_Success;
3357 }
3358
3359
3360 bool haveEaten = false;
3361 bool isAdd = true;
3362 int Reg = -1;
3363 if (Tok.is(AsmToken::Plus)) {
3364 Parser.Lex(); // Eat the '+' token.
3365 haveEaten = true;
3366 } else if (Tok.is(AsmToken::Minus)) {
3367 Parser.Lex(); // Eat the '-' token.
3368 isAdd = false;
3369 haveEaten = true;
3370 }
3371 if (Parser.getTok().is(AsmToken::Identifier))
3372 Reg = tryParseRegister();
3373 if (Reg == -1) {
3374 if (!haveEaten)
3375 return MatchOperand_NoMatch;
3376 Error(Parser.getTok().getLoc(), "register expected");
3377 return MatchOperand_ParseFail;
3378 }
3379 SMLoc E = Parser.getTok().getLoc();
3380
3381 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3382 0, S, E));
3383
3384 return MatchOperand_Success;
3385}
3386
Jim Grosbacha77295d2011-09-08 22:07:06 +00003387/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3388/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3389/// when they refer multiple MIOperands inside a single one.
3390bool ARMAsmParser::
3391cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3392 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3393 // Rt, Rt2
3394 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3395 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3396 // Create a writeback register dummy placeholder.
3397 Inst.addOperand(MCOperand::CreateReg(0));
3398 // addr
3399 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3400 // pred
3401 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3402 return true;
3403}
3404
3405/// cvtT2StrdPre - Convert parsed operands to MCInst.
3406/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3407/// when they refer multiple MIOperands inside a single one.
3408bool ARMAsmParser::
3409cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3410 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3411 // Create a writeback register dummy placeholder.
3412 Inst.addOperand(MCOperand::CreateReg(0));
3413 // Rt, Rt2
3414 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3415 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3416 // addr
3417 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3418 // pred
3419 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3420 return true;
3421}
3422
Jim Grosbacheeec0252011-09-08 00:39:19 +00003423/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3424/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3425/// when they refer multiple MIOperands inside a single one.
3426bool ARMAsmParser::
3427cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3428 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3429 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3430
3431 // Create a writeback register dummy placeholder.
3432 Inst.addOperand(MCOperand::CreateImm(0));
3433
3434 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3435 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3436 return true;
3437}
3438
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003439/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3440/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3441/// when they refer multiple MIOperands inside a single one.
3442bool ARMAsmParser::
3443cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3444 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3445 // Create a writeback register dummy placeholder.
3446 Inst.addOperand(MCOperand::CreateImm(0));
3447 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3448 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3449 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3450 return true;
3451}
3452
Jim Grosbach1355cf12011-07-26 17:10:22 +00003453/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003454/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3455/// when they refer multiple MIOperands inside a single one.
3456bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003457cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003458 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3459 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3460
3461 // Create a writeback register dummy placeholder.
3462 Inst.addOperand(MCOperand::CreateImm(0));
3463
Jim Grosbach7ce05792011-08-03 23:50:40 +00003464 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003465 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3466 return true;
3467}
3468
Owen Anderson9ab0f252011-08-26 20:43:14 +00003469/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3470/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3471/// when they refer multiple MIOperands inside a single one.
3472bool ARMAsmParser::
3473cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3474 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3475 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3476
3477 // Create a writeback register dummy placeholder.
3478 Inst.addOperand(MCOperand::CreateImm(0));
3479
3480 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3481 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3482 return true;
3483}
3484
3485
Jim Grosbach548340c2011-08-11 19:22:40 +00003486/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3487/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3488/// when they refer multiple MIOperands inside a single one.
3489bool ARMAsmParser::
3490cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3491 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3492 // Create a writeback register dummy placeholder.
3493 Inst.addOperand(MCOperand::CreateImm(0));
3494 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3495 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3496 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3497 return true;
3498}
3499
Jim Grosbach1355cf12011-07-26 17:10:22 +00003500/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003501/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3502/// when they refer multiple MIOperands inside a single one.
3503bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003504cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003505 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3506 // Create a writeback register dummy placeholder.
3507 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003508 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3509 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3510 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003511 return true;
3512}
3513
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003514/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3515/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3516/// when they refer multiple MIOperands inside a single one.
3517bool ARMAsmParser::
3518cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3519 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3520 // Create a writeback register dummy placeholder.
3521 Inst.addOperand(MCOperand::CreateImm(0));
3522 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3523 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3524 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3525 return true;
3526}
3527
Jim Grosbach7ce05792011-08-03 23:50:40 +00003528/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3529/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3530/// when they refer multiple MIOperands inside a single one.
3531bool ARMAsmParser::
3532cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3533 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3534 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003535 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003536 // Create a writeback register dummy placeholder.
3537 Inst.addOperand(MCOperand::CreateImm(0));
3538 // addr
3539 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3540 // offset
3541 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3542 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003543 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3544 return true;
3545}
3546
Jim Grosbach7ce05792011-08-03 23:50:40 +00003547/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003548/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3549/// when they refer multiple MIOperands inside a single one.
3550bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003551cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3552 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3553 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003554 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003555 // Create a writeback register dummy placeholder.
3556 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003557 // addr
3558 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3559 // offset
3560 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3561 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003562 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3563 return true;
3564}
3565
Jim Grosbach7ce05792011-08-03 23:50:40 +00003566/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003567/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3568/// when they refer multiple MIOperands inside a single one.
3569bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003570cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3571 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003572 // Create a writeback register dummy placeholder.
3573 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003574 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003575 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003576 // addr
3577 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3578 // offset
3579 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3580 // pred
3581 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3582 return true;
3583}
3584
3585/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3586/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3587/// when they refer multiple MIOperands inside a single one.
3588bool ARMAsmParser::
3589cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3590 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3591 // Create a writeback register dummy placeholder.
3592 Inst.addOperand(MCOperand::CreateImm(0));
3593 // Rt
3594 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3595 // addr
3596 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3597 // offset
3598 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3599 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003600 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3601 return true;
3602}
3603
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003604/// cvtLdrdPre - Convert parsed operands to MCInst.
3605/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3606/// when they refer multiple MIOperands inside a single one.
3607bool ARMAsmParser::
3608cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3609 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3610 // Rt, Rt2
3611 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3612 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3613 // Create a writeback register dummy placeholder.
3614 Inst.addOperand(MCOperand::CreateImm(0));
3615 // addr
3616 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3617 // pred
3618 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3619 return true;
3620}
3621
Jim Grosbach14605d12011-08-11 20:28:23 +00003622/// cvtStrdPre - Convert parsed operands to MCInst.
3623/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3624/// when they refer multiple MIOperands inside a single one.
3625bool ARMAsmParser::
3626cvtStrdPre(MCInst &Inst, unsigned Opcode,
3627 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3628 // Create a writeback register dummy placeholder.
3629 Inst.addOperand(MCOperand::CreateImm(0));
3630 // Rt, Rt2
3631 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3632 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3633 // addr
3634 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3635 // pred
3636 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3637 return true;
3638}
3639
Jim Grosbach623a4542011-08-10 22:42:16 +00003640/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3641/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3642/// when they refer multiple MIOperands inside a single one.
3643bool ARMAsmParser::
3644cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3645 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3646 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3647 // Create a writeback register dummy placeholder.
3648 Inst.addOperand(MCOperand::CreateImm(0));
3649 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3650 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3651 return true;
3652}
3653
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003654/// cvtThumbMultiple- Convert parsed operands to MCInst.
3655/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3656/// when they refer multiple MIOperands inside a single one.
3657bool ARMAsmParser::
3658cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3659 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3660 // The second source operand must be the same register as the destination
3661 // operand.
3662 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003663 (((ARMOperand*)Operands[3])->getReg() !=
3664 ((ARMOperand*)Operands[5])->getReg()) &&
3665 (((ARMOperand*)Operands[3])->getReg() !=
3666 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003667 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003668 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003669 return false;
3670 }
3671 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3672 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003673 // If we have a three-operand form, make sure to set Rn to be the operand
3674 // that isn't the same as Rd.
3675 unsigned RegOp = 4;
3676 if (Operands.size() == 6 &&
3677 ((ARMOperand*)Operands[4])->getReg() ==
3678 ((ARMOperand*)Operands[3])->getReg())
3679 RegOp = 5;
3680 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3681 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003682 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3683
3684 return true;
3685}
Jim Grosbach623a4542011-08-10 22:42:16 +00003686
Jim Grosbach12431322011-10-24 22:16:58 +00003687bool ARMAsmParser::
3688cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3689 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3690 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003691 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003692 // Create a writeback register dummy placeholder.
3693 Inst.addOperand(MCOperand::CreateImm(0));
3694 // Vn
3695 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3696 // pred
3697 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3698 return true;
3699}
3700
3701bool ARMAsmParser::
3702cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3703 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3704 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003705 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003706 // Create a writeback register dummy placeholder.
3707 Inst.addOperand(MCOperand::CreateImm(0));
3708 // Vn
3709 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3710 // Vm
3711 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3712 // pred
3713 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3714 return true;
3715}
3716
Jim Grosbach4334e032011-10-31 21:50:31 +00003717bool ARMAsmParser::
3718cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3719 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3720 // Create a writeback register dummy placeholder.
3721 Inst.addOperand(MCOperand::CreateImm(0));
3722 // Vn
3723 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3724 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003725 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003726 // pred
3727 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3728 return true;
3729}
3730
3731bool ARMAsmParser::
3732cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3733 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3734 // Create a writeback register dummy placeholder.
3735 Inst.addOperand(MCOperand::CreateImm(0));
3736 // Vn
3737 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3738 // Vm
3739 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3740 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003741 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003742 // pred
3743 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3744 return true;
3745}
3746
Bill Wendlinge7176102010-11-06 22:36:58 +00003747/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003748/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003749bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003750parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003751 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003752 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003753 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003754 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003755 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003756
Sean Callanan18b83232010-01-19 21:44:56 +00003757 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003758 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003759 if (BaseRegNum == -1)
3760 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003761
Daniel Dunbar05710932011-01-18 05:34:17 +00003762 // The next token must either be a comma or a closing bracket.
3763 const AsmToken &Tok = Parser.getTok();
3764 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003765 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003766
Jim Grosbach7ce05792011-08-03 23:50:40 +00003767 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003768 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003769 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003770
Jim Grosbach7ce05792011-08-03 23:50:40 +00003771 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003772 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003773
Jim Grosbachfb12f352011-09-19 18:42:21 +00003774 // If there's a pre-indexing writeback marker, '!', just add it as a token
3775 // operand. It's rather odd, but syntactically valid.
3776 if (Parser.getTok().is(AsmToken::Exclaim)) {
3777 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3778 Parser.Lex(); // Eat the '!'.
3779 }
3780
Jim Grosbach7ce05792011-08-03 23:50:40 +00003781 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003782 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003783
Jim Grosbach7ce05792011-08-03 23:50:40 +00003784 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3785 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003786
Jim Grosbach57dcb852011-10-11 17:29:55 +00003787 // If we have a ':', it's an alignment specifier.
3788 if (Parser.getTok().is(AsmToken::Colon)) {
3789 Parser.Lex(); // Eat the ':'.
3790 E = Parser.getTok().getLoc();
3791
3792 const MCExpr *Expr;
3793 if (getParser().ParseExpression(Expr))
3794 return true;
3795
3796 // The expression has to be a constant. Memory references with relocations
3797 // don't come through here, as they use the <label> forms of the relevant
3798 // instructions.
3799 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3800 if (!CE)
3801 return Error (E, "constant expression expected");
3802
3803 unsigned Align = 0;
3804 switch (CE->getValue()) {
3805 default:
3806 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3807 case 64: Align = 8; break;
3808 case 128: Align = 16; break;
3809 case 256: Align = 32; break;
3810 }
3811
3812 // Now we should have the closing ']'
3813 E = Parser.getTok().getLoc();
3814 if (Parser.getTok().isNot(AsmToken::RBrac))
3815 return Error(E, "']' expected");
3816 Parser.Lex(); // Eat right bracket token.
3817
3818 // Don't worry about range checking the value here. That's handled by
3819 // the is*() predicates.
3820 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3821 ARM_AM::no_shift, 0, Align,
3822 false, S, E));
3823
3824 // If there's a pre-indexing writeback marker, '!', just add it as a token
3825 // operand.
3826 if (Parser.getTok().is(AsmToken::Exclaim)) {
3827 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3828 Parser.Lex(); // Eat the '!'.
3829 }
3830
3831 return false;
3832 }
3833
3834 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003835 // offset. Be friendly and also accept a plain integer (without a leading
3836 // hash) for gas compatibility.
3837 if (Parser.getTok().is(AsmToken::Hash) ||
3838 Parser.getTok().is(AsmToken::Integer)) {
3839 if (Parser.getTok().is(AsmToken::Hash))
3840 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003841 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003842
Owen Anderson0da10cf2011-08-29 19:36:44 +00003843 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003844 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003845 if (getParser().ParseExpression(Offset))
3846 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003847
3848 // The expression has to be a constant. Memory references with relocations
3849 // don't come through here, as they use the <label> forms of the relevant
3850 // instructions.
3851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3852 if (!CE)
3853 return Error (E, "constant expression expected");
3854
Owen Anderson0da10cf2011-08-29 19:36:44 +00003855 // If the constant was #-0, represent it as INT32_MIN.
3856 int32_t Val = CE->getValue();
3857 if (isNegative && Val == 0)
3858 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3859
Jim Grosbach7ce05792011-08-03 23:50:40 +00003860 // Now we should have the closing ']'
3861 E = Parser.getTok().getLoc();
3862 if (Parser.getTok().isNot(AsmToken::RBrac))
3863 return Error(E, "']' expected");
3864 Parser.Lex(); // Eat right bracket token.
3865
3866 // Don't worry about range checking the value here. That's handled by
3867 // the is*() predicates.
3868 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003869 ARM_AM::no_shift, 0, 0,
3870 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003871
3872 // If there's a pre-indexing writeback marker, '!', just add it as a token
3873 // operand.
3874 if (Parser.getTok().is(AsmToken::Exclaim)) {
3875 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3876 Parser.Lex(); // Eat the '!'.
3877 }
3878
3879 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003880 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003881
3882 // The register offset is optionally preceded by a '+' or '-'
3883 bool isNegative = false;
3884 if (Parser.getTok().is(AsmToken::Minus)) {
3885 isNegative = true;
3886 Parser.Lex(); // Eat the '-'.
3887 } else if (Parser.getTok().is(AsmToken::Plus)) {
3888 // Nothing to do.
3889 Parser.Lex(); // Eat the '+'.
3890 }
3891
3892 E = Parser.getTok().getLoc();
3893 int OffsetRegNum = tryParseRegister();
3894 if (OffsetRegNum == -1)
3895 return Error(E, "register expected");
3896
3897 // If there's a shift operator, handle it.
3898 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003899 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003900 if (Parser.getTok().is(AsmToken::Comma)) {
3901 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003902 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003903 return true;
3904 }
3905
3906 // Now we should have the closing ']'
3907 E = Parser.getTok().getLoc();
3908 if (Parser.getTok().isNot(AsmToken::RBrac))
3909 return Error(E, "']' expected");
3910 Parser.Lex(); // Eat right bracket token.
3911
3912 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003913 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00003914 S, E));
3915
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003916 // If there's a pre-indexing writeback marker, '!', just add it as a token
3917 // operand.
3918 if (Parser.getTok().is(AsmToken::Exclaim)) {
3919 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3920 Parser.Lex(); // Eat the '!'.
3921 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003922
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003923 return false;
3924}
3925
Jim Grosbach7ce05792011-08-03 23:50:40 +00003926/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003927/// ( lsl | lsr | asr | ror ) , # shift_amount
3928/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00003929/// return true if it parses a shift otherwise it returns false.
3930bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
3931 unsigned &Amount) {
3932 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00003933 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003934 if (Tok.isNot(AsmToken::Identifier))
3935 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00003936 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00003937 if (ShiftName == "lsl" || ShiftName == "LSL" ||
3938 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00003939 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003940 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00003941 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003942 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00003943 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003944 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00003945 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003946 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00003947 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003948 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00003949 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00003950 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003951
Jim Grosbach7ce05792011-08-03 23:50:40 +00003952 // rrx stands alone.
3953 Amount = 0;
3954 if (St != ARM_AM::rrx) {
3955 Loc = Parser.getTok().getLoc();
3956 // A '#' and a shift amount.
3957 const AsmToken &HashTok = Parser.getTok();
3958 if (HashTok.isNot(AsmToken::Hash))
3959 return Error(HashTok.getLoc(), "'#' expected");
3960 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003961
Jim Grosbach7ce05792011-08-03 23:50:40 +00003962 const MCExpr *Expr;
3963 if (getParser().ParseExpression(Expr))
3964 return true;
3965 // Range check the immediate.
3966 // lsl, ror: 0 <= imm <= 31
3967 // lsr, asr: 0 <= imm <= 32
3968 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3969 if (!CE)
3970 return Error(Loc, "shift amount must be an immediate");
3971 int64_t Imm = CE->getValue();
3972 if (Imm < 0 ||
3973 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
3974 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
3975 return Error(Loc, "immediate shift value out of range");
3976 Amount = Imm;
3977 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003978
3979 return false;
3980}
3981
Jim Grosbach9d390362011-10-03 23:38:36 +00003982/// parseFPImm - A floating point immediate expression operand.
3983ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3984parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3985 SMLoc S = Parser.getTok().getLoc();
3986
3987 if (Parser.getTok().isNot(AsmToken::Hash))
3988 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00003989
3990 // Disambiguate the VMOV forms that can accept an FP immediate.
3991 // vmov.f32 <sreg>, #imm
3992 // vmov.f64 <dreg>, #imm
3993 // vmov.f32 <dreg>, #imm @ vector f32x2
3994 // vmov.f32 <qreg>, #imm @ vector f32x4
3995 //
3996 // There are also the NEON VMOV instructions which expect an
3997 // integer constant. Make sure we don't try to parse an FPImm
3998 // for these:
3999 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4000 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4001 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4002 TyOp->getToken() != ".f64"))
4003 return MatchOperand_NoMatch;
4004
Jim Grosbach9d390362011-10-03 23:38:36 +00004005 Parser.Lex(); // Eat the '#'.
4006
4007 // Handle negation, as that still comes through as a separate token.
4008 bool isNegative = false;
4009 if (Parser.getTok().is(AsmToken::Minus)) {
4010 isNegative = true;
4011 Parser.Lex();
4012 }
4013 const AsmToken &Tok = Parser.getTok();
4014 if (Tok.is(AsmToken::Real)) {
4015 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4016 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4017 // If we had a '-' in front, toggle the sign bit.
4018 IntVal ^= (uint64_t)isNegative << 63;
4019 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4020 Parser.Lex(); // Eat the token.
4021 if (Val == -1) {
4022 TokError("floating point value out of range");
4023 return MatchOperand_ParseFail;
4024 }
4025 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4026 return MatchOperand_Success;
4027 }
4028 if (Tok.is(AsmToken::Integer)) {
4029 int64_t Val = Tok.getIntVal();
4030 Parser.Lex(); // Eat the token.
4031 if (Val > 255 || Val < 0) {
4032 TokError("encoded floating point value out of range");
4033 return MatchOperand_ParseFail;
4034 }
4035 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4036 return MatchOperand_Success;
4037 }
4038
4039 TokError("invalid floating point immediate");
4040 return MatchOperand_ParseFail;
4041}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004042/// Parse a arm instruction operand. For now this parses the operand regardless
4043/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004044bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004045 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004046 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004047
4048 // Check if the current operand has a custom associated parser, if so, try to
4049 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004050 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4051 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004052 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004053 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4054 // there was a match, but an error occurred, in which case, just return that
4055 // the operand parsing failed.
4056 if (ResTy == MatchOperand_ParseFail)
4057 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004058
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004059 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004060 default:
4061 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004062 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004063 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004064 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004065 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004066 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004067 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004068 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004069 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004070 else if (Res == -1) // irrecoverable error
4071 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004072 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4073 S = Parser.getTok().getLoc();
4074 Parser.Lex();
4075 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4076 return false;
4077 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004078
4079 // Fall though for the Identifier case that is not a register or a
4080 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004081 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004082 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004083 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004084 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004085 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004086 // This was not a register so parse other operands that start with an
4087 // identifier (like labels) as expressions and create them as immediates.
4088 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004089 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004090 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004091 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004092 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004093 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4094 return false;
4095 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004096 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004097 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004098 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004099 return parseRegisterList(Operands);
Owen Anderson63553c72011-08-29 17:17:09 +00004100 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004101 // #42 -> immediate.
4102 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004103 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004104 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004105 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004106 const MCExpr *ImmVal;
4107 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004108 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004109 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004110 if (CE) {
4111 int32_t Val = CE->getValue();
4112 if (isNegative && Val == 0)
4113 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004114 }
Sean Callanan76264762010-04-02 22:27:05 +00004115 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004116 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4117 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004118 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004119 case AsmToken::Colon: {
4120 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004121 // FIXME: Check it's an expression prefix,
4122 // e.g. (FOO - :lower16:BAR) isn't legal.
4123 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004124 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004125 return true;
4126
Evan Cheng75972122011-01-13 07:58:56 +00004127 const MCExpr *SubExprVal;
4128 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004129 return true;
4130
Evan Cheng75972122011-01-13 07:58:56 +00004131 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4132 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004133 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004134 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004135 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004136 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004137 }
4138}
4139
Jim Grosbach1355cf12011-07-26 17:10:22 +00004140// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004141// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004142bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004143 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004144
4145 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004146 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004147 Parser.Lex(); // Eat ':'
4148
4149 if (getLexer().isNot(AsmToken::Identifier)) {
4150 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4151 return true;
4152 }
4153
4154 StringRef IDVal = Parser.getTok().getIdentifier();
4155 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004156 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004157 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004158 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004159 } else {
4160 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4161 return true;
4162 }
4163 Parser.Lex();
4164
4165 if (getLexer().isNot(AsmToken::Colon)) {
4166 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4167 return true;
4168 }
4169 Parser.Lex(); // Eat the last ':'
4170 return false;
4171}
4172
Daniel Dunbar352e1482011-01-11 15:59:50 +00004173/// \brief Given a mnemonic, split out possible predication code and carry
4174/// setting letters to form a canonical mnemonic and flags.
4175//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004176// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004177// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004178StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004179 unsigned &PredicationCode,
4180 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004181 unsigned &ProcessorIMod,
4182 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004183 PredicationCode = ARMCC::AL;
4184 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004185 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004186
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004187 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004188 //
4189 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004190 if ((Mnemonic == "movs" && isThumb()) ||
4191 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4192 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4193 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4194 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4195 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4196 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4197 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004198 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004199
Jim Grosbach3f00e312011-07-11 17:09:57 +00004200 // First, split out any predication code. Ignore mnemonics we know aren't
4201 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004202 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004203 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004204 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004205 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004206 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4207 .Case("eq", ARMCC::EQ)
4208 .Case("ne", ARMCC::NE)
4209 .Case("hs", ARMCC::HS)
4210 .Case("cs", ARMCC::HS)
4211 .Case("lo", ARMCC::LO)
4212 .Case("cc", ARMCC::LO)
4213 .Case("mi", ARMCC::MI)
4214 .Case("pl", ARMCC::PL)
4215 .Case("vs", ARMCC::VS)
4216 .Case("vc", ARMCC::VC)
4217 .Case("hi", ARMCC::HI)
4218 .Case("ls", ARMCC::LS)
4219 .Case("ge", ARMCC::GE)
4220 .Case("lt", ARMCC::LT)
4221 .Case("gt", ARMCC::GT)
4222 .Case("le", ARMCC::LE)
4223 .Case("al", ARMCC::AL)
4224 .Default(~0U);
4225 if (CC != ~0U) {
4226 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4227 PredicationCode = CC;
4228 }
Bill Wendling52925b62010-10-29 23:50:21 +00004229 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004230
Daniel Dunbar352e1482011-01-11 15:59:50 +00004231 // Next, determine if we have a carry setting bit. We explicitly ignore all
4232 // the instructions we know end in 's'.
4233 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004234 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004235 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4236 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4237 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004238 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004239 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004240 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4241 CarrySetting = true;
4242 }
4243
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004244 // The "cps" instruction can have a interrupt mode operand which is glued into
4245 // the mnemonic. Check if this is the case, split it and parse the imod op
4246 if (Mnemonic.startswith("cps")) {
4247 // Split out any imod code.
4248 unsigned IMod =
4249 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4250 .Case("ie", ARM_PROC::IE)
4251 .Case("id", ARM_PROC::ID)
4252 .Default(~0U);
4253 if (IMod != ~0U) {
4254 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4255 ProcessorIMod = IMod;
4256 }
4257 }
4258
Jim Grosbach89df9962011-08-26 21:43:41 +00004259 // The "it" instruction has the condition mask on the end of the mnemonic.
4260 if (Mnemonic.startswith("it")) {
4261 ITMask = Mnemonic.slice(2, Mnemonic.size());
4262 Mnemonic = Mnemonic.slice(0, 2);
4263 }
4264
Daniel Dunbar352e1482011-01-11 15:59:50 +00004265 return Mnemonic;
4266}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004267
4268/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4269/// inclusion of carry set or predication code operands.
4270//
4271// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004272void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004273getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004274 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004275 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4276 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004277 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004278 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004279 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004280 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004281 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004282 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004283 Mnemonic == "mla" || Mnemonic == "smlal" ||
4284 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004285 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004286 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004287 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004288
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004289 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4290 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4291 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4292 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004293 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4294 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004295 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004296 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4297 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4298 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004299 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4300 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004301 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004302 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004303 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004304 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004305
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004306 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004307 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004308 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004309 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004310 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004311}
4312
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004313bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4314 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004315 // FIXME: This is all horribly hacky. We really need a better way to deal
4316 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004317
4318 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4319 // another does not. Specifically, the MOVW instruction does not. So we
4320 // special case it here and remove the defaulted (non-setting) cc_out
4321 // operand if that's the instruction we're trying to match.
4322 //
4323 // We do this as post-processing of the explicit operands rather than just
4324 // conditionally adding the cc_out in the first place because we need
4325 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004326 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004327 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4328 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4329 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4330 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004331
4332 // Register-register 'add' for thumb does not have a cc_out operand
4333 // when there are only two register operands.
4334 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4335 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4336 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4337 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4338 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004339 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004340 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4341 // have to check the immediate range here since Thumb2 has a variant
4342 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004343 if (((isThumb() && Mnemonic == "add") ||
4344 (isThumbTwo() && Mnemonic == "sub")) &&
4345 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004346 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4347 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4348 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004349 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4350 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4351 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004352 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004353 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4354 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004355 // selecting via the generic "add" mnemonic, so to know that we
4356 // should remove the cc_out operand, we have to explicitly check that
4357 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004358 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4359 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004360 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4361 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4362 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4363 // Nest conditions rather than one big 'if' statement for readability.
4364 //
4365 // If either register is a high reg, it's either one of the SP
4366 // variants (handled above) or a 32-bit encoding, so we just
4367 // check against T3.
4368 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4369 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4370 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4371 return false;
4372 // If both registers are low, we're in an IT block, and the immediate is
4373 // in range, we should use encoding T1 instead, which has a cc_out.
4374 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004375 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004376 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4377 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4378 return false;
4379
4380 // Otherwise, we use encoding T4, which does not have a cc_out
4381 // operand.
4382 return true;
4383 }
4384
Jim Grosbach64944f42011-09-14 21:00:40 +00004385 // The thumb2 multiply instruction doesn't have a CCOut register, so
4386 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4387 // use the 16-bit encoding or not.
4388 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4389 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4390 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4391 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4392 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4393 // If the registers aren't low regs, the destination reg isn't the
4394 // same as one of the source regs, or the cc_out operand is zero
4395 // outside of an IT block, we have to use the 32-bit encoding, so
4396 // remove the cc_out operand.
4397 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4398 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004399 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004400 !inITBlock() ||
4401 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4402 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4403 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4404 static_cast<ARMOperand*>(Operands[4])->getReg())))
4405 return true;
4406
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004407 // Also check the 'mul' syntax variant that doesn't specify an explicit
4408 // destination register.
4409 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4410 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4411 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4412 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4413 // If the registers aren't low regs or the cc_out operand is zero
4414 // outside of an IT block, we have to use the 32-bit encoding, so
4415 // remove the cc_out operand.
4416 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4417 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4418 !inITBlock()))
4419 return true;
4420
Jim Grosbach64944f42011-09-14 21:00:40 +00004421
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004422
Jim Grosbachf69c8042011-08-24 21:42:27 +00004423 // Register-register 'add/sub' for thumb does not have a cc_out operand
4424 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4425 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4426 // right, this will result in better diagnostics (which operand is off)
4427 // anyway.
4428 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4429 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004430 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4431 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4432 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4433 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004434
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004435 return false;
4436}
4437
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004438static bool isDataTypeToken(StringRef Tok) {
4439 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4440 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4441 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4442 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4443 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4444 Tok == ".f" || Tok == ".d";
4445}
4446
4447// FIXME: This bit should probably be handled via an explicit match class
4448// in the .td files that matches the suffix instead of having it be
4449// a literal string token the way it is now.
4450static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4451 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4452}
4453
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004454/// Parse an arm instruction mnemonic followed by its operands.
4455bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4456 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4457 // Create the leading tokens for the mnemonic, split by '.' characters.
4458 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004459 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004460
Daniel Dunbar352e1482011-01-11 15:59:50 +00004461 // Split out the predication code and carry setting flag from the mnemonic.
4462 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004463 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004464 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004465 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004466 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004467 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004468
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004469 // In Thumb1, only the branch (B) instruction can be predicated.
4470 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4471 Parser.EatToEndOfStatement();
4472 return Error(NameLoc, "conditional execution not supported in Thumb1");
4473 }
4474
Jim Grosbachffa32252011-07-19 19:13:28 +00004475 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4476
Jim Grosbach89df9962011-08-26 21:43:41 +00004477 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4478 // is the mask as it will be for the IT encoding if the conditional
4479 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4480 // where the conditional bit0 is zero, the instruction post-processing
4481 // will adjust the mask accordingly.
4482 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004483 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4484 if (ITMask.size() > 3) {
4485 Parser.EatToEndOfStatement();
4486 return Error(Loc, "too many conditions on IT instruction");
4487 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004488 unsigned Mask = 8;
4489 for (unsigned i = ITMask.size(); i != 0; --i) {
4490 char pos = ITMask[i - 1];
4491 if (pos != 't' && pos != 'e') {
4492 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004493 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004494 }
4495 Mask >>= 1;
4496 if (ITMask[i - 1] == 't')
4497 Mask |= 8;
4498 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004499 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004500 }
4501
Jim Grosbachffa32252011-07-19 19:13:28 +00004502 // FIXME: This is all a pretty gross hack. We should automatically handle
4503 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004504
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004505 // Next, add the CCOut and ConditionCode operands, if needed.
4506 //
4507 // For mnemonics which can ever incorporate a carry setting bit or predication
4508 // code, our matching model involves us always generating CCOut and
4509 // ConditionCode operands to match the mnemonic "as written" and then we let
4510 // the matcher deal with finding the right instruction or generating an
4511 // appropriate error.
4512 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004513 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004514
Jim Grosbach33c16a22011-07-14 22:04:21 +00004515 // If we had a carry-set on an instruction that can't do that, issue an
4516 // error.
4517 if (!CanAcceptCarrySet && CarrySetting) {
4518 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004519 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004520 "' can not set flags, but 's' suffix specified");
4521 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004522 // If we had a predication code on an instruction that can't do that, issue an
4523 // error.
4524 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4525 Parser.EatToEndOfStatement();
4526 return Error(NameLoc, "instruction '" + Mnemonic +
4527 "' is not predicable, but condition code specified");
4528 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004529
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004530 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004531 if (CanAcceptCarrySet) {
4532 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004533 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004534 Loc));
4535 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004536
4537 // Add the predication code operand, if necessary.
4538 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004539 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4540 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004541 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004542 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004543 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004544
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004545 // Add the processor imod operand, if necessary.
4546 if (ProcessorIMod) {
4547 Operands.push_back(ARMOperand::CreateImm(
4548 MCConstantExpr::Create(ProcessorIMod, getContext()),
4549 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004550 }
4551
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004552 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004553 while (Next != StringRef::npos) {
4554 Start = Next;
4555 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004556 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004557
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004558 // Some NEON instructions have an optional datatype suffix that is
4559 // completely ignored. Check for that.
4560 if (isDataTypeToken(ExtraToken) &&
4561 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4562 continue;
4563
Jim Grosbach81d2e392011-09-07 16:06:04 +00004564 if (ExtraToken != ".n") {
4565 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4566 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4567 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004568 }
4569
4570 // Read the remaining operands.
4571 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004572 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004573 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004574 Parser.EatToEndOfStatement();
4575 return true;
4576 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004577
4578 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004579 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004580
4581 // Parse and remember the 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 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004588
Chris Lattnercbf8a982010-09-11 16:18:25 +00004589 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004590 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004591 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004592 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004593 }
Bill Wendling146018f2010-11-06 21:42:12 +00004594
Chris Lattner34e53142010-09-08 05:10:46 +00004595 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004596
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004597 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4598 // do and don't have a cc_out optional-def operand. With some spot-checks
4599 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004600 // parse and adjust accordingly before actually matching. We shouldn't ever
4601 // try to remove a cc_out operand that was explicitly set on the the
4602 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4603 // table driven matcher doesn't fit well with the ARM instruction set.
4604 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004605 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4606 Operands.erase(Operands.begin() + 1);
4607 delete Op;
4608 }
4609
Jim Grosbachcf121c32011-07-28 21:57:55 +00004610 // ARM mode 'blx' need special handling, as the register operand version
4611 // is predicable, but the label operand version is not. So, we can't rely
4612 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004613 // a k_CondCode operand in the list. If we're trying to match the label
4614 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004615 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4616 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4617 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4618 Operands.erase(Operands.begin() + 1);
4619 delete Op;
4620 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004621
4622 // The vector-compare-to-zero instructions have a literal token "#0" at
4623 // the end that comes to here as an immediate operand. Convert it to a
4624 // token to play nicely with the matcher.
4625 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4626 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4627 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4628 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4629 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4630 if (CE && CE->getValue() == 0) {
4631 Operands.erase(Operands.begin() + 5);
4632 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4633 delete Op;
4634 }
4635 }
Jim Grosbach68259142011-10-03 22:30:24 +00004636 // VCMP{E} does the same thing, but with a different operand count.
4637 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4638 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4639 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4640 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4641 if (CE && CE->getValue() == 0) {
4642 Operands.erase(Operands.begin() + 4);
4643 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4644 delete Op;
4645 }
4646 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004647 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
4648 // end. Convert it to a token here.
4649 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
4650 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4651 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4652 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4653 if (CE && CE->getValue() == 0) {
4654 Operands.erase(Operands.begin() + 5);
4655 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4656 delete Op;
4657 }
4658 }
4659
Chris Lattner98986712010-01-14 22:21:20 +00004660 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004661}
4662
Jim Grosbach189610f2011-07-26 18:25:39 +00004663// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004664
4665// return 'true' if register list contains non-low GPR registers,
4666// 'false' otherwise. If Reg is in the register list or is HiReg, set
4667// 'containsReg' to true.
4668static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4669 unsigned HiReg, bool &containsReg) {
4670 containsReg = false;
4671 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4672 unsigned OpReg = Inst.getOperand(i).getReg();
4673 if (OpReg == Reg)
4674 containsReg = true;
4675 // Anything other than a low register isn't legal here.
4676 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4677 return true;
4678 }
4679 return false;
4680}
4681
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004682// Check if the specified regisgter is in the register list of the inst,
4683// starting at the indicated operand number.
4684static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4685 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4686 unsigned OpReg = Inst.getOperand(i).getReg();
4687 if (OpReg == Reg)
4688 return true;
4689 }
4690 return false;
4691}
4692
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004693// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4694// the ARMInsts array) instead. Getting that here requires awkward
4695// API changes, though. Better way?
4696namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004697extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004698}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004699static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004700 return ARMInsts[Opcode];
4701}
4702
Jim Grosbach189610f2011-07-26 18:25:39 +00004703// FIXME: We would really like to be able to tablegen'erate this.
4704bool ARMAsmParser::
4705validateInstruction(MCInst &Inst,
4706 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004707 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004708 SMLoc Loc = Operands[0]->getStartLoc();
4709 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004710 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4711 // being allowed in IT blocks, but not being predicable. It just always
4712 // executes.
4713 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004714 unsigned bit = 1;
4715 if (ITState.FirstCond)
4716 ITState.FirstCond = false;
4717 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004718 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004719 // The instruction must be predicable.
4720 if (!MCID.isPredicable())
4721 return Error(Loc, "instructions in IT block must be predicable");
4722 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4723 unsigned ITCond = bit ? ITState.Cond :
4724 ARMCC::getOppositeCondition(ITState.Cond);
4725 if (Cond != ITCond) {
4726 // Find the condition code Operand to get its SMLoc information.
4727 SMLoc CondLoc;
4728 for (unsigned i = 1; i < Operands.size(); ++i)
4729 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4730 CondLoc = Operands[i]->getStartLoc();
4731 return Error(CondLoc, "incorrect condition in IT block; got '" +
4732 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4733 "', but expected '" +
4734 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4735 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004736 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004737 } else if (isThumbTwo() && MCID.isPredicable() &&
4738 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004739 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4740 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004741 return Error(Loc, "predicated instructions must be in IT block");
4742
Jim Grosbach189610f2011-07-26 18:25:39 +00004743 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004744 case ARM::LDRD:
4745 case ARM::LDRD_PRE:
4746 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004747 case ARM::LDREXD: {
4748 // Rt2 must be Rt + 1.
4749 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4750 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4751 if (Rt2 != Rt + 1)
4752 return Error(Operands[3]->getStartLoc(),
4753 "destination operands must be sequential");
4754 return false;
4755 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004756 case ARM::STRD: {
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 "source operands must be sequential");
4763 return false;
4764 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004765 case ARM::STRD_PRE:
4766 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004767 case ARM::STREXD: {
4768 // Rt2 must be Rt + 1.
4769 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4770 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4771 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004772 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004773 "source operands must be sequential");
4774 return false;
4775 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004776 case ARM::SBFX:
4777 case ARM::UBFX: {
4778 // width must be in range [1, 32-lsb]
4779 unsigned lsb = Inst.getOperand(2).getImm();
4780 unsigned widthm1 = Inst.getOperand(3).getImm();
4781 if (widthm1 >= 32 - lsb)
4782 return Error(Operands[5]->getStartLoc(),
4783 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004784 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004785 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004786 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004787 // If we're parsing Thumb2, the .w variant is available and handles
4788 // most cases that are normally illegal for a Thumb1 LDM
4789 // instruction. We'll make the transformation in processInstruction()
4790 // if necessary.
4791 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004792 // Thumb LDM instructions are writeback iff the base register is not
4793 // in the register list.
4794 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004795 bool hasWritebackToken =
4796 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4797 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004798 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004799 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004800 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4801 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004802 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004803 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004804 return Error(Operands[2]->getStartLoc(),
4805 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004806 // If we should not have writeback, there must not be a '!'. This is
4807 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004808 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004809 return Error(Operands[3]->getStartLoc(),
4810 "writeback operator '!' not allowed when base register "
4811 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004812
4813 break;
4814 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004815 case ARM::t2LDMIA_UPD: {
4816 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4817 return Error(Operands[4]->getStartLoc(),
4818 "writeback operator '!' not allowed when base register "
4819 "in register list");
4820 break;
4821 }
Jim Grosbach54026372011-11-10 23:17:11 +00004822 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4823 // so only issue a diagnostic for thumb1. The instructions will be
4824 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004825 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004826 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004827 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4828 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004829 return Error(Operands[2]->getStartLoc(),
4830 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004831 break;
4832 }
4833 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004834 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004835 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4836 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004837 return Error(Operands[2]->getStartLoc(),
4838 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004839 break;
4840 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004841 case ARM::tSTMIA_UPD: {
4842 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004843 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004844 return Error(Operands[4]->getStartLoc(),
4845 "registers must be in range r0-r7");
4846 break;
4847 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004848 }
4849
4850 return false;
4851}
4852
Jim Grosbach84defb52011-12-02 22:34:51 +00004853static unsigned getRealVSTLNOpcode(unsigned Opc) {
4854 switch(Opc) {
4855 default: assert(0 && "unexpected opcode!");
4856 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4857 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4858 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4859 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4860 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4861 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4862 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4863 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4864 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4865 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4866 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4867 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4868 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4869 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4870 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4871 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4872 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4873 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4874 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4875 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
4876 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
4877 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
4878 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
4879 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
4880 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
4881 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
4882 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
4883 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
4884 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
4885 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
4886 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
4887 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
4888 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
4889 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
4890 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
4891 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
4892 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
4893 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
4894 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
4895 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
4896 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
4897 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
4898 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
4899 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
4900 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
4901 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
4902 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
4903 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
4904 }
4905}
4906
4907static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00004908 switch(Opc) {
4909 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00004910 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
4911 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
4912 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
4913 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
4914 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
4915 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
4916 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
4917 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
4918 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
4919 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
4920 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
4921 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
4922 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
4923 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
4924 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
4925 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
4926 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
4927 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
4928 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
4929 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
4930 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
4931 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
4932 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
4933 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
4934 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
4935 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
4936 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
4937 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
4938 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
4939 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
4940 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
4941 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004942 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
4943 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
4944 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
4945 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
4946 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00004947 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
4948 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
4949 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
4950 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
4951 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00004952 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
4953 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
4954 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
4955 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
4956 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
4957 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00004958 }
4959}
4960
Jim Grosbach83ec8772011-11-10 23:42:14 +00004961bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00004962processInstruction(MCInst &Inst,
4963 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4964 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00004965 // Handle NEON VST1 complex aliases.
4966 case ARM::VST1LNdWB_register_Asm_8:
4967 case ARM::VST1LNdWB_register_Asm_P8:
4968 case ARM::VST1LNdWB_register_Asm_I8:
4969 case ARM::VST1LNdWB_register_Asm_S8:
4970 case ARM::VST1LNdWB_register_Asm_U8:
4971 case ARM::VST1LNdWB_register_Asm_16:
4972 case ARM::VST1LNdWB_register_Asm_P16:
4973 case ARM::VST1LNdWB_register_Asm_I16:
4974 case ARM::VST1LNdWB_register_Asm_S16:
4975 case ARM::VST1LNdWB_register_Asm_U16:
4976 case ARM::VST1LNdWB_register_Asm_32:
4977 case ARM::VST1LNdWB_register_Asm_F:
4978 case ARM::VST1LNdWB_register_Asm_F32:
4979 case ARM::VST1LNdWB_register_Asm_I32:
4980 case ARM::VST1LNdWB_register_Asm_S32:
4981 case ARM::VST1LNdWB_register_Asm_U32: {
4982 MCInst TmpInst;
4983 // Shuffle the operands around so the lane index operand is in the
4984 // right place.
4985 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
4986 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
4987 TmpInst.addOperand(Inst.getOperand(2)); // Rn
4988 TmpInst.addOperand(Inst.getOperand(3)); // alignment
4989 TmpInst.addOperand(Inst.getOperand(4)); // Rm
4990 TmpInst.addOperand(Inst.getOperand(0)); // Vd
4991 TmpInst.addOperand(Inst.getOperand(1)); // lane
4992 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
4993 TmpInst.addOperand(Inst.getOperand(6));
4994 Inst = TmpInst;
4995 return true;
4996 }
4997 case ARM::VST1LNdWB_fixed_Asm_8:
4998 case ARM::VST1LNdWB_fixed_Asm_P8:
4999 case ARM::VST1LNdWB_fixed_Asm_I8:
5000 case ARM::VST1LNdWB_fixed_Asm_S8:
5001 case ARM::VST1LNdWB_fixed_Asm_U8:
5002 case ARM::VST1LNdWB_fixed_Asm_16:
5003 case ARM::VST1LNdWB_fixed_Asm_P16:
5004 case ARM::VST1LNdWB_fixed_Asm_I16:
5005 case ARM::VST1LNdWB_fixed_Asm_S16:
5006 case ARM::VST1LNdWB_fixed_Asm_U16:
5007 case ARM::VST1LNdWB_fixed_Asm_32:
5008 case ARM::VST1LNdWB_fixed_Asm_F:
5009 case ARM::VST1LNdWB_fixed_Asm_F32:
5010 case ARM::VST1LNdWB_fixed_Asm_I32:
5011 case ARM::VST1LNdWB_fixed_Asm_S32:
5012 case ARM::VST1LNdWB_fixed_Asm_U32: {
5013 MCInst TmpInst;
5014 // Shuffle the operands around so the lane index operand is in the
5015 // right place.
5016 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5017 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5018 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5019 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5020 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5021 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5022 TmpInst.addOperand(Inst.getOperand(1)); // lane
5023 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5024 TmpInst.addOperand(Inst.getOperand(5));
5025 Inst = TmpInst;
5026 return true;
5027 }
5028 case ARM::VST1LNdAsm_8:
5029 case ARM::VST1LNdAsm_P8:
5030 case ARM::VST1LNdAsm_I8:
5031 case ARM::VST1LNdAsm_S8:
5032 case ARM::VST1LNdAsm_U8:
5033 case ARM::VST1LNdAsm_16:
5034 case ARM::VST1LNdAsm_P16:
5035 case ARM::VST1LNdAsm_I16:
5036 case ARM::VST1LNdAsm_S16:
5037 case ARM::VST1LNdAsm_U16:
5038 case ARM::VST1LNdAsm_32:
5039 case ARM::VST1LNdAsm_F:
5040 case ARM::VST1LNdAsm_F32:
5041 case ARM::VST1LNdAsm_I32:
5042 case ARM::VST1LNdAsm_S32:
5043 case ARM::VST1LNdAsm_U32: {
5044 MCInst TmpInst;
5045 // Shuffle the operands around so the lane index operand is in the
5046 // right place.
5047 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5048 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5049 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5050 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5051 TmpInst.addOperand(Inst.getOperand(1)); // lane
5052 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5053 TmpInst.addOperand(Inst.getOperand(5));
5054 Inst = TmpInst;
5055 return true;
5056 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005057 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005058 case ARM::VLD1LNdWB_register_Asm_8:
5059 case ARM::VLD1LNdWB_register_Asm_P8:
5060 case ARM::VLD1LNdWB_register_Asm_I8:
5061 case ARM::VLD1LNdWB_register_Asm_S8:
5062 case ARM::VLD1LNdWB_register_Asm_U8:
5063 case ARM::VLD1LNdWB_register_Asm_16:
5064 case ARM::VLD1LNdWB_register_Asm_P16:
5065 case ARM::VLD1LNdWB_register_Asm_I16:
5066 case ARM::VLD1LNdWB_register_Asm_S16:
5067 case ARM::VLD1LNdWB_register_Asm_U16:
5068 case ARM::VLD1LNdWB_register_Asm_32:
5069 case ARM::VLD1LNdWB_register_Asm_F:
5070 case ARM::VLD1LNdWB_register_Asm_F32:
5071 case ARM::VLD1LNdWB_register_Asm_I32:
5072 case ARM::VLD1LNdWB_register_Asm_S32:
5073 case ARM::VLD1LNdWB_register_Asm_U32: {
5074 MCInst TmpInst;
5075 // Shuffle the operands around so the lane index operand is in the
5076 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005077 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005078 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5079 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5080 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5081 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5082 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5083 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5084 TmpInst.addOperand(Inst.getOperand(1)); // lane
5085 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5086 TmpInst.addOperand(Inst.getOperand(6));
5087 Inst = TmpInst;
5088 return true;
5089 }
5090 case ARM::VLD1LNdWB_fixed_Asm_8:
5091 case ARM::VLD1LNdWB_fixed_Asm_P8:
5092 case ARM::VLD1LNdWB_fixed_Asm_I8:
5093 case ARM::VLD1LNdWB_fixed_Asm_S8:
5094 case ARM::VLD1LNdWB_fixed_Asm_U8:
5095 case ARM::VLD1LNdWB_fixed_Asm_16:
5096 case ARM::VLD1LNdWB_fixed_Asm_P16:
5097 case ARM::VLD1LNdWB_fixed_Asm_I16:
5098 case ARM::VLD1LNdWB_fixed_Asm_S16:
5099 case ARM::VLD1LNdWB_fixed_Asm_U16:
5100 case ARM::VLD1LNdWB_fixed_Asm_32:
5101 case ARM::VLD1LNdWB_fixed_Asm_F:
5102 case ARM::VLD1LNdWB_fixed_Asm_F32:
5103 case ARM::VLD1LNdWB_fixed_Asm_I32:
5104 case ARM::VLD1LNdWB_fixed_Asm_S32:
5105 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5106 MCInst TmpInst;
5107 // Shuffle the operands around so the lane index operand is in the
5108 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005109 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005110 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5111 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5112 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5113 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5114 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5115 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5116 TmpInst.addOperand(Inst.getOperand(1)); // lane
5117 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5118 TmpInst.addOperand(Inst.getOperand(5));
5119 Inst = TmpInst;
5120 return true;
5121 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005122 case ARM::VLD1LNdAsm_8:
5123 case ARM::VLD1LNdAsm_P8:
5124 case ARM::VLD1LNdAsm_I8:
5125 case ARM::VLD1LNdAsm_S8:
5126 case ARM::VLD1LNdAsm_U8:
5127 case ARM::VLD1LNdAsm_16:
5128 case ARM::VLD1LNdAsm_P16:
5129 case ARM::VLD1LNdAsm_I16:
5130 case ARM::VLD1LNdAsm_S16:
5131 case ARM::VLD1LNdAsm_U16:
5132 case ARM::VLD1LNdAsm_32:
5133 case ARM::VLD1LNdAsm_F:
5134 case ARM::VLD1LNdAsm_F32:
5135 case ARM::VLD1LNdAsm_I32:
5136 case ARM::VLD1LNdAsm_S32:
5137 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005138 MCInst TmpInst;
5139 // Shuffle the operands around so the lane index operand is in the
5140 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005141 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005142 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5143 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5144 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5145 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5146 TmpInst.addOperand(Inst.getOperand(1)); // lane
5147 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5148 TmpInst.addOperand(Inst.getOperand(5));
5149 Inst = TmpInst;
5150 return true;
5151 }
Jim Grosbach71810ab2011-11-10 16:44:55 +00005152 // Handle the MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005153 case ARM::ASRr:
5154 case ARM::LSRr:
5155 case ARM::LSLr:
5156 case ARM::RORr: {
5157 ARM_AM::ShiftOpc ShiftTy;
5158 switch(Inst.getOpcode()) {
5159 default: llvm_unreachable("unexpected opcode!");
5160 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5161 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5162 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5163 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5164 }
5165 // A shift by zero is a plain MOVr, not a MOVsi.
5166 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5167 MCInst TmpInst;
5168 TmpInst.setOpcode(ARM::MOVsr);
5169 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5170 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5171 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5172 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5173 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5174 TmpInst.addOperand(Inst.getOperand(4));
5175 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5176 Inst = TmpInst;
5177 return true;
5178 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005179 case ARM::ASRi:
5180 case ARM::LSRi:
5181 case ARM::LSLi:
5182 case ARM::RORi: {
5183 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005184 switch(Inst.getOpcode()) {
5185 default: llvm_unreachable("unexpected opcode!");
5186 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5187 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5188 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5189 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5190 }
5191 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005192 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005193 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5194 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005195 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005196 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005197 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5198 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005199 if (Opc == ARM::MOVsi)
5200 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005201 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5202 TmpInst.addOperand(Inst.getOperand(4));
5203 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5204 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005205 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005206 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005207 case ARM::RRXi: {
5208 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5209 MCInst TmpInst;
5210 TmpInst.setOpcode(ARM::MOVsi);
5211 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5212 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5213 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5214 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5215 TmpInst.addOperand(Inst.getOperand(3));
5216 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5217 Inst = TmpInst;
5218 return true;
5219 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005220 case ARM::t2LDMIA_UPD: {
5221 // If this is a load of a single register, then we should use
5222 // a post-indexed LDR instruction instead, per the ARM ARM.
5223 if (Inst.getNumOperands() != 5)
5224 return false;
5225 MCInst TmpInst;
5226 TmpInst.setOpcode(ARM::t2LDR_POST);
5227 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5228 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5229 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5230 TmpInst.addOperand(MCOperand::CreateImm(4));
5231 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5232 TmpInst.addOperand(Inst.getOperand(3));
5233 Inst = TmpInst;
5234 return true;
5235 }
5236 case ARM::t2STMDB_UPD: {
5237 // If this is a store of a single register, then we should use
5238 // a pre-indexed STR instruction instead, per the ARM ARM.
5239 if (Inst.getNumOperands() != 5)
5240 return false;
5241 MCInst TmpInst;
5242 TmpInst.setOpcode(ARM::t2STR_PRE);
5243 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5244 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5245 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5246 TmpInst.addOperand(MCOperand::CreateImm(-4));
5247 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5248 TmpInst.addOperand(Inst.getOperand(3));
5249 Inst = TmpInst;
5250 return true;
5251 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005252 case ARM::LDMIA_UPD:
5253 // If this is a load of a single register via a 'pop', then we should use
5254 // a post-indexed LDR instruction instead, per the ARM ARM.
5255 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5256 Inst.getNumOperands() == 5) {
5257 MCInst TmpInst;
5258 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5259 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5260 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5261 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5262 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5263 TmpInst.addOperand(MCOperand::CreateImm(4));
5264 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5265 TmpInst.addOperand(Inst.getOperand(3));
5266 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005267 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005268 }
5269 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005270 case ARM::STMDB_UPD:
5271 // If this is a store of a single register via a 'push', then we should use
5272 // a pre-indexed STR instruction instead, per the ARM ARM.
5273 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5274 Inst.getNumOperands() == 5) {
5275 MCInst TmpInst;
5276 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5277 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5278 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5279 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5280 TmpInst.addOperand(MCOperand::CreateImm(-4));
5281 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5282 TmpInst.addOperand(Inst.getOperand(3));
5283 Inst = TmpInst;
5284 }
5285 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005286 case ARM::t2ADDri12:
5287 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5288 // mnemonic was used (not "addw"), encoding T3 is preferred.
5289 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5290 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5291 break;
5292 Inst.setOpcode(ARM::t2ADDri);
5293 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5294 break;
5295 case ARM::t2SUBri12:
5296 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5297 // mnemonic was used (not "subw"), encoding T3 is preferred.
5298 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5299 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5300 break;
5301 Inst.setOpcode(ARM::t2SUBri);
5302 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5303 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005304 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005305 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5306 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5307 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5308 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005309 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005310 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005311 return true;
5312 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005313 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005314 case ARM::tSUBi8:
5315 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5316 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5317 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5318 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005319 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005320 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005321 return true;
5322 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005323 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005324 case ARM::t2ADDrr: {
5325 // If the destination and first source operand are the same, and
5326 // there's no setting of the flags, use encoding T2 instead of T3.
5327 // Note that this is only for ADD, not SUB. This mirrors the system
5328 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5329 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5330 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005331 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5332 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005333 break;
5334 MCInst TmpInst;
5335 TmpInst.setOpcode(ARM::tADDhirr);
5336 TmpInst.addOperand(Inst.getOperand(0));
5337 TmpInst.addOperand(Inst.getOperand(0));
5338 TmpInst.addOperand(Inst.getOperand(2));
5339 TmpInst.addOperand(Inst.getOperand(3));
5340 TmpInst.addOperand(Inst.getOperand(4));
5341 Inst = TmpInst;
5342 return true;
5343 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005344 case ARM::tB:
5345 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005346 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005347 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005348 return true;
5349 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005350 break;
5351 case ARM::t2B:
5352 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005353 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005354 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005355 return true;
5356 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005357 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005358 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005359 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005360 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005361 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005362 return true;
5363 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005364 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005365 case ARM::tBcc:
5366 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005367 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005368 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005369 return true;
5370 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005371 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005372 case ARM::tLDMIA: {
5373 // If the register list contains any high registers, or if the writeback
5374 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5375 // instead if we're in Thumb2. Otherwise, this should have generated
5376 // an error in validateInstruction().
5377 unsigned Rn = Inst.getOperand(0).getReg();
5378 bool hasWritebackToken =
5379 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5380 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5381 bool listContainsBase;
5382 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5383 (!listContainsBase && !hasWritebackToken) ||
5384 (listContainsBase && hasWritebackToken)) {
5385 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5386 assert (isThumbTwo());
5387 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5388 // If we're switching to the updating version, we need to insert
5389 // the writeback tied operand.
5390 if (hasWritebackToken)
5391 Inst.insert(Inst.begin(),
5392 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005393 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005394 }
5395 break;
5396 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005397 case ARM::tSTMIA_UPD: {
5398 // If the register list contains any high registers, we need to use
5399 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5400 // should have generated an error in validateInstruction().
5401 unsigned Rn = Inst.getOperand(0).getReg();
5402 bool listContainsBase;
5403 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5404 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5405 assert (isThumbTwo());
5406 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005407 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005408 }
5409 break;
5410 }
Jim Grosbach54026372011-11-10 23:17:11 +00005411 case ARM::tPOP: {
5412 bool listContainsBase;
5413 // If the register list contains any high registers, we need to use
5414 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5415 // should have generated an error in validateInstruction().
5416 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005417 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005418 assert (isThumbTwo());
5419 Inst.setOpcode(ARM::t2LDMIA_UPD);
5420 // Add the base register and writeback operands.
5421 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5422 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005423 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005424 }
5425 case ARM::tPUSH: {
5426 bool listContainsBase;
5427 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005428 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005429 assert (isThumbTwo());
5430 Inst.setOpcode(ARM::t2STMDB_UPD);
5431 // Add the base register and writeback operands.
5432 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5433 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005434 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005435 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005436 case ARM::t2MOVi: {
5437 // If we can use the 16-bit encoding and the user didn't explicitly
5438 // request the 32-bit variant, transform it here.
5439 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5440 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005441 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5442 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5443 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005444 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5445 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5446 // The operands aren't in the same order for tMOVi8...
5447 MCInst TmpInst;
5448 TmpInst.setOpcode(ARM::tMOVi8);
5449 TmpInst.addOperand(Inst.getOperand(0));
5450 TmpInst.addOperand(Inst.getOperand(4));
5451 TmpInst.addOperand(Inst.getOperand(1));
5452 TmpInst.addOperand(Inst.getOperand(2));
5453 TmpInst.addOperand(Inst.getOperand(3));
5454 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005455 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005456 }
5457 break;
5458 }
5459 case ARM::t2MOVr: {
5460 // If we can use the 16-bit encoding and the user didn't explicitly
5461 // request the 32-bit variant, transform it here.
5462 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5463 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5464 Inst.getOperand(2).getImm() == ARMCC::AL &&
5465 Inst.getOperand(4).getReg() == ARM::CPSR &&
5466 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5467 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5468 // The operands aren't the same for tMOV[S]r... (no cc_out)
5469 MCInst TmpInst;
5470 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5471 TmpInst.addOperand(Inst.getOperand(0));
5472 TmpInst.addOperand(Inst.getOperand(1));
5473 TmpInst.addOperand(Inst.getOperand(2));
5474 TmpInst.addOperand(Inst.getOperand(3));
5475 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005476 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005477 }
5478 break;
5479 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005480 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005481 case ARM::t2SXTB:
5482 case ARM::t2UXTH:
5483 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005484 // If we can use the 16-bit encoding and the user didn't explicitly
5485 // request the 32-bit variant, transform it here.
5486 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5487 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5488 Inst.getOperand(2).getImm() == 0 &&
5489 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5490 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005491 unsigned NewOpc;
5492 switch (Inst.getOpcode()) {
5493 default: llvm_unreachable("Illegal opcode!");
5494 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5495 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5496 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5497 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5498 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005499 // The operands aren't the same for thumb1 (no rotate operand).
5500 MCInst TmpInst;
5501 TmpInst.setOpcode(NewOpc);
5502 TmpInst.addOperand(Inst.getOperand(0));
5503 TmpInst.addOperand(Inst.getOperand(1));
5504 TmpInst.addOperand(Inst.getOperand(3));
5505 TmpInst.addOperand(Inst.getOperand(4));
5506 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005507 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005508 }
5509 break;
5510 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005511 case ARM::t2IT: {
5512 // The mask bits for all but the first condition are represented as
5513 // the low bit of the condition code value implies 't'. We currently
5514 // always have 1 implies 't', so XOR toggle the bits if the low bit
5515 // of the condition code is zero. The encoding also expects the low
5516 // bit of the condition to be encoded as bit 4 of the mask operand,
5517 // so mask that in if needed
5518 MCOperand &MO = Inst.getOperand(1);
5519 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005520 unsigned OrigMask = Mask;
5521 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005522 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005523 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5524 for (unsigned i = 3; i != TZ; --i)
5525 Mask ^= 1 << i;
5526 } else
5527 Mask |= 0x10;
5528 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005529
5530 // Set up the IT block state according to the IT instruction we just
5531 // matched.
5532 assert(!inITBlock() && "nested IT blocks?!");
5533 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5534 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5535 ITState.CurPosition = 0;
5536 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005537 break;
5538 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005539 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005540 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005541}
5542
Jim Grosbach47a0d522011-08-16 20:45:50 +00005543unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5544 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5545 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005546 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005547 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005548 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5549 assert(MCID.hasOptionalDef() &&
5550 "optionally flag setting instruction missing optional def operand");
5551 assert(MCID.NumOperands == Inst.getNumOperands() &&
5552 "operand count mismatch!");
5553 // Find the optional-def operand (cc_out).
5554 unsigned OpNo;
5555 for (OpNo = 0;
5556 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5557 ++OpNo)
5558 ;
5559 // If we're parsing Thumb1, reject it completely.
5560 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5561 return Match_MnemonicFail;
5562 // If we're parsing Thumb2, which form is legal depends on whether we're
5563 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005564 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5565 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005566 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005567 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5568 inITBlock())
5569 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005570 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005571 // Some high-register supporting Thumb1 encodings only allow both registers
5572 // to be from r0-r7 when in Thumb2.
5573 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5574 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5575 isARMLowRegister(Inst.getOperand(2).getReg()))
5576 return Match_RequiresThumb2;
5577 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005578 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005579 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5580 isARMLowRegister(Inst.getOperand(1).getReg()))
5581 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005582 return Match_Success;
5583}
5584
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005585bool ARMAsmParser::
5586MatchAndEmitInstruction(SMLoc IDLoc,
5587 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5588 MCStreamer &Out) {
5589 MCInst Inst;
5590 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005591 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005592 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005593 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005594 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005595 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005596 // Context sensitive operand constraints aren't handled by the matcher,
5597 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005598 if (validateInstruction(Inst, Operands)) {
5599 // Still progress the IT block, otherwise one wrong condition causes
5600 // nasty cascading errors.
5601 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005602 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005603 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005604
Jim Grosbachf8fce712011-08-11 17:35:48 +00005605 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005606 // encoding is selected. Loop on it while changes happen so the
5607 // individual transformations can chain off each other. E.g.,
5608 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5609 while (processInstruction(Inst, Operands))
5610 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005611
Jim Grosbacha1109882011-09-02 23:22:08 +00005612 // Only move forward at the very end so that everything in validate
5613 // and process gets a consistent answer about whether we're in an IT
5614 // block.
5615 forwardITPosition();
5616
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005617 Out.EmitInstruction(Inst);
5618 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005619 case Match_MissingFeature:
5620 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5621 return true;
5622 case Match_InvalidOperand: {
5623 SMLoc ErrorLoc = IDLoc;
5624 if (ErrorInfo != ~0U) {
5625 if (ErrorInfo >= Operands.size())
5626 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005627
Chris Lattnere73d4f82010-10-28 21:41:58 +00005628 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5629 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5630 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005631
Chris Lattnere73d4f82010-10-28 21:41:58 +00005632 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005633 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005634 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005635 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005636 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005637 // The converter function will have already emited a diagnostic.
5638 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005639 case Match_RequiresNotITBlock:
5640 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005641 case Match_RequiresITBlock:
5642 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005643 case Match_RequiresV6:
5644 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5645 case Match_RequiresThumb2:
5646 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005647 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005648
Eric Christopherc223e2b2010-10-29 09:26:59 +00005649 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005650 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005651}
5652
Jim Grosbach1355cf12011-07-26 17:10:22 +00005653/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005654bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5655 StringRef IDVal = DirectiveID.getIdentifier();
5656 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005657 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005658 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005659 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00005660 else if (IDVal == ".arm")
5661 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005662 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005663 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005664 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005665 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005666 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005667 return parseDirectiveSyntax(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005668 return true;
5669}
5670
Jim Grosbach1355cf12011-07-26 17:10:22 +00005671/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005672/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005673bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005674 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5675 for (;;) {
5676 const MCExpr *Value;
5677 if (getParser().ParseExpression(Value))
5678 return true;
5679
Chris Lattneraaec2052010-01-19 19:46:13 +00005680 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005681
5682 if (getLexer().is(AsmToken::EndOfStatement))
5683 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005684
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005685 // FIXME: Improve diagnostic.
5686 if (getLexer().isNot(AsmToken::Comma))
5687 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005688 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005689 }
5690 }
5691
Sean Callananb9a25b72010-01-19 20:27:46 +00005692 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005693 return false;
5694}
5695
Jim Grosbach1355cf12011-07-26 17:10:22 +00005696/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005697/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005698bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005699 if (getLexer().isNot(AsmToken::EndOfStatement))
5700 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005701 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005702
Jim Grosbach9a70df92011-12-07 18:04:19 +00005703 if (!isThumb())
5704 SwitchMode();
5705 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5706 return false;
5707}
5708
5709/// parseDirectiveARM
5710/// ::= .arm
5711bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5712 if (getLexer().isNot(AsmToken::EndOfStatement))
5713 return Error(L, "unexpected token in directive");
5714 Parser.Lex();
5715
5716 if (isThumb())
5717 SwitchMode();
5718 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00005719 return false;
5720}
5721
Jim Grosbach1355cf12011-07-26 17:10:22 +00005722/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005723/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005724bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005725 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5726 bool isMachO = MAI.hasSubsectionsViaSymbols();
5727 StringRef Name;
5728
5729 // Darwin asm has function name after .thumb_func direction
5730 // ELF doesn't
5731 if (isMachO) {
5732 const AsmToken &Tok = Parser.getTok();
5733 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5734 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005735 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005736 Parser.Lex(); // Consume the identifier token.
5737 }
5738
Jim Grosbachd475f862011-11-10 20:48:53 +00005739 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005740 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005741 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005742
Rafael Espindola64695402011-05-16 16:17:21 +00005743 // FIXME: assuming function name will be the line following .thumb_func
5744 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005745 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005746 }
5747
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005748 // Mark symbol as a thumb symbol.
5749 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5750 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005751 return false;
5752}
5753
Jim Grosbach1355cf12011-07-26 17:10:22 +00005754/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005755/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005756bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005757 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005758 if (Tok.isNot(AsmToken::Identifier))
5759 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005760 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005761 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005762 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005763 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005764 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005765 else
5766 return Error(L, "unrecognized syntax mode in .syntax directive");
5767
5768 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005769 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005770 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005771
5772 // TODO tell the MC streamer the mode
5773 // getParser().getStreamer().Emit???();
5774 return false;
5775}
5776
Jim Grosbach1355cf12011-07-26 17:10:22 +00005777/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005778/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005779bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005780 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005781 if (Tok.isNot(AsmToken::Integer))
5782 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005783 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005784 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005785 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005786 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005787 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005788 else
5789 return Error(L, "invalid operand to .code directive");
5790
5791 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005792 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005793 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005794
Evan Cheng32869202011-07-08 22:36:29 +00005795 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005796 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005797 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005798 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005799 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005800 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005801 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005802 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005803 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005804
Kevin Enderby515d5092009-10-15 20:48:48 +00005805 return false;
5806}
5807
Sean Callanan90b70972010-04-07 20:29:34 +00005808extern "C" void LLVMInitializeARMAsmLexer();
5809
Kevin Enderby9c41fa82009-10-30 22:55:57 +00005810/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005811extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00005812 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
5813 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00005814 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005815}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005816
Chris Lattner0692ee62010-09-06 19:11:01 +00005817#define GET_REGISTER_MATCHER
5818#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00005819#include "ARMGenAsmMatcher.inc"