blob: 667418cf120a18f29f7beb2e3e2eb2d2c37e48ca [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 Grosbacha39cda72011-12-14 02:16:11 +000048 // Map of register aliases registers via the .req directive.
49 StringMap<unsigned> RegisterReqs;
50
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000051 struct {
52 ARMCC::CondCodes Cond; // Condition for IT block.
53 unsigned Mask:4; // Condition mask for instructions.
54 // Starting at first 1 (from lsb).
55 // '1' condition as indicated in IT.
56 // '0' inverse of condition (else).
57 // Count of instructions in IT block is
58 // 4 - trailingzeroes(mask)
59
60 bool FirstCond; // Explicit flag for when we're parsing the
61 // First instruction in the IT block. It's
62 // implied in the mask, so needs special
63 // handling.
64
65 unsigned CurPosition; // Current position in parsing of IT
66 // block. In range [0,3]. Initialized
67 // according to count of instructions in block.
68 // ~0U if no active IT block.
69 } ITState;
70 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000071 void forwardITPosition() {
72 if (!inITBlock()) return;
73 // Move to the next instruction in the IT block, if there is one. If not,
74 // mark the block as done.
75 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
76 if (++ITState.CurPosition == 5 - TZ)
77 ITState.CurPosition = ~0U; // Done with the IT block after this.
78 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000079
80
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000081 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
83
84 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000085 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
86
Jim Grosbach1355cf12011-07-26 17:10:22 +000087 int tryParseRegister();
88 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000089 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000090 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000091 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000092 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
93 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +000094 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
95 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +000096 bool parseDirectiveWord(unsigned Size, SMLoc L);
97 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +000098 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseDirectiveThumbFunc(SMLoc L);
100 bool parseDirectiveCode(SMLoc L);
101 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000102 bool parseDirectiveReq(StringRef Name, SMLoc L);
103 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000104 bool parseDirectiveArch(SMLoc L);
105 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000106
Jim Grosbach1355cf12011-07-26 17:10:22 +0000107 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000108 bool &CarrySetting, unsigned &ProcessorIMod,
109 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000110 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000111 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000112
Evan Chengebdeeab2011-07-08 01:53:10 +0000113 bool isThumb() const {
114 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000115 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000116 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000118 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000119 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000120 bool isThumbTwo() const {
121 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
122 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000123 bool hasV6Ops() const {
124 return STI.getFeatureBits() & ARM::HasV6Ops;
125 }
James Molloyacad68d2011-09-28 14:21:38 +0000126 bool hasV7Ops() const {
127 return STI.getFeatureBits() & ARM::HasV7Ops;
128 }
Evan Cheng32869202011-07-08 22:36:29 +0000129 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000130 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
131 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool isMClass() const {
134 return STI.getFeatureBits() & ARM::FeatureMClass;
135 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000136
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000137 /// @name Auto-generated Match Functions
138 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000139
Chris Lattner0692ee62010-09-06 19:11:01 +0000140#define GET_ASSEMBLER_HEADER
141#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000142
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000143 /// }
144
Jim Grosbach89df9962011-08-26 21:43:41 +0000145 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000148 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000150 OperandMatchResultTy parseCoprocOptionOperand(
151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000156 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000157 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000158 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
159 StringRef Op, int Low, int High);
160 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
161 return parsePKHImm(O, "lsl", 0, 31);
162 }
163 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
164 return parsePKHImm(O, "asr", 1, 32);
165 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000166 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000167 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000168 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000169 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000170 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000171 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000172 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000173 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000174 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000175
176 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000177 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
179 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000181 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000183 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000185 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000187 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000189 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000191 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000193 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000195 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
201 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000203 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000205 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000207 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000209 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000211 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
213 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000215 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
217 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
218 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000219
220 bool validateInstruction(MCInst &Inst,
221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000222 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000223 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000224 bool shouldOmitCCOutOperand(StringRef Mnemonic,
225 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000227public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000228 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000230 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000231 Match_RequiresV6,
232 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000233 };
234
Evan Chengffc0e732011-07-09 05:47:46 +0000235 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000236 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000238
Evan Chengebdeeab2011-07-08 01:53:10 +0000239 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000240 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000241
242 // Not in an ITBlock to start with.
243 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000244 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000245
Jim Grosbach1355cf12011-07-26 17:10:22 +0000246 // Implementation of the MCTargetAsmParser interface:
247 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
248 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000249 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000250 bool ParseDirective(AsmToken DirectiveID);
251
Jim Grosbach47a0d522011-08-16 20:45:50 +0000252 unsigned checkTargetMatchPredicate(MCInst &Inst);
253
Jim Grosbach1355cf12011-07-26 17:10:22 +0000254 bool MatchAndEmitInstruction(SMLoc IDLoc,
255 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
256 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000257};
Jim Grosbach16c74252010-10-29 14:46:02 +0000258} // end anonymous namespace
259
Chris Lattner3a697562010-10-28 17:20:03 +0000260namespace {
261
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000262/// ARMOperand - Instances of this class represent a parsed ARM machine
263/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000264class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000265 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000266 k_CondCode,
267 k_CCOut,
268 k_ITCondMask,
269 k_CoprocNum,
270 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000271 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000272 k_Immediate,
273 k_FPImmediate,
274 k_MemBarrierOpt,
275 k_Memory,
276 k_PostIndexRegister,
277 k_MSRMask,
278 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000279 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000280 k_Register,
281 k_RegisterList,
282 k_DPRRegisterList,
283 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000284 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000285 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000286 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000287 k_ShiftedRegister,
288 k_ShiftedImmediate,
289 k_ShifterImmediate,
290 k_RotateImmediate,
291 k_BitfieldDescriptor,
292 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000293 } Kind;
294
Sean Callanan76264762010-04-02 22:27:05 +0000295 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000296 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000297
298 union {
299 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000300 ARMCC::CondCodes Val;
301 } CC;
302
303 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000304 unsigned Val;
305 } Cop;
306
307 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000308 unsigned Val;
309 } CoprocOption;
310
311 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000312 unsigned Mask:4;
313 } ITMask;
314
315 struct {
316 ARM_MB::MemBOpt Val;
317 } MBOpt;
318
319 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000320 ARM_PROC::IFlags Val;
321 } IFlags;
322
323 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000324 unsigned Val;
325 } MMask;
326
327 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000328 const char *Data;
329 unsigned Length;
330 } Tok;
331
332 struct {
333 unsigned RegNum;
334 } Reg;
335
Jim Grosbach862019c2011-10-18 23:02:30 +0000336 // A vector register list is a sequential list of 1 to 4 registers.
337 struct {
338 unsigned RegNum;
339 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000340 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000341 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000342 } VectorList;
343
Bill Wendling8155e5b2010-11-06 22:19:43 +0000344 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000345 unsigned Val;
346 } VectorIndex;
347
348 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000349 const MCExpr *Val;
350 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000351
Jim Grosbach9d390362011-10-03 23:38:36 +0000352 struct {
353 unsigned Val; // encoded 8-bit representation
354 } FPImm;
355
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000356 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000357 struct {
358 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000359 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
360 // was specified.
361 const MCConstantExpr *OffsetImm; // Offset immediate value
362 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
363 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000364 unsigned ShiftImm; // shift for OffsetReg.
365 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000366 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000368 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000369
370 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000371 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000372 bool isAdd;
373 ARM_AM::ShiftOpc ShiftTy;
374 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 } PostIdxReg;
376
377 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000378 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000379 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000380 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000381 struct {
382 ARM_AM::ShiftOpc ShiftTy;
383 unsigned SrcReg;
384 unsigned ShiftReg;
385 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000386 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000387 struct {
388 ARM_AM::ShiftOpc ShiftTy;
389 unsigned SrcReg;
390 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000391 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000392 struct {
393 unsigned Imm;
394 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000395 struct {
396 unsigned LSB;
397 unsigned Width;
398 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000399 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000400
Bill Wendling146018f2010-11-06 21:42:12 +0000401 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
402public:
Sean Callanan76264762010-04-02 22:27:05 +0000403 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
404 Kind = o.Kind;
405 StartLoc = o.StartLoc;
406 EndLoc = o.EndLoc;
407 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000409 CC = o.CC;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000412 ITMask = o.ITMask;
413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000415 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000416 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000417 case k_CCOut:
418 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000419 Reg = o.Reg;
420 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000421 case k_RegisterList:
422 case k_DPRRegisterList:
423 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000424 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000425 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000427 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000428 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000429 VectorList = o.VectorList;
430 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000431 case k_CoprocNum:
432 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000433 Cop = o.Cop;
434 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000435 case k_CoprocOption:
436 CoprocOption = o.CoprocOption;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000439 Imm = o.Imm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000442 FPImm = o.FPImm;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000445 MBOpt = o.MBOpt;
446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000448 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000451 PostIdxReg = o.PostIdxReg;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000454 MMask = o.MMask;
455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000457 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000460 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000466 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000469 RotImm = o.RotImm;
470 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000471 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000472 Bitfield = o.Bitfield;
473 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000474 case k_VectorIndex:
475 VectorIndex = o.VectorIndex;
476 break;
Sean Callanan76264762010-04-02 22:27:05 +0000477 }
478 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000479
Sean Callanan76264762010-04-02 22:27:05 +0000480 /// getStartLoc - Get the location of the first token of this operand.
481 SMLoc getStartLoc() const { return StartLoc; }
482 /// getEndLoc - Get the location of the last token of this operand.
483 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000484
Daniel Dunbar8462b302010-08-11 06:36:53 +0000485 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000486 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000487 return CC.Val;
488 }
489
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000490 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000491 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000492 return Cop.Val;
493 }
494
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000495 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000496 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000497 return StringRef(Tok.Data, Tok.Length);
498 }
499
500 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000501 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000502 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000503 }
504
Bill Wendling5fa22a12010-11-09 23:28:44 +0000505 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000506 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
507 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000508 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000509 }
510
Kevin Enderbycfe07242009-10-13 22:19:02 +0000511 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000512 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000513 return Imm.Val;
514 }
515
Jim Grosbach9d390362011-10-03 23:38:36 +0000516 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000517 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000518 return FPImm.Val;
519 }
520
Jim Grosbach460a9052011-10-07 23:56:00 +0000521 unsigned getVectorIndex() const {
522 assert(Kind == k_VectorIndex && "Invalid access!");
523 return VectorIndex.Val;
524 }
525
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000526 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000527 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 return MBOpt.Val;
529 }
530
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000531 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000532 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 return IFlags.Val;
534 }
535
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000536 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000537 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 return MMask.Val;
539 }
540
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCoprocNum() const { return Kind == k_CoprocNum; }
542 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000543 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000544 bool isCondCode() const { return Kind == k_CondCode; }
545 bool isCCOut() const { return Kind == k_CCOut; }
546 bool isITMask() const { return Kind == k_ITCondMask; }
547 bool isITCondCode() const { return Kind == k_CondCode; }
548 bool isImm() const { return Kind == k_Immediate; }
549 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000550 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000551 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +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 >= -1020 && Value <= 1020;
557 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000558 bool isImm0_1020s4() 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 <= 1020;
565 }
566 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000567 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +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 & 3) == 0) && Value >= 0 && Value <= 508;
573 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000574 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000575 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000576 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 < 256;
581 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000582 bool isImm0_1() 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 < 2;
589 }
590 bool isImm0_3() const {
591 if (Kind != k_Immediate)
592 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 < 4;
597 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000598 bool isImm0_7() 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 < 8;
605 }
606 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000607 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +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 < 16;
613 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000614 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000615 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000616 return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = CE->getValue();
620 return Value >= 0 && Value < 32;
621 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000622 bool isImm0_63() 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 >= 0 && Value < 64;
629 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000630 bool isImm8() 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 == 8;
637 }
638 bool isImm16() 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 == 16;
645 }
646 bool isImm32() 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 == 32;
653 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000654 bool isShrImm8() 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 <= 8;
661 }
662 bool isShrImm16() const {
663 if (Kind != k_Immediate)
664 return false;
665 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
666 if (!CE) return false;
667 int64_t Value = CE->getValue();
668 return Value > 0 && Value <= 16;
669 }
670 bool isShrImm32() const {
671 if (Kind != k_Immediate)
672 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 <= 32;
677 }
678 bool isShrImm64() 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 <= 64;
685 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000686 bool isImm1_7() const {
687 if (Kind != k_Immediate)
688 return false;
689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
690 if (!CE) return false;
691 int64_t Value = CE->getValue();
692 return Value > 0 && Value < 8;
693 }
694 bool isImm1_15() const {
695 if (Kind != k_Immediate)
696 return false;
697 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
698 if (!CE) return false;
699 int64_t Value = CE->getValue();
700 return Value > 0 && Value < 16;
701 }
702 bool isImm1_31() const {
703 if (Kind != k_Immediate)
704 return false;
705 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
706 if (!CE) return false;
707 int64_t Value = CE->getValue();
708 return Value > 0 && Value < 32;
709 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000710 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000711 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000712 return false;
713 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714 if (!CE) return false;
715 int64_t Value = CE->getValue();
716 return Value > 0 && Value < 17;
717 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000718 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000719 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000720 return false;
721 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
722 if (!CE) return false;
723 int64_t Value = CE->getValue();
724 return Value > 0 && Value < 33;
725 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000726 bool isImm0_32() const {
727 if (Kind != k_Immediate)
728 return false;
729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value >= 0 && Value < 33;
733 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000734 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000735 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000736 return false;
737 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
738 if (!CE) return false;
739 int64_t Value = CE->getValue();
740 return Value >= 0 && Value < 65536;
741 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000742 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000743 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000744 return false;
745 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
746 // If it's not a constant expression, it'll generate a fixup and be
747 // handled later.
748 if (!CE) return true;
749 int64_t Value = CE->getValue();
750 return Value >= 0 && Value < 65536;
751 }
Jim Grosbached838482011-07-26 16:24:27 +0000752 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000753 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000754 return false;
755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756 if (!CE) return false;
757 int64_t Value = CE->getValue();
758 return Value >= 0 && Value <= 0xffffff;
759 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000760 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000761 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000762 return false;
763 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
764 if (!CE) return false;
765 int64_t Value = CE->getValue();
766 return Value > 0 && Value < 33;
767 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000768 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000769 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000770 return false;
771 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772 if (!CE) return false;
773 int64_t Value = CE->getValue();
774 return Value >= 0 && Value < 32;
775 }
776 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000777 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000778 return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return Value > 0 && Value <= 32;
783 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000784 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000785 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000786 return false;
787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return ARM_AM::getSOImmVal(Value) != -1;
791 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000792 bool isARMSOImmNot() const {
793 if (Kind != k_Immediate)
794 return false;
795 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
796 if (!CE) return false;
797 int64_t Value = CE->getValue();
798 return ARM_AM::getSOImmVal(~Value) != -1;
799 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000800 bool isARMSOImmNeg() const {
801 if (Kind != k_Immediate)
802 return false;
803 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
804 if (!CE) return false;
805 int64_t Value = CE->getValue();
806 return ARM_AM::getSOImmVal(-Value) != -1;
807 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000808 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000809 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000810 return false;
811 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
812 if (!CE) return false;
813 int64_t Value = CE->getValue();
814 return ARM_AM::getT2SOImmVal(Value) != -1;
815 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000816 bool isT2SOImmNot() const {
817 if (Kind != k_Immediate)
818 return false;
819 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
820 if (!CE) return false;
821 int64_t Value = CE->getValue();
822 return ARM_AM::getT2SOImmVal(~Value) != -1;
823 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000824 bool isT2SOImmNeg() const {
825 if (Kind != k_Immediate)
826 return false;
827 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
828 if (!CE) return false;
829 int64_t Value = CE->getValue();
830 return ARM_AM::getT2SOImmVal(-Value) != -1;
831 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000832 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000833 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000834 return false;
835 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
836 if (!CE) return false;
837 int64_t Value = CE->getValue();
838 return Value == 1 || Value == 0;
839 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000840 bool isReg() const { return Kind == k_Register; }
841 bool isRegList() const { return Kind == k_RegisterList; }
842 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
843 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
844 bool isToken() const { return Kind == k_Token; }
845 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
846 bool isMemory() const { return Kind == k_Memory; }
847 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
848 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
849 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
850 bool isRotImm() const { return Kind == k_RotateImmediate; }
851 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
852 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000853 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000854 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000855 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000856 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000857 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000858 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000859 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000860 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
861 (alignOK || Memory.Alignment == 0);
862 }
863 bool isAlignedMemory() const {
864 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000865 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000866 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000867 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000868 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000869 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000871 if (!Memory.OffsetImm) return true;
872 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000873 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000874 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000875 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000876 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000877 return false;
878 // Immediate offset in range [-4095, 4095].
879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
880 if (!CE) return false;
881 int64_t Val = CE->getValue();
882 return Val > -4096 && Val < 4096;
883 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000884 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000885 // If we have an immediate that's not a constant, treat it as a label
886 // reference needing a fixup. If it is a constant, it's something else
887 // and we reject it.
888 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
889 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000891 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000893 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000894 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000895 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000896 if (!Memory.OffsetImm) return true;
897 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000898 return Val > -256 && Val < 256;
899 }
900 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000901 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000902 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000903 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000904 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
905 // Immediate offset in range [-255, 255].
906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000909 // Special case, #-0 is INT32_MIN.
910 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000911 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000912 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000913 // If we have an immediate that's not a constant, treat it as a label
914 // reference needing a fixup. If it is a constant, it's something else
915 // and we reject it.
916 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
917 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000918 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000919 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000920 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000921 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000922 if (!Memory.OffsetImm) return true;
923 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000924 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000925 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000926 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000927 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000928 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000929 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000930 return false;
931 return true;
932 }
933 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000934 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000935 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
936 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000937 return false;
938 return true;
939 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000940 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000941 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000942 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000943 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000944 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000945 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000946 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
947 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000948 return false;
949 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000950 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000951 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000953 return false;
954 return true;
955 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000956 bool isMemThumbRR() const {
957 // Thumb reg+reg addressing is simple. Just two registers, a base and
958 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000959 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000960 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000961 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 return isARMLowRegister(Memory.BaseRegNum) &&
963 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000964 }
965 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000966 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000967 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000968 return false;
969 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000970 if (!Memory.OffsetImm) return true;
971 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000972 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
973 }
Jim Grosbach38466302011-08-19 18:55:51 +0000974 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000975 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000976 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000977 return false;
978 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000979 if (!Memory.OffsetImm) return true;
980 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000981 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
982 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000983 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000984 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000985 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000986 return false;
987 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000988 if (!Memory.OffsetImm) return true;
989 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000990 return Val >= 0 && Val <= 31;
991 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000992 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000993 if (!isMemory() || Memory.OffsetRegNum != 0 ||
994 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000995 return false;
996 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000999 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001000 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001001 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001002 // If we have an immediate that's not a constant, treat it as a label
1003 // reference needing a fixup. If it is a constant, it's something else
1004 // and we reject it.
1005 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
1006 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001007 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001008 return false;
1009 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001010 if (!Memory.OffsetImm) return true;
1011 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001012 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1013 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001014 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001015 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001016 return false;
1017 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001018 if (!Memory.OffsetImm) return true;
1019 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001020 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1021 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001022 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001023 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001024 return false;
1025 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001026 if (!Memory.OffsetImm) return true;
1027 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001028 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001029 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001030 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001032 return false;
1033 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001036 return Val >= 0 && Val < 256;
1037 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001038 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001040 return false;
1041 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001042 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001044 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001045 }
1046 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001048 return false;
1049 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001050 if (!Memory.OffsetImm) return true;
1051 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001052 return (Val >= 0 && Val < 4096);
1053 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001054 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001055 // If we have an immediate that's not a constant, treat it as a label
1056 // reference needing a fixup. If it is a constant, it's something else
1057 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001058 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001059 return true;
1060
Jim Grosbach57dcb852011-10-11 17:29:55 +00001061 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001062 return false;
1063 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001064 if (!Memory.OffsetImm) return true;
1065 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001066 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001067 }
1068 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001069 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001070 return false;
1071 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1072 if (!CE) return false;
1073 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001074 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001075 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001076 bool isPostIdxImm8s4() const {
1077 if (Kind != k_Immediate)
1078 return false;
1079 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1080 if (!CE) return false;
1081 int64_t Val = CE->getValue();
1082 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1083 (Val == INT32_MIN);
1084 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001085
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001086 bool isMSRMask() const { return Kind == k_MSRMask; }
1087 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001088
Jim Grosbach0e387b22011-10-17 22:26:03 +00001089 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001090 bool isSingleSpacedVectorList() const {
1091 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1092 }
1093 bool isDoubleSpacedVectorList() const {
1094 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1095 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001096 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001097 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001098 return VectorList.Count == 1;
1099 }
1100
Jim Grosbach280dfad2011-10-21 18:54:25 +00001101 bool isVecListTwoD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001102 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach280dfad2011-10-21 18:54:25 +00001103 return VectorList.Count == 2;
1104 }
1105
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001106 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001107 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001108 return VectorList.Count == 3;
1109 }
1110
Jim Grosbachb6310312011-10-21 20:35:01 +00001111 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001112 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001113 return VectorList.Count == 4;
1114 }
1115
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001116 bool isVecListTwoQ() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001117 if (!isDoubleSpacedVectorList()) return false;
1118 return VectorList.Count == 2;
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001119 }
1120
Jim Grosbach98b05a52011-11-30 01:09:44 +00001121 bool isVecListOneDAllLanes() const {
1122 if (Kind != k_VectorListAllLanes) return false;
1123 return VectorList.Count == 1;
1124 }
1125
Jim Grosbach13af2222011-11-30 18:21:25 +00001126 bool isVecListTwoDAllLanes() const {
1127 if (Kind != k_VectorListAllLanes) return false;
1128 return VectorList.Count == 2;
1129 }
1130
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001131 bool isSingleSpacedVectorIndexed() const {
1132 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1133 }
1134 bool isDoubleSpacedVectorIndexed() const {
1135 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1136 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001137 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001138 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001139 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1140 }
1141
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001142 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001143 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001144 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1145 }
1146
1147 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001148 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001149 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1150 }
1151
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001152 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001153 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001154 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1155 }
1156
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001157 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001158 if (!isSingleSpacedVectorIndexed()) return false;
1159 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1160 }
1161
1162 bool isVecListTwoQWordIndexed() const {
1163 if (!isDoubleSpacedVectorIndexed()) return false;
1164 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1165 }
1166
1167 bool isVecListTwoQHWordIndexed() const {
1168 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001169 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1170 }
1171
1172 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001173 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001174 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1175 }
1176
Jim Grosbach460a9052011-10-07 23:56:00 +00001177 bool isVectorIndex8() const {
1178 if (Kind != k_VectorIndex) return false;
1179 return VectorIndex.Val < 8;
1180 }
1181 bool isVectorIndex16() const {
1182 if (Kind != k_VectorIndex) return false;
1183 return VectorIndex.Val < 4;
1184 }
1185 bool isVectorIndex32() const {
1186 if (Kind != k_VectorIndex) return false;
1187 return VectorIndex.Val < 2;
1188 }
1189
Jim Grosbach0e387b22011-10-17 22:26:03 +00001190 bool isNEONi8splat() const {
1191 if (Kind != k_Immediate)
1192 return false;
1193 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1194 // Must be a constant.
1195 if (!CE) return false;
1196 int64_t Value = CE->getValue();
1197 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1198 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001199 return Value >= 0 && Value < 256;
1200 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001201
Jim Grosbachea461102011-10-17 23:09:09 +00001202 bool isNEONi16splat() const {
1203 if (Kind != k_Immediate)
1204 return false;
1205 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1206 // Must be a constant.
1207 if (!CE) return false;
1208 int64_t Value = CE->getValue();
1209 // i16 value in the range [0,255] or [0x0100, 0xff00]
1210 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1211 }
1212
Jim Grosbach6248a542011-10-18 00:22:00 +00001213 bool isNEONi32splat() const {
1214 if (Kind != k_Immediate)
1215 return false;
1216 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1217 // Must be a constant.
1218 if (!CE) return false;
1219 int64_t Value = CE->getValue();
1220 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1221 return (Value >= 0 && Value < 256) ||
1222 (Value >= 0x0100 && Value <= 0xff00) ||
1223 (Value >= 0x010000 && Value <= 0xff0000) ||
1224 (Value >= 0x01000000 && Value <= 0xff000000);
1225 }
1226
1227 bool isNEONi32vmov() const {
1228 if (Kind != k_Immediate)
1229 return false;
1230 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1231 // Must be a constant.
1232 if (!CE) return false;
1233 int64_t Value = CE->getValue();
1234 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1235 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1236 return (Value >= 0 && Value < 256) ||
1237 (Value >= 0x0100 && Value <= 0xff00) ||
1238 (Value >= 0x010000 && Value <= 0xff0000) ||
1239 (Value >= 0x01000000 && Value <= 0xff000000) ||
1240 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1241 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1242 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001243 bool isNEONi32vmovNeg() const {
1244 if (Kind != k_Immediate)
1245 return false;
1246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1247 // Must be a constant.
1248 if (!CE) return false;
1249 int64_t Value = ~CE->getValue();
1250 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1251 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1252 return (Value >= 0 && Value < 256) ||
1253 (Value >= 0x0100 && Value <= 0xff00) ||
1254 (Value >= 0x010000 && Value <= 0xff0000) ||
1255 (Value >= 0x01000000 && Value <= 0xff000000) ||
1256 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1257 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1258 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001259
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001260 bool isNEONi64splat() const {
1261 if (Kind != k_Immediate)
1262 return false;
1263 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1264 // Must be a constant.
1265 if (!CE) return false;
1266 uint64_t Value = CE->getValue();
1267 // i64 value with each byte being either 0 or 0xff.
1268 for (unsigned i = 0; i < 8; ++i)
1269 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1270 return true;
1271 }
1272
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001273 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001274 // Add as immediates when possible. Null MCExpr = 0.
1275 if (Expr == 0)
1276 Inst.addOperand(MCOperand::CreateImm(0));
1277 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001278 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1279 else
1280 Inst.addOperand(MCOperand::CreateExpr(Expr));
1281 }
1282
Daniel Dunbar8462b302010-08-11 06:36:53 +00001283 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001284 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001285 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001286 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1287 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001288 }
1289
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001290 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1291 assert(N == 1 && "Invalid number of operands!");
1292 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1293 }
1294
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001295 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1296 assert(N == 1 && "Invalid number of operands!");
1297 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1298 }
1299
1300 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1301 assert(N == 1 && "Invalid number of operands!");
1302 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1303 }
1304
Jim Grosbach89df9962011-08-26 21:43:41 +00001305 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1306 assert(N == 1 && "Invalid number of operands!");
1307 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1308 }
1309
1310 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1311 assert(N == 1 && "Invalid number of operands!");
1312 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1313 }
1314
Jim Grosbachd67641b2010-12-06 18:21:12 +00001315 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1316 assert(N == 1 && "Invalid number of operands!");
1317 Inst.addOperand(MCOperand::CreateReg(getReg()));
1318 }
1319
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001320 void addRegOperands(MCInst &Inst, unsigned N) const {
1321 assert(N == 1 && "Invalid number of operands!");
1322 Inst.addOperand(MCOperand::CreateReg(getReg()));
1323 }
1324
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001325 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001326 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001327 assert(isRegShiftedReg() &&
1328 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001329 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1330 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001331 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001332 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001333 }
1334
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001335 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001336 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001337 assert(isRegShiftedImm() &&
1338 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001339 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001340 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001341 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001342 }
1343
Jim Grosbach580f4a92011-07-25 22:20:28 +00001344 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001345 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001346 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1347 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001348 }
1349
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001350 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001351 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001352 const SmallVectorImpl<unsigned> &RegList = getRegList();
1353 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001354 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1355 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001356 }
1357
Bill Wendling0f630752010-11-17 04:32:08 +00001358 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1359 addRegListOperands(Inst, N);
1360 }
1361
1362 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1363 addRegListOperands(Inst, N);
1364 }
1365
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001366 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1367 assert(N == 1 && "Invalid number of operands!");
1368 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1369 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1370 }
1371
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001372 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1373 assert(N == 1 && "Invalid number of operands!");
1374 // Munge the lsb/width into a bitfield mask.
1375 unsigned lsb = Bitfield.LSB;
1376 unsigned width = Bitfield.Width;
1377 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1378 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1379 (32 - (lsb + width)));
1380 Inst.addOperand(MCOperand::CreateImm(Mask));
1381 }
1382
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001383 void addImmOperands(MCInst &Inst, unsigned N) const {
1384 assert(N == 1 && "Invalid number of operands!");
1385 addExpr(Inst, getImm());
1386 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001387
Jim Grosbach9d390362011-10-03 23:38:36 +00001388 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1389 assert(N == 1 && "Invalid number of operands!");
1390 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1391 }
1392
Jim Grosbacha77295d2011-09-08 22:07:06 +00001393 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 // FIXME: We really want to scale the value here, but the LDRD/STRD
1396 // instruction don't encode operands that way yet.
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1399 }
1400
Jim Grosbach72f39f82011-08-24 21:22:15 +00001401 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 // The immediate is scaled by four in the encoding and is stored
1404 // in the MCInst as such. Lop off the low two bits here.
1405 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1406 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1407 }
1408
1409 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 // The immediate is scaled by four in the encoding and is stored
1412 // in the MCInst as such. Lop off the low two bits here.
1413 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1414 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1415 }
1416
Jim Grosbachf4943352011-07-25 23:09:14 +00001417 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1418 assert(N == 1 && "Invalid number of operands!");
1419 // The constant encodes as the immediate-1, and we store in the instruction
1420 // the bits as encoded, so subtract off one here.
1421 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1422 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1423 }
1424
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001425 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 // The constant encodes as the immediate-1, and we store in the instruction
1428 // the bits as encoded, so subtract off one here.
1429 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1430 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1431 }
1432
Jim Grosbach70939ee2011-08-17 21:51:27 +00001433 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
1435 // The constant encodes as the immediate, except for 32, which encodes as
1436 // zero.
1437 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1438 unsigned Imm = CE->getValue();
1439 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1440 }
1441
Jim Grosbachf6c05252011-07-21 17:23:04 +00001442 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1443 assert(N == 1 && "Invalid number of operands!");
1444 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1445 // the instruction as well.
1446 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1447 int Val = CE->getValue();
1448 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1449 }
1450
Jim Grosbach89a63372011-10-28 22:36:30 +00001451 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1452 assert(N == 1 && "Invalid number of operands!");
1453 // The operand is actually a t2_so_imm, but we have its bitwise
1454 // negation in the assembly source, so twiddle it here.
1455 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1456 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1457 }
1458
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001459 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
1461 // The operand is actually a t2_so_imm, but we have its
1462 // negation in the assembly source, so twiddle it here.
1463 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1464 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1465 }
1466
Jim Grosbache70ec842011-10-28 22:50:54 +00001467 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
1469 // The operand is actually a so_imm, but we have its bitwise
1470 // negation in the assembly source, so twiddle it here.
1471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1472 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1473 }
1474
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001475 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1476 assert(N == 1 && "Invalid number of operands!");
1477 // The operand is actually a so_imm, but we have its
1478 // negation in the assembly source, so twiddle it here.
1479 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1480 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1481 }
1482
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001483 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1484 assert(N == 1 && "Invalid number of operands!");
1485 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1486 }
1487
Jim Grosbach7ce05792011-08-03 23:50:40 +00001488 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001490 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001491 }
1492
Jim Grosbach57dcb852011-10-11 17:29:55 +00001493 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1494 assert(N == 2 && "Invalid number of operands!");
1495 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1496 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1497 }
1498
Jim Grosbach7ce05792011-08-03 23:50:40 +00001499 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1500 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001501 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1502 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001503 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1504 // Special case for #-0
1505 if (Val == INT32_MIN) Val = 0;
1506 if (Val < 0) Val = -Val;
1507 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1508 } else {
1509 // For register offset, we encode the shift type and negation flag
1510 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001511 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1512 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001513 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001514 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1515 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001516 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001517 }
1518
Jim Grosbach039c2e12011-08-04 23:01:30 +00001519 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1520 assert(N == 2 && "Invalid number of operands!");
1521 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1522 assert(CE && "non-constant AM2OffsetImm operand!");
1523 int32_t Val = CE->getValue();
1524 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1525 // Special case for #-0
1526 if (Val == INT32_MIN) Val = 0;
1527 if (Val < 0) Val = -Val;
1528 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1529 Inst.addOperand(MCOperand::CreateReg(0));
1530 Inst.addOperand(MCOperand::CreateImm(Val));
1531 }
1532
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001533 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1534 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001535 // If we have an immediate that's not a constant, treat it as a label
1536 // reference needing a fixup. If it is a constant, it's something else
1537 // and we reject it.
1538 if (isImm()) {
1539 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1540 Inst.addOperand(MCOperand::CreateReg(0));
1541 Inst.addOperand(MCOperand::CreateImm(0));
1542 return;
1543 }
1544
Jim Grosbache53c87b2011-10-11 15:59:20 +00001545 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1546 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001547 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1548 // Special case for #-0
1549 if (Val == INT32_MIN) Val = 0;
1550 if (Val < 0) Val = -Val;
1551 Val = ARM_AM::getAM3Opc(AddSub, Val);
1552 } else {
1553 // For register offset, we encode the shift type and negation flag
1554 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001555 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001556 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001557 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1558 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001559 Inst.addOperand(MCOperand::CreateImm(Val));
1560 }
1561
1562 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1563 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001564 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001565 int32_t Val =
1566 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1567 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1568 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001569 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001570 }
1571
1572 // Constant offset.
1573 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1574 int32_t Val = CE->getValue();
1575 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1576 // Special case for #-0
1577 if (Val == INT32_MIN) Val = 0;
1578 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001579 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001580 Inst.addOperand(MCOperand::CreateReg(0));
1581 Inst.addOperand(MCOperand::CreateImm(Val));
1582 }
1583
Jim Grosbach7ce05792011-08-03 23:50:40 +00001584 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1585 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001586 // If we have an immediate that's not a constant, treat it as a label
1587 // reference needing a fixup. If it is a constant, it's something else
1588 // and we reject it.
1589 if (isImm()) {
1590 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1591 Inst.addOperand(MCOperand::CreateImm(0));
1592 return;
1593 }
1594
Jim Grosbach7ce05792011-08-03 23:50:40 +00001595 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001596 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001597 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1598 // Special case for #-0
1599 if (Val == INT32_MIN) Val = 0;
1600 if (Val < 0) Val = -Val;
1601 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001602 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001603 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001604 }
1605
Jim Grosbacha77295d2011-09-08 22:07:06 +00001606 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1607 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001608 // If we have an immediate that's not a constant, treat it as a label
1609 // reference needing a fixup. If it is a constant, it's something else
1610 // and we reject it.
1611 if (isImm()) {
1612 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1613 Inst.addOperand(MCOperand::CreateImm(0));
1614 return;
1615 }
1616
Jim Grosbache53c87b2011-10-11 15:59:20 +00001617 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1618 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001619 Inst.addOperand(MCOperand::CreateImm(Val));
1620 }
1621
Jim Grosbachb6aed502011-09-09 18:37:27 +00001622 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1623 assert(N == 2 && "Invalid number of operands!");
1624 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001625 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1626 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001627 Inst.addOperand(MCOperand::CreateImm(Val));
1628 }
1629
Jim Grosbach7ce05792011-08-03 23:50:40 +00001630 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1631 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001632 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1633 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001634 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001635 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001636
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001637 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1638 addMemImm8OffsetOperands(Inst, N);
1639 }
1640
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001641 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001642 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001643 }
1644
1645 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1646 assert(N == 2 && "Invalid number of operands!");
1647 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001648 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001649 addExpr(Inst, getImm());
1650 Inst.addOperand(MCOperand::CreateImm(0));
1651 return;
1652 }
1653
1654 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001655 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1656 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001657 Inst.addOperand(MCOperand::CreateImm(Val));
1658 }
1659
Jim Grosbach7ce05792011-08-03 23:50:40 +00001660 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1661 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001662 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001663 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001664 addExpr(Inst, getImm());
1665 Inst.addOperand(MCOperand::CreateImm(0));
1666 return;
1667 }
1668
1669 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001670 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1671 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001672 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001673 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001674
Jim Grosbach7f739be2011-09-19 22:21:13 +00001675 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1676 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001677 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1678 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001679 }
1680
1681 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1682 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001683 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1684 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001685 }
1686
Jim Grosbach7ce05792011-08-03 23:50:40 +00001687 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1688 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001689 unsigned Val =
1690 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1691 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001692 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1693 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001694 Inst.addOperand(MCOperand::CreateImm(Val));
1695 }
1696
Jim Grosbachab899c12011-09-07 23:10:15 +00001697 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1698 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001699 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1700 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1701 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001702 }
1703
Jim Grosbach7ce05792011-08-03 23:50:40 +00001704 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1705 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001706 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1707 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001708 }
1709
Jim Grosbach60f91a32011-08-19 17:55:24 +00001710 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1711 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001712 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1713 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001714 Inst.addOperand(MCOperand::CreateImm(Val));
1715 }
1716
Jim Grosbach38466302011-08-19 18:55:51 +00001717 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1718 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001719 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1720 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001721 Inst.addOperand(MCOperand::CreateImm(Val));
1722 }
1723
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001724 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1725 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001726 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1727 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001728 Inst.addOperand(MCOperand::CreateImm(Val));
1729 }
1730
Jim Grosbachecd85892011-08-19 18:13:48 +00001731 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1732 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001733 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1734 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001735 Inst.addOperand(MCOperand::CreateImm(Val));
1736 }
1737
Jim Grosbach7ce05792011-08-03 23:50:40 +00001738 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1739 assert(N == 1 && "Invalid number of operands!");
1740 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1741 assert(CE && "non-constant post-idx-imm8 operand!");
1742 int Imm = CE->getValue();
1743 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001744 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001745 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1746 Inst.addOperand(MCOperand::CreateImm(Imm));
1747 }
1748
Jim Grosbach2bd01182011-10-11 21:55:36 +00001749 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1752 assert(CE && "non-constant post-idx-imm8s4 operand!");
1753 int Imm = CE->getValue();
1754 bool isAdd = Imm >= 0;
1755 if (Imm == INT32_MIN) Imm = 0;
1756 // Immediate is scaled by 4.
1757 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1758 Inst.addOperand(MCOperand::CreateImm(Imm));
1759 }
1760
Jim Grosbach7ce05792011-08-03 23:50:40 +00001761 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
1763 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001764 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1765 }
1766
1767 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1768 assert(N == 2 && "Invalid number of operands!");
1769 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1770 // The sign, shift type, and shift amount are encoded in a single operand
1771 // using the AM2 encoding helpers.
1772 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1773 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1774 PostIdxReg.ShiftTy);
1775 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001776 }
1777
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001778 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1779 assert(N == 1 && "Invalid number of operands!");
1780 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1781 }
1782
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001783 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1784 assert(N == 1 && "Invalid number of operands!");
1785 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1786 }
1787
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001788 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001789 assert(N == 1 && "Invalid number of operands!");
1790 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1791 }
1792
Jim Grosbach7636bf62011-12-02 00:35:16 +00001793 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1794 assert(N == 2 && "Invalid number of operands!");
1795 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1796 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1797 }
1798
Jim Grosbach460a9052011-10-07 23:56:00 +00001799 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1800 assert(N == 1 && "Invalid number of operands!");
1801 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1802 }
1803
1804 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1805 assert(N == 1 && "Invalid number of operands!");
1806 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1807 }
1808
1809 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1810 assert(N == 1 && "Invalid number of operands!");
1811 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1812 }
1813
Jim Grosbach0e387b22011-10-17 22:26:03 +00001814 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1815 assert(N == 1 && "Invalid number of operands!");
1816 // The immediate encodes the type of constant as well as the value.
1817 // Mask in that this is an i8 splat.
1818 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1819 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1820 }
1821
Jim Grosbachea461102011-10-17 23:09:09 +00001822 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1823 assert(N == 1 && "Invalid number of operands!");
1824 // The immediate encodes the type of constant as well as the value.
1825 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1826 unsigned Value = CE->getValue();
1827 if (Value >= 256)
1828 Value = (Value >> 8) | 0xa00;
1829 else
1830 Value |= 0x800;
1831 Inst.addOperand(MCOperand::CreateImm(Value));
1832 }
1833
Jim Grosbach6248a542011-10-18 00:22:00 +00001834 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1835 assert(N == 1 && "Invalid number of operands!");
1836 // The immediate encodes the type of constant as well as the value.
1837 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1838 unsigned Value = CE->getValue();
1839 if (Value >= 256 && Value <= 0xff00)
1840 Value = (Value >> 8) | 0x200;
1841 else if (Value > 0xffff && Value <= 0xff0000)
1842 Value = (Value >> 16) | 0x400;
1843 else if (Value > 0xffffff)
1844 Value = (Value >> 24) | 0x600;
1845 Inst.addOperand(MCOperand::CreateImm(Value));
1846 }
1847
1848 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1849 assert(N == 1 && "Invalid number of operands!");
1850 // The immediate encodes the type of constant as well as the value.
1851 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1852 unsigned Value = CE->getValue();
1853 if (Value >= 256 && Value <= 0xffff)
1854 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1855 else if (Value > 0xffff && Value <= 0xffffff)
1856 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1857 else if (Value > 0xffffff)
1858 Value = (Value >> 24) | 0x600;
1859 Inst.addOperand(MCOperand::CreateImm(Value));
1860 }
1861
Jim Grosbach9b087852011-12-19 23:51:07 +00001862 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
1863 assert(N == 1 && "Invalid number of operands!");
1864 // The immediate encodes the type of constant as well as the value.
1865 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1866 unsigned Value = ~CE->getValue();
1867 if (Value >= 256 && Value <= 0xffff)
1868 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1869 else if (Value > 0xffff && Value <= 0xffffff)
1870 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1871 else if (Value > 0xffffff)
1872 Value = (Value >> 24) | 0x600;
1873 Inst.addOperand(MCOperand::CreateImm(Value));
1874 }
1875
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001876 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1877 assert(N == 1 && "Invalid number of operands!");
1878 // The immediate encodes the type of constant as well as the value.
1879 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1880 uint64_t Value = CE->getValue();
1881 unsigned Imm = 0;
1882 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1883 Imm |= (Value & 1) << i;
1884 }
1885 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1886 }
1887
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001888 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001889
Jim Grosbach89df9962011-08-26 21:43:41 +00001890 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001891 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001892 Op->ITMask.Mask = Mask;
1893 Op->StartLoc = S;
1894 Op->EndLoc = S;
1895 return Op;
1896 }
1897
Chris Lattner3a697562010-10-28 17:20:03 +00001898 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001899 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001900 Op->CC.Val = CC;
1901 Op->StartLoc = S;
1902 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001903 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001904 }
1905
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001906 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001907 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001908 Op->Cop.Val = CopVal;
1909 Op->StartLoc = S;
1910 Op->EndLoc = S;
1911 return Op;
1912 }
1913
1914 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001915 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001916 Op->Cop.Val = CopVal;
1917 Op->StartLoc = S;
1918 Op->EndLoc = S;
1919 return Op;
1920 }
1921
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001922 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1923 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1924 Op->Cop.Val = Val;
1925 Op->StartLoc = S;
1926 Op->EndLoc = E;
1927 return Op;
1928 }
1929
Jim Grosbachd67641b2010-12-06 18:21:12 +00001930 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001931 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001932 Op->Reg.RegNum = RegNum;
1933 Op->StartLoc = S;
1934 Op->EndLoc = S;
1935 return Op;
1936 }
1937
Chris Lattner3a697562010-10-28 17:20:03 +00001938 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001939 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001940 Op->Tok.Data = Str.data();
1941 Op->Tok.Length = Str.size();
1942 Op->StartLoc = S;
1943 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001944 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001945 }
1946
Bill Wendling50d0f582010-11-18 23:43:05 +00001947 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001948 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001949 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001950 Op->StartLoc = S;
1951 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001952 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001953 }
1954
Jim Grosbache8606dc2011-07-13 17:50:29 +00001955 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1956 unsigned SrcReg,
1957 unsigned ShiftReg,
1958 unsigned ShiftImm,
1959 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001960 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001961 Op->RegShiftedReg.ShiftTy = ShTy;
1962 Op->RegShiftedReg.SrcReg = SrcReg;
1963 Op->RegShiftedReg.ShiftReg = ShiftReg;
1964 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001965 Op->StartLoc = S;
1966 Op->EndLoc = E;
1967 return Op;
1968 }
1969
Owen Anderson92a20222011-07-21 18:54:16 +00001970 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1971 unsigned SrcReg,
1972 unsigned ShiftImm,
1973 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001974 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001975 Op->RegShiftedImm.ShiftTy = ShTy;
1976 Op->RegShiftedImm.SrcReg = SrcReg;
1977 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001978 Op->StartLoc = S;
1979 Op->EndLoc = E;
1980 return Op;
1981 }
1982
Jim Grosbach580f4a92011-07-25 22:20:28 +00001983 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001984 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001985 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001986 Op->ShifterImm.isASR = isASR;
1987 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001988 Op->StartLoc = S;
1989 Op->EndLoc = E;
1990 return Op;
1991 }
1992
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001993 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001994 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001995 Op->RotImm.Imm = Imm;
1996 Op->StartLoc = S;
1997 Op->EndLoc = E;
1998 return Op;
1999 }
2000
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002001 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2002 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002003 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002004 Op->Bitfield.LSB = LSB;
2005 Op->Bitfield.Width = Width;
2006 Op->StartLoc = S;
2007 Op->EndLoc = E;
2008 return Op;
2009 }
2010
Bill Wendling7729e062010-11-09 22:44:22 +00002011 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002012 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002013 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002014 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002015
Jim Grosbachd300b942011-09-13 22:56:44 +00002016 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002017 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002018 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002019 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002020 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002021
2022 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002023 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002024 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002025 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002026 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002027 Op->StartLoc = StartLoc;
2028 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002029 return Op;
2030 }
2031
Jim Grosbach862019c2011-10-18 23:02:30 +00002032 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002033 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002034 ARMOperand *Op = new ARMOperand(k_VectorList);
2035 Op->VectorList.RegNum = RegNum;
2036 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002037 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002038 Op->StartLoc = S;
2039 Op->EndLoc = E;
2040 return Op;
2041 }
2042
Jim Grosbach98b05a52011-11-30 01:09:44 +00002043 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
2044 SMLoc S, SMLoc E) {
2045 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2046 Op->VectorList.RegNum = RegNum;
2047 Op->VectorList.Count = Count;
2048 Op->StartLoc = S;
2049 Op->EndLoc = E;
2050 return Op;
2051 }
2052
Jim Grosbach7636bf62011-12-02 00:35:16 +00002053 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002054 unsigned Index,
2055 bool isDoubleSpaced,
2056 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002057 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2058 Op->VectorList.RegNum = RegNum;
2059 Op->VectorList.Count = Count;
2060 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002061 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002062 Op->StartLoc = S;
2063 Op->EndLoc = E;
2064 return Op;
2065 }
2066
Jim Grosbach460a9052011-10-07 23:56:00 +00002067 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2068 MCContext &Ctx) {
2069 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2070 Op->VectorIndex.Val = Idx;
2071 Op->StartLoc = S;
2072 Op->EndLoc = E;
2073 return Op;
2074 }
2075
Chris Lattner3a697562010-10-28 17:20:03 +00002076 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002077 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002078 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002079 Op->StartLoc = S;
2080 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002081 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002082 }
2083
Jim Grosbach9d390362011-10-03 23:38:36 +00002084 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002085 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00002086 Op->FPImm.Val = Val;
2087 Op->StartLoc = S;
2088 Op->EndLoc = S;
2089 return Op;
2090 }
2091
Jim Grosbach7ce05792011-08-03 23:50:40 +00002092 static ARMOperand *CreateMem(unsigned BaseRegNum,
2093 const MCConstantExpr *OffsetImm,
2094 unsigned OffsetRegNum,
2095 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002096 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002097 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002098 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002099 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002100 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002101 Op->Memory.BaseRegNum = BaseRegNum;
2102 Op->Memory.OffsetImm = OffsetImm;
2103 Op->Memory.OffsetRegNum = OffsetRegNum;
2104 Op->Memory.ShiftType = ShiftType;
2105 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002106 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002107 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002108 Op->StartLoc = S;
2109 Op->EndLoc = E;
2110 return Op;
2111 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002112
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002113 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2114 ARM_AM::ShiftOpc ShiftTy,
2115 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002116 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002117 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002118 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002119 Op->PostIdxReg.isAdd = isAdd;
2120 Op->PostIdxReg.ShiftTy = ShiftTy;
2121 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002122 Op->StartLoc = S;
2123 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002124 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002125 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002126
2127 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002128 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002129 Op->MBOpt.Val = Opt;
2130 Op->StartLoc = S;
2131 Op->EndLoc = S;
2132 return Op;
2133 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002134
2135 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002136 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002137 Op->IFlags.Val = IFlags;
2138 Op->StartLoc = S;
2139 Op->EndLoc = S;
2140 return Op;
2141 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002142
2143 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002144 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002145 Op->MMask.Val = MMask;
2146 Op->StartLoc = S;
2147 Op->EndLoc = S;
2148 return Op;
2149 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002150};
2151
2152} // end anonymous namespace.
2153
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002154void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002155 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002156 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002157 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2158 << ") >";
2159 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002160 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002161 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002162 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002163 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002164 OS << "<ccout " << getReg() << ">";
2165 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002166 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002167 static const char *MaskStr[] = {
2168 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2169 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2170 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002171 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2172 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2173 break;
2174 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002175 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002176 OS << "<coprocessor number: " << getCoproc() << ">";
2177 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002178 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002179 OS << "<coprocessor register: " << getCoproc() << ">";
2180 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002181 case k_CoprocOption:
2182 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2183 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002184 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002185 OS << "<mask: " << getMSRMask() << ">";
2186 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002187 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002188 getImm()->print(OS);
2189 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002190 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002191 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2192 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002193 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002194 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002195 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002196 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002197 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002198 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002199 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2200 << PostIdxReg.RegNum;
2201 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2202 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2203 << PostIdxReg.ShiftImm;
2204 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002205 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002206 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002207 OS << "<ARM_PROC::";
2208 unsigned IFlags = getProcIFlags();
2209 for (int i=2; i >= 0; --i)
2210 if (IFlags & (1 << i))
2211 OS << ARM_PROC::IFlagsToString(1 << i);
2212 OS << ">";
2213 break;
2214 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002215 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002216 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002217 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002218 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002219 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2220 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002221 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002222 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002223 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002224 << RegShiftedReg.SrcReg << " "
2225 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2226 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002227 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002228 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002229 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002230 << RegShiftedImm.SrcReg << " "
2231 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2232 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002233 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002234 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002235 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2236 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002237 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002238 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2239 << ", width: " << Bitfield.Width << ">";
2240 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002241 case k_RegisterList:
2242 case k_DPRRegisterList:
2243 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002244 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002245
Bill Wendling5fa22a12010-11-09 23:28:44 +00002246 const SmallVectorImpl<unsigned> &RegList = getRegList();
2247 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002248 I = RegList.begin(), E = RegList.end(); I != E; ) {
2249 OS << *I;
2250 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002251 }
2252
2253 OS << ">";
2254 break;
2255 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002256 case k_VectorList:
2257 OS << "<vector_list " << VectorList.Count << " * "
2258 << VectorList.RegNum << ">";
2259 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002260 case k_VectorListAllLanes:
2261 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2262 << VectorList.RegNum << ">";
2263 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002264 case k_VectorListIndexed:
2265 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2266 << VectorList.Count << " * " << VectorList.RegNum << ">";
2267 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002268 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002269 OS << "'" << getToken() << "'";
2270 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002271 case k_VectorIndex:
2272 OS << "<vectorindex " << getVectorIndex() << ">";
2273 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002274 }
2275}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002276
2277/// @name Auto-generated Match Functions
2278/// {
2279
2280static unsigned MatchRegisterName(StringRef Name);
2281
2282/// }
2283
Bob Wilson69df7232011-02-03 21:46:10 +00002284bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2285 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002286 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002287 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002288 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002289
2290 return (RegNo == (unsigned)-1);
2291}
2292
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002293/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002294/// and if it is a register name the token is eaten and the register number is
2295/// returned. Otherwise return -1.
2296///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002297int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002298 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002299 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002300
Benjamin Kramer59085362011-11-06 20:37:06 +00002301 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002302 unsigned RegNum = MatchRegisterName(lowerCase);
2303 if (!RegNum) {
2304 RegNum = StringSwitch<unsigned>(lowerCase)
2305 .Case("r13", ARM::SP)
2306 .Case("r14", ARM::LR)
2307 .Case("r15", ARM::PC)
2308 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002309 // Additional register name aliases for 'gas' compatibility.
2310 .Case("a1", ARM::R0)
2311 .Case("a2", ARM::R1)
2312 .Case("a3", ARM::R2)
2313 .Case("a4", ARM::R3)
2314 .Case("v1", ARM::R4)
2315 .Case("v2", ARM::R5)
2316 .Case("v3", ARM::R6)
2317 .Case("v4", ARM::R7)
2318 .Case("v5", ARM::R8)
2319 .Case("v6", ARM::R9)
2320 .Case("v7", ARM::R10)
2321 .Case("v8", ARM::R11)
2322 .Case("sb", ARM::R9)
2323 .Case("sl", ARM::R10)
2324 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002325 .Default(0);
2326 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002327 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002328 // Check for aliases registered via .req. Canonicalize to lower case.
2329 // That's more consistent since register names are case insensitive, and
2330 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2331 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002332 // If no match, return failure.
2333 if (Entry == RegisterReqs.end())
2334 return -1;
2335 Parser.Lex(); // Eat identifier token.
2336 return Entry->getValue();
2337 }
Bob Wilson69df7232011-02-03 21:46:10 +00002338
Chris Lattnere5658fa2010-10-30 04:09:10 +00002339 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002340
Chris Lattnere5658fa2010-10-30 04:09:10 +00002341 return RegNum;
2342}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002343
Jim Grosbach19906722011-07-13 18:49:30 +00002344// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2345// If a recoverable error occurs, return 1. If an irrecoverable error
2346// occurs, return -1. An irrecoverable error is one where tokens have been
2347// consumed in the process of trying to parse the shifter (i.e., when it is
2348// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002349int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002350 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2351 SMLoc S = Parser.getTok().getLoc();
2352 const AsmToken &Tok = Parser.getTok();
2353 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2354
Benjamin Kramer59085362011-11-06 20:37:06 +00002355 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002356 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002357 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002358 .Case("lsl", ARM_AM::lsl)
2359 .Case("lsr", ARM_AM::lsr)
2360 .Case("asr", ARM_AM::asr)
2361 .Case("ror", ARM_AM::ror)
2362 .Case("rrx", ARM_AM::rrx)
2363 .Default(ARM_AM::no_shift);
2364
2365 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002366 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002367
Jim Grosbache8606dc2011-07-13 17:50:29 +00002368 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002369
Jim Grosbache8606dc2011-07-13 17:50:29 +00002370 // The source register for the shift has already been added to the
2371 // operand list, so we need to pop it off and combine it into the shifted
2372 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002373 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002374 if (!PrevOp->isReg())
2375 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2376 int SrcReg = PrevOp->getReg();
2377 int64_t Imm = 0;
2378 int ShiftReg = 0;
2379 if (ShiftTy == ARM_AM::rrx) {
2380 // RRX Doesn't have an explicit shift amount. The encoder expects
2381 // the shift register to be the same as the source register. Seems odd,
2382 // but OK.
2383 ShiftReg = SrcReg;
2384 } else {
2385 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002386 if (Parser.getTok().is(AsmToken::Hash) ||
2387 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002388 Parser.Lex(); // Eat hash.
2389 SMLoc ImmLoc = Parser.getTok().getLoc();
2390 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002391 if (getParser().ParseExpression(ShiftExpr)) {
2392 Error(ImmLoc, "invalid immediate shift value");
2393 return -1;
2394 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002395 // The expression must be evaluatable as an immediate.
2396 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002397 if (!CE) {
2398 Error(ImmLoc, "invalid immediate shift value");
2399 return -1;
2400 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002401 // Range check the immediate.
2402 // lsl, ror: 0 <= imm <= 31
2403 // lsr, asr: 0 <= imm <= 32
2404 Imm = CE->getValue();
2405 if (Imm < 0 ||
2406 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2407 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002408 Error(ImmLoc, "immediate shift value out of range");
2409 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002410 }
2411 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002412 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002413 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002414 if (ShiftReg == -1) {
2415 Error (L, "expected immediate or register in shift operand");
2416 return -1;
2417 }
2418 } else {
2419 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002420 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002421 return -1;
2422 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002423 }
2424
Owen Anderson92a20222011-07-21 18:54:16 +00002425 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2426 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002427 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002428 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002429 else
2430 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2431 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002432
Jim Grosbach19906722011-07-13 18:49:30 +00002433 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002434}
2435
2436
Bill Wendling50d0f582010-11-18 23:43:05 +00002437/// Try to parse a register name. The token must be an Identifier when called.
2438/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2439/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002440///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002441/// TODO this is likely to change to allow different register types and or to
2442/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002443bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002444tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002445 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002446 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002447 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002448 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002449
Bill Wendling50d0f582010-11-18 23:43:05 +00002450 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002451
Chris Lattnere5658fa2010-10-30 04:09:10 +00002452 const AsmToken &ExclaimTok = Parser.getTok();
2453 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002454 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2455 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002456 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002457 return false;
2458 }
2459
2460 // Also check for an index operand. This is only legal for vector registers,
2461 // but that'll get caught OK in operand matching, so we don't need to
2462 // explicitly filter everything else out here.
2463 if (Parser.getTok().is(AsmToken::LBrac)) {
2464 SMLoc SIdx = Parser.getTok().getLoc();
2465 Parser.Lex(); // Eat left bracket token.
2466
2467 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002468 if (getParser().ParseExpression(ImmVal))
2469 return MatchOperand_ParseFail;
2470 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2471 if (!MCE) {
2472 TokError("immediate value expected for vector index");
2473 return MatchOperand_ParseFail;
2474 }
2475
2476 SMLoc E = Parser.getTok().getLoc();
2477 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2478 Error(E, "']' expected");
2479 return MatchOperand_ParseFail;
2480 }
2481
2482 Parser.Lex(); // Eat right bracket token.
2483
2484 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2485 SIdx, E,
2486 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002487 }
2488
Bill Wendling50d0f582010-11-18 23:43:05 +00002489 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002490}
2491
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002492/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2493/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2494/// "c5", ...
2495static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002496 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2497 // but efficient.
2498 switch (Name.size()) {
2499 default: break;
2500 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002501 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002502 return -1;
2503 switch (Name[1]) {
2504 default: return -1;
2505 case '0': return 0;
2506 case '1': return 1;
2507 case '2': return 2;
2508 case '3': return 3;
2509 case '4': return 4;
2510 case '5': return 5;
2511 case '6': return 6;
2512 case '7': return 7;
2513 case '8': return 8;
2514 case '9': return 9;
2515 }
2516 break;
2517 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002518 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002519 return -1;
2520 switch (Name[2]) {
2521 default: return -1;
2522 case '0': return 10;
2523 case '1': return 11;
2524 case '2': return 12;
2525 case '3': return 13;
2526 case '4': return 14;
2527 case '5': return 15;
2528 }
2529 break;
2530 }
2531
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002532 return -1;
2533}
2534
Jim Grosbach89df9962011-08-26 21:43:41 +00002535/// parseITCondCode - Try to parse a condition code for an IT instruction.
2536ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2537parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2538 SMLoc S = Parser.getTok().getLoc();
2539 const AsmToken &Tok = Parser.getTok();
2540 if (!Tok.is(AsmToken::Identifier))
2541 return MatchOperand_NoMatch;
2542 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2543 .Case("eq", ARMCC::EQ)
2544 .Case("ne", ARMCC::NE)
2545 .Case("hs", ARMCC::HS)
2546 .Case("cs", ARMCC::HS)
2547 .Case("lo", ARMCC::LO)
2548 .Case("cc", ARMCC::LO)
2549 .Case("mi", ARMCC::MI)
2550 .Case("pl", ARMCC::PL)
2551 .Case("vs", ARMCC::VS)
2552 .Case("vc", ARMCC::VC)
2553 .Case("hi", ARMCC::HI)
2554 .Case("ls", ARMCC::LS)
2555 .Case("ge", ARMCC::GE)
2556 .Case("lt", ARMCC::LT)
2557 .Case("gt", ARMCC::GT)
2558 .Case("le", ARMCC::LE)
2559 .Case("al", ARMCC::AL)
2560 .Default(~0U);
2561 if (CC == ~0U)
2562 return MatchOperand_NoMatch;
2563 Parser.Lex(); // Eat the token.
2564
2565 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2566
2567 return MatchOperand_Success;
2568}
2569
Jim Grosbach43904292011-07-25 20:14:50 +00002570/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002571/// token must be an Identifier when called, and if it is a coprocessor
2572/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002573ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002574parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002575 SMLoc S = Parser.getTok().getLoc();
2576 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002577 if (Tok.isNot(AsmToken::Identifier))
2578 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002579
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002580 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002581 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002582 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002583
2584 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002585 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002586 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002587}
2588
Jim Grosbach43904292011-07-25 20:14:50 +00002589/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002590/// token must be an Identifier when called, and if it is a coprocessor
2591/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002592ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002593parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002594 SMLoc S = Parser.getTok().getLoc();
2595 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002596 if (Tok.isNot(AsmToken::Identifier))
2597 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002598
2599 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2600 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002601 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002602
2603 Parser.Lex(); // Eat identifier token.
2604 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002605 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002606}
2607
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002608/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2609/// coproc_option : '{' imm0_255 '}'
2610ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2611parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2612 SMLoc S = Parser.getTok().getLoc();
2613
2614 // If this isn't a '{', this isn't a coprocessor immediate operand.
2615 if (Parser.getTok().isNot(AsmToken::LCurly))
2616 return MatchOperand_NoMatch;
2617 Parser.Lex(); // Eat the '{'
2618
2619 const MCExpr *Expr;
2620 SMLoc Loc = Parser.getTok().getLoc();
2621 if (getParser().ParseExpression(Expr)) {
2622 Error(Loc, "illegal expression");
2623 return MatchOperand_ParseFail;
2624 }
2625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2626 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2627 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2628 return MatchOperand_ParseFail;
2629 }
2630 int Val = CE->getValue();
2631
2632 // Check for and consume the closing '}'
2633 if (Parser.getTok().isNot(AsmToken::RCurly))
2634 return MatchOperand_ParseFail;
2635 SMLoc E = Parser.getTok().getLoc();
2636 Parser.Lex(); // Eat the '}'
2637
2638 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2639 return MatchOperand_Success;
2640}
2641
Jim Grosbachd0588e22011-09-14 18:08:35 +00002642// For register list parsing, we need to map from raw GPR register numbering
2643// to the enumeration values. The enumeration values aren't sorted by
2644// register number due to our using "sp", "lr" and "pc" as canonical names.
2645static unsigned getNextRegister(unsigned Reg) {
2646 // If this is a GPR, we need to do it manually, otherwise we can rely
2647 // on the sort ordering of the enumeration since the other reg-classes
2648 // are sane.
2649 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2650 return Reg + 1;
2651 switch(Reg) {
2652 default: assert(0 && "Invalid GPR number!");
2653 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2654 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2655 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2656 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2657 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2658 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2659 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2660 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2661 }
2662}
2663
Jim Grosbachce485e72011-11-11 21:27:40 +00002664// Return the low-subreg of a given Q register.
2665static unsigned getDRegFromQReg(unsigned QReg) {
2666 switch (QReg) {
2667 default: llvm_unreachable("expected a Q register!");
2668 case ARM::Q0: return ARM::D0;
2669 case ARM::Q1: return ARM::D2;
2670 case ARM::Q2: return ARM::D4;
2671 case ARM::Q3: return ARM::D6;
2672 case ARM::Q4: return ARM::D8;
2673 case ARM::Q5: return ARM::D10;
2674 case ARM::Q6: return ARM::D12;
2675 case ARM::Q7: return ARM::D14;
2676 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002677 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002678 case ARM::Q10: return ARM::D20;
2679 case ARM::Q11: return ARM::D22;
2680 case ARM::Q12: return ARM::D24;
2681 case ARM::Q13: return ARM::D26;
2682 case ARM::Q14: return ARM::D28;
2683 case ARM::Q15: return ARM::D30;
2684 }
2685}
2686
Jim Grosbachd0588e22011-09-14 18:08:35 +00002687/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002688bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002689parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002690 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002691 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002692 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002693 Parser.Lex(); // Eat '{' token.
2694 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002695
Jim Grosbachd0588e22011-09-14 18:08:35 +00002696 // Check the first register in the list to see what register class
2697 // this is a list of.
2698 int Reg = tryParseRegister();
2699 if (Reg == -1)
2700 return Error(RegLoc, "register expected");
2701
Jim Grosbachce485e72011-11-11 21:27:40 +00002702 // The reglist instructions have at most 16 registers, so reserve
2703 // space for that many.
2704 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2705
2706 // Allow Q regs and just interpret them as the two D sub-registers.
2707 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2708 Reg = getDRegFromQReg(Reg);
2709 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2710 ++Reg;
2711 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002712 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002713 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2714 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2715 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2716 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2717 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2718 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2719 else
2720 return Error(RegLoc, "invalid register in register list");
2721
Jim Grosbachce485e72011-11-11 21:27:40 +00002722 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002723 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002724
Jim Grosbachd0588e22011-09-14 18:08:35 +00002725 // This starts immediately after the first register token in the list,
2726 // so we can see either a comma or a minus (range separator) as a legal
2727 // next token.
2728 while (Parser.getTok().is(AsmToken::Comma) ||
2729 Parser.getTok().is(AsmToken::Minus)) {
2730 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002731 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002732 SMLoc EndLoc = Parser.getTok().getLoc();
2733 int EndReg = tryParseRegister();
2734 if (EndReg == -1)
2735 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002736 // Allow Q regs and just interpret them as the two D sub-registers.
2737 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2738 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002739 // If the register is the same as the start reg, there's nothing
2740 // more to do.
2741 if (Reg == EndReg)
2742 continue;
2743 // The register must be in the same register class as the first.
2744 if (!RC->contains(EndReg))
2745 return Error(EndLoc, "invalid register in register list");
2746 // Ranges must go from low to high.
2747 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2748 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002749
Jim Grosbachd0588e22011-09-14 18:08:35 +00002750 // Add all the registers in the range to the register list.
2751 while (Reg != EndReg) {
2752 Reg = getNextRegister(Reg);
2753 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2754 }
2755 continue;
2756 }
2757 Parser.Lex(); // Eat the comma.
2758 RegLoc = Parser.getTok().getLoc();
2759 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002760 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002761 Reg = tryParseRegister();
2762 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002763 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002764 // Allow Q regs and just interpret them as the two D sub-registers.
2765 bool isQReg = false;
2766 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2767 Reg = getDRegFromQReg(Reg);
2768 isQReg = true;
2769 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002770 // The register must be in the same register class as the first.
2771 if (!RC->contains(Reg))
2772 return Error(RegLoc, "invalid register in register list");
2773 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002774 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002775 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002776 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2777 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2778 ") in register list");
2779 continue;
2780 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002781 // VFP register lists must also be contiguous.
2782 // It's OK to use the enumeration values directly here rather, as the
2783 // VFP register classes have the enum sorted properly.
2784 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2785 Reg != OldReg + 1)
2786 return Error(RegLoc, "non-contiguous register range");
2787 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002788 if (isQReg)
2789 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002790 }
2791
Jim Grosbachd0588e22011-09-14 18:08:35 +00002792 SMLoc E = Parser.getTok().getLoc();
2793 if (Parser.getTok().isNot(AsmToken::RCurly))
2794 return Error(E, "'}' expected");
2795 Parser.Lex(); // Eat '}' token.
2796
Jim Grosbach27debd62011-12-13 21:48:29 +00002797 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002798 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002799
2800 // The ARM system instruction variants for LDM/STM have a '^' token here.
2801 if (Parser.getTok().is(AsmToken::Caret)) {
2802 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2803 Parser.Lex(); // Eat '^' token.
2804 }
2805
Bill Wendling50d0f582010-11-18 23:43:05 +00002806 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002807}
2808
Jim Grosbach98b05a52011-11-30 01:09:44 +00002809// Helper function to parse the lane index for vector lists.
2810ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002811parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2812 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002813 if (Parser.getTok().is(AsmToken::LBrac)) {
2814 Parser.Lex(); // Eat the '['.
2815 if (Parser.getTok().is(AsmToken::RBrac)) {
2816 // "Dn[]" is the 'all lanes' syntax.
2817 LaneKind = AllLanes;
2818 Parser.Lex(); // Eat the ']'.
2819 return MatchOperand_Success;
2820 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002821 if (Parser.getTok().is(AsmToken::Integer)) {
2822 int64_t Val = Parser.getTok().getIntVal();
2823 // Make this range check context sensitive for .8, .16, .32.
2824 if (Val < 0 && Val > 7)
2825 Error(Parser.getTok().getLoc(), "lane index out of range");
2826 Index = Val;
2827 LaneKind = IndexedLane;
2828 Parser.Lex(); // Eat the token;
2829 if (Parser.getTok().isNot(AsmToken::RBrac))
2830 Error(Parser.getTok().getLoc(), "']' expected");
2831 Parser.Lex(); // Eat the ']'.
2832 return MatchOperand_Success;
2833 }
2834 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002835 return MatchOperand_ParseFail;
2836 }
2837 LaneKind = NoLanes;
2838 return MatchOperand_Success;
2839}
2840
Jim Grosbach862019c2011-10-18 23:02:30 +00002841// parse a vector register list
2842ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2843parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002844 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002845 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002846 SMLoc S = Parser.getTok().getLoc();
2847 // As an extension (to match gas), support a plain D register or Q register
2848 // (without encosing curly braces) as a single or double entry list,
2849 // respectively.
2850 if (Parser.getTok().is(AsmToken::Identifier)) {
2851 int Reg = tryParseRegister();
2852 if (Reg == -1)
2853 return MatchOperand_NoMatch;
2854 SMLoc E = Parser.getTok().getLoc();
2855 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002856 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002857 if (Res != MatchOperand_Success)
2858 return Res;
2859 switch (LaneKind) {
2860 default:
2861 assert(0 && "unexpected lane kind!");
2862 case NoLanes:
2863 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002864 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002865 break;
2866 case AllLanes:
2867 E = Parser.getTok().getLoc();
2868 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2869 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002870 case IndexedLane:
2871 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002872 LaneIndex,
2873 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002874 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002875 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002876 return MatchOperand_Success;
2877 }
2878 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2879 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002880 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002881 if (Res != MatchOperand_Success)
2882 return Res;
2883 switch (LaneKind) {
2884 default:
2885 assert(0 && "unexpected lane kind!");
2886 case NoLanes:
2887 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002888 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00002889 break;
2890 case AllLanes:
2891 E = Parser.getTok().getLoc();
2892 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2893 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002894 case IndexedLane:
2895 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002896 LaneIndex,
2897 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00002898 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002899 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002900 return MatchOperand_Success;
2901 }
2902 Error(S, "vector register expected");
2903 return MatchOperand_ParseFail;
2904 }
2905
2906 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002907 return MatchOperand_NoMatch;
2908
Jim Grosbach862019c2011-10-18 23:02:30 +00002909 Parser.Lex(); // Eat '{' token.
2910 SMLoc RegLoc = Parser.getTok().getLoc();
2911
2912 int Reg = tryParseRegister();
2913 if (Reg == -1) {
2914 Error(RegLoc, "register expected");
2915 return MatchOperand_ParseFail;
2916 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002917 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00002918 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002919 unsigned FirstReg = Reg;
2920 // The list is of D registers, but we also allow Q regs and just interpret
2921 // them as the two D sub-registers.
2922 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2923 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002924 Spacing = 1; // double-spacing requires explicit D registers, otherwise
2925 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002926 ++Reg;
2927 ++Count;
2928 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002929 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002930 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002931
Jim Grosbache43862b2011-11-15 23:19:15 +00002932 while (Parser.getTok().is(AsmToken::Comma) ||
2933 Parser.getTok().is(AsmToken::Minus)) {
2934 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002935 if (!Spacing)
2936 Spacing = 1; // Register range implies a single spaced list.
2937 else if (Spacing == 2) {
2938 Error(Parser.getTok().getLoc(),
2939 "sequential registers in double spaced list");
2940 return MatchOperand_ParseFail;
2941 }
Jim Grosbache43862b2011-11-15 23:19:15 +00002942 Parser.Lex(); // Eat the minus.
2943 SMLoc EndLoc = Parser.getTok().getLoc();
2944 int EndReg = tryParseRegister();
2945 if (EndReg == -1) {
2946 Error(EndLoc, "register expected");
2947 return MatchOperand_ParseFail;
2948 }
2949 // Allow Q regs and just interpret them as the two D sub-registers.
2950 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2951 EndReg = getDRegFromQReg(EndReg) + 1;
2952 // If the register is the same as the start reg, there's nothing
2953 // more to do.
2954 if (Reg == EndReg)
2955 continue;
2956 // The register must be in the same register class as the first.
2957 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2958 Error(EndLoc, "invalid register in register list");
2959 return MatchOperand_ParseFail;
2960 }
2961 // Ranges must go from low to high.
2962 if (Reg > EndReg) {
2963 Error(EndLoc, "bad range in register list");
2964 return MatchOperand_ParseFail;
2965 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002966 // Parse the lane specifier if present.
2967 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002968 unsigned NextLaneIndex;
2969 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002970 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002971 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002972 Error(EndLoc, "mismatched lane index in register list");
2973 return MatchOperand_ParseFail;
2974 }
2975 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002976
2977 // Add all the registers in the range to the register list.
2978 Count += EndReg - Reg;
2979 Reg = EndReg;
2980 continue;
2981 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002982 Parser.Lex(); // Eat the comma.
2983 RegLoc = Parser.getTok().getLoc();
2984 int OldReg = Reg;
2985 Reg = tryParseRegister();
2986 if (Reg == -1) {
2987 Error(RegLoc, "register expected");
2988 return MatchOperand_ParseFail;
2989 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002990 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002991 // It's OK to use the enumeration values directly here rather, as the
2992 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002993 //
2994 // The list is of D registers, but we also allow Q regs and just interpret
2995 // them as the two D sub-registers.
2996 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002997 if (!Spacing)
2998 Spacing = 1; // Register range implies a single spaced list.
2999 else if (Spacing == 2) {
3000 Error(RegLoc,
3001 "invalid register in double-spaced list (must be 'D' register')");
3002 return MatchOperand_ParseFail;
3003 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003004 Reg = getDRegFromQReg(Reg);
3005 if (Reg != OldReg + 1) {
3006 Error(RegLoc, "non-contiguous register range");
3007 return MatchOperand_ParseFail;
3008 }
3009 ++Reg;
3010 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003011 // Parse the lane specifier if present.
3012 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003013 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003014 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003015 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003016 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003017 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003018 Error(EndLoc, "mismatched lane index in register list");
3019 return MatchOperand_ParseFail;
3020 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003021 continue;
3022 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003023 // Normal D register.
3024 // Figure out the register spacing (single or double) of the list if
3025 // we don't know it already.
3026 if (!Spacing)
3027 Spacing = 1 + (Reg == OldReg + 2);
3028
3029 // Just check that it's contiguous and keep going.
3030 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003031 Error(RegLoc, "non-contiguous register range");
3032 return MatchOperand_ParseFail;
3033 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003034 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003035 // Parse the lane specifier if present.
3036 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003037 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003038 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003039 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003040 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003041 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003042 Error(EndLoc, "mismatched lane index in register list");
3043 return MatchOperand_ParseFail;
3044 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003045 }
3046
3047 SMLoc E = Parser.getTok().getLoc();
3048 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3049 Error(E, "'}' expected");
3050 return MatchOperand_ParseFail;
3051 }
3052 Parser.Lex(); // Eat '}' token.
3053
Jim Grosbach98b05a52011-11-30 01:09:44 +00003054 switch (LaneKind) {
3055 default:
3056 assert(0 && "unexpected lane kind in register list.");
3057 case NoLanes:
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003058 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3059 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003060 break;
3061 case AllLanes:
3062 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
3063 S, E));
3064 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003065 case IndexedLane:
3066 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003067 LaneIndex,
3068 (Spacing == 2),
3069 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003070 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003071 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003072 return MatchOperand_Success;
3073}
3074
Jim Grosbach43904292011-07-25 20:14:50 +00003075/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003076ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003077parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003078 SMLoc S = Parser.getTok().getLoc();
3079 const AsmToken &Tok = Parser.getTok();
3080 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3081 StringRef OptStr = Tok.getString();
3082
3083 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3084 .Case("sy", ARM_MB::SY)
3085 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003086 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003087 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003088 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003089 .Case("ishst", ARM_MB::ISHST)
3090 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003091 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003092 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003093 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003094 .Case("osh", ARM_MB::OSH)
3095 .Case("oshst", ARM_MB::OSHST)
3096 .Default(~0U);
3097
3098 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003099 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003100
3101 Parser.Lex(); // Eat identifier token.
3102 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003103 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003104}
3105
Jim Grosbach43904292011-07-25 20:14:50 +00003106/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003107ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003108parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003109 SMLoc S = Parser.getTok().getLoc();
3110 const AsmToken &Tok = Parser.getTok();
3111 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3112 StringRef IFlagsStr = Tok.getString();
3113
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003114 // An iflags string of "none" is interpreted to mean that none of the AIF
3115 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003116 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003117 if (IFlagsStr != "none") {
3118 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3119 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3120 .Case("a", ARM_PROC::A)
3121 .Case("i", ARM_PROC::I)
3122 .Case("f", ARM_PROC::F)
3123 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003124
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003125 // If some specific iflag is already set, it means that some letter is
3126 // present more than once, this is not acceptable.
3127 if (Flag == ~0U || (IFlags & Flag))
3128 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003129
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003130 IFlags |= Flag;
3131 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003132 }
3133
3134 Parser.Lex(); // Eat identifier token.
3135 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3136 return MatchOperand_Success;
3137}
3138
Jim Grosbach43904292011-07-25 20:14:50 +00003139/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003140ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003141parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003142 SMLoc S = Parser.getTok().getLoc();
3143 const AsmToken &Tok = Parser.getTok();
3144 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3145 StringRef Mask = Tok.getString();
3146
James Molloyacad68d2011-09-28 14:21:38 +00003147 if (isMClass()) {
3148 // See ARMv6-M 10.1.1
3149 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3150 .Case("apsr", 0)
3151 .Case("iapsr", 1)
3152 .Case("eapsr", 2)
3153 .Case("xpsr", 3)
3154 .Case("ipsr", 5)
3155 .Case("epsr", 6)
3156 .Case("iepsr", 7)
3157 .Case("msp", 8)
3158 .Case("psp", 9)
3159 .Case("primask", 16)
3160 .Case("basepri", 17)
3161 .Case("basepri_max", 18)
3162 .Case("faultmask", 19)
3163 .Case("control", 20)
3164 .Default(~0U);
3165
3166 if (FlagsVal == ~0U)
3167 return MatchOperand_NoMatch;
3168
3169 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3170 // basepri, basepri_max and faultmask only valid for V7m.
3171 return MatchOperand_NoMatch;
3172
3173 Parser.Lex(); // Eat identifier token.
3174 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3175 return MatchOperand_Success;
3176 }
3177
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003178 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3179 size_t Start = 0, Next = Mask.find('_');
3180 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003181 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003182 if (Next != StringRef::npos)
3183 Flags = Mask.slice(Next+1, Mask.size());
3184
3185 // FlagsVal contains the complete mask:
3186 // 3-0: Mask
3187 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3188 unsigned FlagsVal = 0;
3189
3190 if (SpecReg == "apsr") {
3191 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003192 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003193 .Case("g", 0x4) // same as CPSR_s
3194 .Case("nzcvqg", 0xc) // same as CPSR_fs
3195 .Default(~0U);
3196
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003197 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003198 if (!Flags.empty())
3199 return MatchOperand_NoMatch;
3200 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003201 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003202 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003203 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003204 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3205 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003206 for (int i = 0, e = Flags.size(); i != e; ++i) {
3207 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3208 .Case("c", 1)
3209 .Case("x", 2)
3210 .Case("s", 4)
3211 .Case("f", 8)
3212 .Default(~0U);
3213
3214 // If some specific flag is already set, it means that some letter is
3215 // present more than once, this is not acceptable.
3216 if (FlagsVal == ~0U || (FlagsVal & Flag))
3217 return MatchOperand_NoMatch;
3218 FlagsVal |= Flag;
3219 }
3220 } else // No match for special register.
3221 return MatchOperand_NoMatch;
3222
Owen Anderson7784f1d2011-10-21 18:43:28 +00003223 // Special register without flags is NOT equivalent to "fc" flags.
3224 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3225 // two lines would enable gas compatibility at the expense of breaking
3226 // round-tripping.
3227 //
3228 // if (!FlagsVal)
3229 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003230
3231 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3232 if (SpecReg == "spsr")
3233 FlagsVal |= 16;
3234
3235 Parser.Lex(); // Eat identifier token.
3236 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3237 return MatchOperand_Success;
3238}
3239
Jim Grosbachf6c05252011-07-21 17:23:04 +00003240ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3241parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3242 int Low, int High) {
3243 const AsmToken &Tok = Parser.getTok();
3244 if (Tok.isNot(AsmToken::Identifier)) {
3245 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3246 return MatchOperand_ParseFail;
3247 }
3248 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003249 std::string LowerOp = Op.lower();
3250 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003251 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3252 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3253 return MatchOperand_ParseFail;
3254 }
3255 Parser.Lex(); // Eat shift type token.
3256
3257 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003258 if (Parser.getTok().isNot(AsmToken::Hash) &&
3259 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003260 Error(Parser.getTok().getLoc(), "'#' expected");
3261 return MatchOperand_ParseFail;
3262 }
3263 Parser.Lex(); // Eat hash token.
3264
3265 const MCExpr *ShiftAmount;
3266 SMLoc Loc = Parser.getTok().getLoc();
3267 if (getParser().ParseExpression(ShiftAmount)) {
3268 Error(Loc, "illegal expression");
3269 return MatchOperand_ParseFail;
3270 }
3271 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3272 if (!CE) {
3273 Error(Loc, "constant expression expected");
3274 return MatchOperand_ParseFail;
3275 }
3276 int Val = CE->getValue();
3277 if (Val < Low || Val > High) {
3278 Error(Loc, "immediate value out of range");
3279 return MatchOperand_ParseFail;
3280 }
3281
3282 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3283
3284 return MatchOperand_Success;
3285}
3286
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003287ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3288parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3289 const AsmToken &Tok = Parser.getTok();
3290 SMLoc S = Tok.getLoc();
3291 if (Tok.isNot(AsmToken::Identifier)) {
3292 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3293 return MatchOperand_ParseFail;
3294 }
3295 int Val = StringSwitch<int>(Tok.getString())
3296 .Case("be", 1)
3297 .Case("le", 0)
3298 .Default(-1);
3299 Parser.Lex(); // Eat the token.
3300
3301 if (Val == -1) {
3302 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3303 return MatchOperand_ParseFail;
3304 }
3305 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3306 getContext()),
3307 S, Parser.getTok().getLoc()));
3308 return MatchOperand_Success;
3309}
3310
Jim Grosbach580f4a92011-07-25 22:20:28 +00003311/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3312/// instructions. Legal values are:
3313/// lsl #n 'n' in [0,31]
3314/// asr #n 'n' in [1,32]
3315/// n == 32 encoded as n == 0.
3316ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3317parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3318 const AsmToken &Tok = Parser.getTok();
3319 SMLoc S = Tok.getLoc();
3320 if (Tok.isNot(AsmToken::Identifier)) {
3321 Error(S, "shift operator 'asr' or 'lsl' expected");
3322 return MatchOperand_ParseFail;
3323 }
3324 StringRef ShiftName = Tok.getString();
3325 bool isASR;
3326 if (ShiftName == "lsl" || ShiftName == "LSL")
3327 isASR = false;
3328 else if (ShiftName == "asr" || ShiftName == "ASR")
3329 isASR = true;
3330 else {
3331 Error(S, "shift operator 'asr' or 'lsl' expected");
3332 return MatchOperand_ParseFail;
3333 }
3334 Parser.Lex(); // Eat the operator.
3335
3336 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003337 if (Parser.getTok().isNot(AsmToken::Hash) &&
3338 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003339 Error(Parser.getTok().getLoc(), "'#' expected");
3340 return MatchOperand_ParseFail;
3341 }
3342 Parser.Lex(); // Eat hash token.
3343
3344 const MCExpr *ShiftAmount;
3345 SMLoc E = Parser.getTok().getLoc();
3346 if (getParser().ParseExpression(ShiftAmount)) {
3347 Error(E, "malformed shift expression");
3348 return MatchOperand_ParseFail;
3349 }
3350 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3351 if (!CE) {
3352 Error(E, "shift amount must be an immediate");
3353 return MatchOperand_ParseFail;
3354 }
3355
3356 int64_t Val = CE->getValue();
3357 if (isASR) {
3358 // Shift amount must be in [1,32]
3359 if (Val < 1 || Val > 32) {
3360 Error(E, "'asr' shift amount must be in range [1,32]");
3361 return MatchOperand_ParseFail;
3362 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003363 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3364 if (isThumb() && Val == 32) {
3365 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3366 return MatchOperand_ParseFail;
3367 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003368 if (Val == 32) Val = 0;
3369 } else {
3370 // Shift amount must be in [1,32]
3371 if (Val < 0 || Val > 31) {
3372 Error(E, "'lsr' shift amount must be in range [0,31]");
3373 return MatchOperand_ParseFail;
3374 }
3375 }
3376
3377 E = Parser.getTok().getLoc();
3378 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3379
3380 return MatchOperand_Success;
3381}
3382
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003383/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3384/// of instructions. Legal values are:
3385/// ror #n 'n' in {0, 8, 16, 24}
3386ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3387parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3388 const AsmToken &Tok = Parser.getTok();
3389 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003390 if (Tok.isNot(AsmToken::Identifier))
3391 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003392 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003393 if (ShiftName != "ror" && ShiftName != "ROR")
3394 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003395 Parser.Lex(); // Eat the operator.
3396
3397 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003398 if (Parser.getTok().isNot(AsmToken::Hash) &&
3399 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003400 Error(Parser.getTok().getLoc(), "'#' expected");
3401 return MatchOperand_ParseFail;
3402 }
3403 Parser.Lex(); // Eat hash token.
3404
3405 const MCExpr *ShiftAmount;
3406 SMLoc E = Parser.getTok().getLoc();
3407 if (getParser().ParseExpression(ShiftAmount)) {
3408 Error(E, "malformed rotate expression");
3409 return MatchOperand_ParseFail;
3410 }
3411 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3412 if (!CE) {
3413 Error(E, "rotate amount must be an immediate");
3414 return MatchOperand_ParseFail;
3415 }
3416
3417 int64_t Val = CE->getValue();
3418 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3419 // normally, zero is represented in asm by omitting the rotate operand
3420 // entirely.
3421 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3422 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3423 return MatchOperand_ParseFail;
3424 }
3425
3426 E = Parser.getTok().getLoc();
3427 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3428
3429 return MatchOperand_Success;
3430}
3431
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003432ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3433parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3434 SMLoc S = Parser.getTok().getLoc();
3435 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003436 if (Parser.getTok().isNot(AsmToken::Hash) &&
3437 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003438 Error(Parser.getTok().getLoc(), "'#' expected");
3439 return MatchOperand_ParseFail;
3440 }
3441 Parser.Lex(); // Eat hash token.
3442
3443 const MCExpr *LSBExpr;
3444 SMLoc E = Parser.getTok().getLoc();
3445 if (getParser().ParseExpression(LSBExpr)) {
3446 Error(E, "malformed immediate expression");
3447 return MatchOperand_ParseFail;
3448 }
3449 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3450 if (!CE) {
3451 Error(E, "'lsb' operand must be an immediate");
3452 return MatchOperand_ParseFail;
3453 }
3454
3455 int64_t LSB = CE->getValue();
3456 // The LSB must be in the range [0,31]
3457 if (LSB < 0 || LSB > 31) {
3458 Error(E, "'lsb' operand must be in the range [0,31]");
3459 return MatchOperand_ParseFail;
3460 }
3461 E = Parser.getTok().getLoc();
3462
3463 // Expect another immediate operand.
3464 if (Parser.getTok().isNot(AsmToken::Comma)) {
3465 Error(Parser.getTok().getLoc(), "too few operands");
3466 return MatchOperand_ParseFail;
3467 }
3468 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003469 if (Parser.getTok().isNot(AsmToken::Hash) &&
3470 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003471 Error(Parser.getTok().getLoc(), "'#' expected");
3472 return MatchOperand_ParseFail;
3473 }
3474 Parser.Lex(); // Eat hash token.
3475
3476 const MCExpr *WidthExpr;
3477 if (getParser().ParseExpression(WidthExpr)) {
3478 Error(E, "malformed immediate expression");
3479 return MatchOperand_ParseFail;
3480 }
3481 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3482 if (!CE) {
3483 Error(E, "'width' operand must be an immediate");
3484 return MatchOperand_ParseFail;
3485 }
3486
3487 int64_t Width = CE->getValue();
3488 // The LSB must be in the range [1,32-lsb]
3489 if (Width < 1 || Width > 32 - LSB) {
3490 Error(E, "'width' operand must be in the range [1,32-lsb]");
3491 return MatchOperand_ParseFail;
3492 }
3493 E = Parser.getTok().getLoc();
3494
3495 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3496
3497 return MatchOperand_Success;
3498}
3499
Jim Grosbach7ce05792011-08-03 23:50:40 +00003500ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3501parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3502 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003503 // postidx_reg := '+' register {, shift}
3504 // | '-' register {, shift}
3505 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003506
3507 // This method must return MatchOperand_NoMatch without consuming any tokens
3508 // in the case where there is no match, as other alternatives take other
3509 // parse methods.
3510 AsmToken Tok = Parser.getTok();
3511 SMLoc S = Tok.getLoc();
3512 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003513 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003514 int Reg = -1;
3515 if (Tok.is(AsmToken::Plus)) {
3516 Parser.Lex(); // Eat the '+' token.
3517 haveEaten = true;
3518 } else if (Tok.is(AsmToken::Minus)) {
3519 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003520 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003521 haveEaten = true;
3522 }
3523 if (Parser.getTok().is(AsmToken::Identifier))
3524 Reg = tryParseRegister();
3525 if (Reg == -1) {
3526 if (!haveEaten)
3527 return MatchOperand_NoMatch;
3528 Error(Parser.getTok().getLoc(), "register expected");
3529 return MatchOperand_ParseFail;
3530 }
3531 SMLoc E = Parser.getTok().getLoc();
3532
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003533 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3534 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003535 if (Parser.getTok().is(AsmToken::Comma)) {
3536 Parser.Lex(); // Eat the ','.
3537 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3538 return MatchOperand_ParseFail;
3539 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003540
3541 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3542 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003543
3544 return MatchOperand_Success;
3545}
3546
Jim Grosbach251bf252011-08-10 21:56:18 +00003547ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3548parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3549 // Check for a post-index addressing register operand. Specifically:
3550 // am3offset := '+' register
3551 // | '-' register
3552 // | register
3553 // | # imm
3554 // | # + imm
3555 // | # - imm
3556
3557 // This method must return MatchOperand_NoMatch without consuming any tokens
3558 // in the case where there is no match, as other alternatives take other
3559 // parse methods.
3560 AsmToken Tok = Parser.getTok();
3561 SMLoc S = Tok.getLoc();
3562
3563 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003564 if (Parser.getTok().is(AsmToken::Hash) ||
3565 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003566 Parser.Lex(); // Eat the '#'.
3567 // Explicitly look for a '-', as we need to encode negative zero
3568 // differently.
3569 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3570 const MCExpr *Offset;
3571 if (getParser().ParseExpression(Offset))
3572 return MatchOperand_ParseFail;
3573 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3574 if (!CE) {
3575 Error(S, "constant expression expected");
3576 return MatchOperand_ParseFail;
3577 }
3578 SMLoc E = Tok.getLoc();
3579 // Negative zero is encoded as the flag value INT32_MIN.
3580 int32_t Val = CE->getValue();
3581 if (isNegative && Val == 0)
3582 Val = INT32_MIN;
3583
3584 Operands.push_back(
3585 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3586
3587 return MatchOperand_Success;
3588 }
3589
3590
3591 bool haveEaten = false;
3592 bool isAdd = true;
3593 int Reg = -1;
3594 if (Tok.is(AsmToken::Plus)) {
3595 Parser.Lex(); // Eat the '+' token.
3596 haveEaten = true;
3597 } else if (Tok.is(AsmToken::Minus)) {
3598 Parser.Lex(); // Eat the '-' token.
3599 isAdd = false;
3600 haveEaten = true;
3601 }
3602 if (Parser.getTok().is(AsmToken::Identifier))
3603 Reg = tryParseRegister();
3604 if (Reg == -1) {
3605 if (!haveEaten)
3606 return MatchOperand_NoMatch;
3607 Error(Parser.getTok().getLoc(), "register expected");
3608 return MatchOperand_ParseFail;
3609 }
3610 SMLoc E = Parser.getTok().getLoc();
3611
3612 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3613 0, S, E));
3614
3615 return MatchOperand_Success;
3616}
3617
Jim Grosbacha77295d2011-09-08 22:07:06 +00003618/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3619/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3620/// when they refer multiple MIOperands inside a single one.
3621bool ARMAsmParser::
3622cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3623 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3624 // Rt, Rt2
3625 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3626 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3627 // Create a writeback register dummy placeholder.
3628 Inst.addOperand(MCOperand::CreateReg(0));
3629 // addr
3630 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3631 // pred
3632 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3633 return true;
3634}
3635
3636/// cvtT2StrdPre - Convert parsed operands to MCInst.
3637/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3638/// when they refer multiple MIOperands inside a single one.
3639bool ARMAsmParser::
3640cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3641 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3642 // Create a writeback register dummy placeholder.
3643 Inst.addOperand(MCOperand::CreateReg(0));
3644 // Rt, Rt2
3645 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3646 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3647 // addr
3648 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3649 // pred
3650 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3651 return true;
3652}
3653
Jim Grosbacheeec0252011-09-08 00:39:19 +00003654/// cvtLdWriteBackRegT2AddrModeImm8 - 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::
3658cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3659 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3660 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3661
3662 // Create a writeback register dummy placeholder.
3663 Inst.addOperand(MCOperand::CreateImm(0));
3664
3665 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3666 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3667 return true;
3668}
3669
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003670/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3671/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3672/// when they refer multiple MIOperands inside a single one.
3673bool ARMAsmParser::
3674cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3675 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3676 // Create a writeback register dummy placeholder.
3677 Inst.addOperand(MCOperand::CreateImm(0));
3678 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3679 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3680 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3681 return true;
3682}
3683
Jim Grosbach1355cf12011-07-26 17:10:22 +00003684/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003685/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3686/// when they refer multiple MIOperands inside a single one.
3687bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003688cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003689 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3690 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3691
3692 // Create a writeback register dummy placeholder.
3693 Inst.addOperand(MCOperand::CreateImm(0));
3694
Jim Grosbach7ce05792011-08-03 23:50:40 +00003695 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003696 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3697 return true;
3698}
3699
Owen Anderson9ab0f252011-08-26 20:43:14 +00003700/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3701/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3702/// when they refer multiple MIOperands inside a single one.
3703bool ARMAsmParser::
3704cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3705 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3706 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3707
3708 // Create a writeback register dummy placeholder.
3709 Inst.addOperand(MCOperand::CreateImm(0));
3710
3711 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3712 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3713 return true;
3714}
3715
3716
Jim Grosbach548340c2011-08-11 19:22:40 +00003717/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3718/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3719/// when they refer multiple MIOperands inside a single one.
3720bool ARMAsmParser::
3721cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3722 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3723 // Create a writeback register dummy placeholder.
3724 Inst.addOperand(MCOperand::CreateImm(0));
3725 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3726 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3727 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3728 return true;
3729}
3730
Jim Grosbach1355cf12011-07-26 17:10:22 +00003731/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003732/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3733/// when they refer multiple MIOperands inside a single one.
3734bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003735cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003736 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3737 // Create a writeback register dummy placeholder.
3738 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003739 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3740 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3741 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003742 return true;
3743}
3744
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003745/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3746/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3747/// when they refer multiple MIOperands inside a single one.
3748bool ARMAsmParser::
3749cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3750 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3751 // Create a writeback register dummy placeholder.
3752 Inst.addOperand(MCOperand::CreateImm(0));
3753 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3754 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3755 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3756 return true;
3757}
3758
Jim Grosbach7ce05792011-08-03 23:50:40 +00003759/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3760/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3761/// when they refer multiple MIOperands inside a single one.
3762bool ARMAsmParser::
3763cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3764 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3765 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003766 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003767 // Create a writeback register dummy placeholder.
3768 Inst.addOperand(MCOperand::CreateImm(0));
3769 // addr
3770 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3771 // offset
3772 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3773 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003774 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3775 return true;
3776}
3777
Jim Grosbach7ce05792011-08-03 23:50:40 +00003778/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003779/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3780/// when they refer multiple MIOperands inside a single one.
3781bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003782cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3783 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3784 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003785 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003786 // Create a writeback register dummy placeholder.
3787 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003788 // addr
3789 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3790 // offset
3791 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3792 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003793 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3794 return true;
3795}
3796
Jim Grosbach7ce05792011-08-03 23:50:40 +00003797/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003798/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3799/// when they refer multiple MIOperands inside a single one.
3800bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003801cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3802 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003803 // Create a writeback register dummy placeholder.
3804 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003805 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003806 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003807 // addr
3808 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3809 // offset
3810 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3811 // pred
3812 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3813 return true;
3814}
3815
3816/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3817/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3818/// when they refer multiple MIOperands inside a single one.
3819bool ARMAsmParser::
3820cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3821 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3822 // Create a writeback register dummy placeholder.
3823 Inst.addOperand(MCOperand::CreateImm(0));
3824 // Rt
3825 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3826 // addr
3827 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3828 // offset
3829 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3830 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003831 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3832 return true;
3833}
3834
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003835/// cvtLdrdPre - Convert parsed operands to MCInst.
3836/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3837/// when they refer multiple MIOperands inside a single one.
3838bool ARMAsmParser::
3839cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3840 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3841 // Rt, Rt2
3842 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3843 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3844 // Create a writeback register dummy placeholder.
3845 Inst.addOperand(MCOperand::CreateImm(0));
3846 // addr
3847 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3848 // pred
3849 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3850 return true;
3851}
3852
Jim Grosbach14605d12011-08-11 20:28:23 +00003853/// cvtStrdPre - Convert parsed operands to MCInst.
3854/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3855/// when they refer multiple MIOperands inside a single one.
3856bool ARMAsmParser::
3857cvtStrdPre(MCInst &Inst, unsigned Opcode,
3858 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3859 // Create a writeback register dummy placeholder.
3860 Inst.addOperand(MCOperand::CreateImm(0));
3861 // Rt, Rt2
3862 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3863 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3864 // addr
3865 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3866 // pred
3867 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3868 return true;
3869}
3870
Jim Grosbach623a4542011-08-10 22:42:16 +00003871/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3872/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3873/// when they refer multiple MIOperands inside a single one.
3874bool ARMAsmParser::
3875cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3876 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3877 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3878 // Create a writeback register dummy placeholder.
3879 Inst.addOperand(MCOperand::CreateImm(0));
3880 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3881 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3882 return true;
3883}
3884
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003885/// cvtThumbMultiple- Convert parsed operands to MCInst.
3886/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3887/// when they refer multiple MIOperands inside a single one.
3888bool ARMAsmParser::
3889cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3890 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3891 // The second source operand must be the same register as the destination
3892 // operand.
3893 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003894 (((ARMOperand*)Operands[3])->getReg() !=
3895 ((ARMOperand*)Operands[5])->getReg()) &&
3896 (((ARMOperand*)Operands[3])->getReg() !=
3897 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003898 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003899 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003900 return false;
3901 }
3902 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3903 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003904 // If we have a three-operand form, make sure to set Rn to be the operand
3905 // that isn't the same as Rd.
3906 unsigned RegOp = 4;
3907 if (Operands.size() == 6 &&
3908 ((ARMOperand*)Operands[4])->getReg() ==
3909 ((ARMOperand*)Operands[3])->getReg())
3910 RegOp = 5;
3911 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3912 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003913 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3914
3915 return true;
3916}
Jim Grosbach623a4542011-08-10 22:42:16 +00003917
Jim Grosbach12431322011-10-24 22:16:58 +00003918bool ARMAsmParser::
3919cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3920 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3921 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003922 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003923 // Create a writeback register dummy placeholder.
3924 Inst.addOperand(MCOperand::CreateImm(0));
3925 // Vn
3926 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3927 // pred
3928 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3929 return true;
3930}
3931
3932bool ARMAsmParser::
3933cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3934 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3935 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003936 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003937 // Create a writeback register dummy placeholder.
3938 Inst.addOperand(MCOperand::CreateImm(0));
3939 // Vn
3940 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3941 // Vm
3942 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3943 // pred
3944 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3945 return true;
3946}
3947
Jim Grosbach4334e032011-10-31 21:50:31 +00003948bool ARMAsmParser::
3949cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3950 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3951 // Create a writeback register dummy placeholder.
3952 Inst.addOperand(MCOperand::CreateImm(0));
3953 // Vn
3954 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3955 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003956 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003957 // pred
3958 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3959 return true;
3960}
3961
3962bool ARMAsmParser::
3963cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3964 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3965 // Create a writeback register dummy placeholder.
3966 Inst.addOperand(MCOperand::CreateImm(0));
3967 // Vn
3968 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3969 // Vm
3970 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3971 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003972 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003973 // pred
3974 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3975 return true;
3976}
3977
Bill Wendlinge7176102010-11-06 22:36:58 +00003978/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003979/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003980bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003981parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003982 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003983 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003984 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003985 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003986 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003987
Sean Callanan18b83232010-01-19 21:44:56 +00003988 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003989 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003990 if (BaseRegNum == -1)
3991 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003992
Daniel Dunbar05710932011-01-18 05:34:17 +00003993 // The next token must either be a comma or a closing bracket.
3994 const AsmToken &Tok = Parser.getTok();
3995 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003996 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003997
Jim Grosbach7ce05792011-08-03 23:50:40 +00003998 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003999 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004000 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004001
Jim Grosbach7ce05792011-08-03 23:50:40 +00004002 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004003 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004004
Jim Grosbachfb12f352011-09-19 18:42:21 +00004005 // If there's a pre-indexing writeback marker, '!', just add it as a token
4006 // operand. It's rather odd, but syntactically valid.
4007 if (Parser.getTok().is(AsmToken::Exclaim)) {
4008 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4009 Parser.Lex(); // Eat the '!'.
4010 }
4011
Jim Grosbach7ce05792011-08-03 23:50:40 +00004012 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004013 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004014
Jim Grosbach7ce05792011-08-03 23:50:40 +00004015 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4016 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004017
Jim Grosbach57dcb852011-10-11 17:29:55 +00004018 // If we have a ':', it's an alignment specifier.
4019 if (Parser.getTok().is(AsmToken::Colon)) {
4020 Parser.Lex(); // Eat the ':'.
4021 E = Parser.getTok().getLoc();
4022
4023 const MCExpr *Expr;
4024 if (getParser().ParseExpression(Expr))
4025 return true;
4026
4027 // The expression has to be a constant. Memory references with relocations
4028 // don't come through here, as they use the <label> forms of the relevant
4029 // instructions.
4030 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4031 if (!CE)
4032 return Error (E, "constant expression expected");
4033
4034 unsigned Align = 0;
4035 switch (CE->getValue()) {
4036 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004037 return Error(E,
4038 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4039 case 16: Align = 2; break;
4040 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004041 case 64: Align = 8; break;
4042 case 128: Align = 16; break;
4043 case 256: Align = 32; break;
4044 }
4045
4046 // Now we should have the closing ']'
4047 E = Parser.getTok().getLoc();
4048 if (Parser.getTok().isNot(AsmToken::RBrac))
4049 return Error(E, "']' expected");
4050 Parser.Lex(); // Eat right bracket token.
4051
4052 // Don't worry about range checking the value here. That's handled by
4053 // the is*() predicates.
4054 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4055 ARM_AM::no_shift, 0, Align,
4056 false, S, E));
4057
4058 // If there's a pre-indexing writeback marker, '!', just add it as a token
4059 // operand.
4060 if (Parser.getTok().is(AsmToken::Exclaim)) {
4061 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4062 Parser.Lex(); // Eat the '!'.
4063 }
4064
4065 return false;
4066 }
4067
4068 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004069 // offset. Be friendly and also accept a plain integer (without a leading
4070 // hash) for gas compatibility.
4071 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004072 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004073 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004074 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004075 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004076 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004077
Owen Anderson0da10cf2011-08-29 19:36:44 +00004078 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004079 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004080 if (getParser().ParseExpression(Offset))
4081 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004082
4083 // The expression has to be a constant. Memory references with relocations
4084 // don't come through here, as they use the <label> forms of the relevant
4085 // instructions.
4086 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4087 if (!CE)
4088 return Error (E, "constant expression expected");
4089
Owen Anderson0da10cf2011-08-29 19:36:44 +00004090 // If the constant was #-0, represent it as INT32_MIN.
4091 int32_t Val = CE->getValue();
4092 if (isNegative && Val == 0)
4093 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4094
Jim Grosbach7ce05792011-08-03 23:50:40 +00004095 // Now we should have the closing ']'
4096 E = Parser.getTok().getLoc();
4097 if (Parser.getTok().isNot(AsmToken::RBrac))
4098 return Error(E, "']' expected");
4099 Parser.Lex(); // Eat right bracket token.
4100
4101 // Don't worry about range checking the value here. That's handled by
4102 // the is*() predicates.
4103 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004104 ARM_AM::no_shift, 0, 0,
4105 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004106
4107 // If there's a pre-indexing writeback marker, '!', just add it as a token
4108 // operand.
4109 if (Parser.getTok().is(AsmToken::Exclaim)) {
4110 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4111 Parser.Lex(); // Eat the '!'.
4112 }
4113
4114 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004115 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004116
4117 // The register offset is optionally preceded by a '+' or '-'
4118 bool isNegative = false;
4119 if (Parser.getTok().is(AsmToken::Minus)) {
4120 isNegative = true;
4121 Parser.Lex(); // Eat the '-'.
4122 } else if (Parser.getTok().is(AsmToken::Plus)) {
4123 // Nothing to do.
4124 Parser.Lex(); // Eat the '+'.
4125 }
4126
4127 E = Parser.getTok().getLoc();
4128 int OffsetRegNum = tryParseRegister();
4129 if (OffsetRegNum == -1)
4130 return Error(E, "register expected");
4131
4132 // If there's a shift operator, handle it.
4133 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004134 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004135 if (Parser.getTok().is(AsmToken::Comma)) {
4136 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004137 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004138 return true;
4139 }
4140
4141 // Now we should have the closing ']'
4142 E = Parser.getTok().getLoc();
4143 if (Parser.getTok().isNot(AsmToken::RBrac))
4144 return Error(E, "']' expected");
4145 Parser.Lex(); // Eat right bracket token.
4146
4147 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004148 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004149 S, E));
4150
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004151 // If there's a pre-indexing writeback marker, '!', just add it as a token
4152 // operand.
4153 if (Parser.getTok().is(AsmToken::Exclaim)) {
4154 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4155 Parser.Lex(); // Eat the '!'.
4156 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004157
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004158 return false;
4159}
4160
Jim Grosbach7ce05792011-08-03 23:50:40 +00004161/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004162/// ( lsl | lsr | asr | ror ) , # shift_amount
4163/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004164/// return true if it parses a shift otherwise it returns false.
4165bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4166 unsigned &Amount) {
4167 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004168 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004169 if (Tok.isNot(AsmToken::Identifier))
4170 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004171 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004172 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4173 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004174 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004175 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004176 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004177 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004178 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004179 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004180 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004181 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004182 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004183 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004184 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004185 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004186
Jim Grosbach7ce05792011-08-03 23:50:40 +00004187 // rrx stands alone.
4188 Amount = 0;
4189 if (St != ARM_AM::rrx) {
4190 Loc = Parser.getTok().getLoc();
4191 // A '#' and a shift amount.
4192 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004193 if (HashTok.isNot(AsmToken::Hash) &&
4194 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004195 return Error(HashTok.getLoc(), "'#' expected");
4196 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004197
Jim Grosbach7ce05792011-08-03 23:50:40 +00004198 const MCExpr *Expr;
4199 if (getParser().ParseExpression(Expr))
4200 return true;
4201 // Range check the immediate.
4202 // lsl, ror: 0 <= imm <= 31
4203 // lsr, asr: 0 <= imm <= 32
4204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4205 if (!CE)
4206 return Error(Loc, "shift amount must be an immediate");
4207 int64_t Imm = CE->getValue();
4208 if (Imm < 0 ||
4209 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4210 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4211 return Error(Loc, "immediate shift value out of range");
4212 Amount = Imm;
4213 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004214
4215 return false;
4216}
4217
Jim Grosbach9d390362011-10-03 23:38:36 +00004218/// parseFPImm - A floating point immediate expression operand.
4219ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4220parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4221 SMLoc S = Parser.getTok().getLoc();
4222
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004223 if (Parser.getTok().isNot(AsmToken::Hash) &&
4224 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004225 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004226
4227 // Disambiguate the VMOV forms that can accept an FP immediate.
4228 // vmov.f32 <sreg>, #imm
4229 // vmov.f64 <dreg>, #imm
4230 // vmov.f32 <dreg>, #imm @ vector f32x2
4231 // vmov.f32 <qreg>, #imm @ vector f32x4
4232 //
4233 // There are also the NEON VMOV instructions which expect an
4234 // integer constant. Make sure we don't try to parse an FPImm
4235 // for these:
4236 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4237 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4238 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4239 TyOp->getToken() != ".f64"))
4240 return MatchOperand_NoMatch;
4241
Jim Grosbach9d390362011-10-03 23:38:36 +00004242 Parser.Lex(); // Eat the '#'.
4243
4244 // Handle negation, as that still comes through as a separate token.
4245 bool isNegative = false;
4246 if (Parser.getTok().is(AsmToken::Minus)) {
4247 isNegative = true;
4248 Parser.Lex();
4249 }
4250 const AsmToken &Tok = Parser.getTok();
4251 if (Tok.is(AsmToken::Real)) {
4252 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4253 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4254 // If we had a '-' in front, toggle the sign bit.
4255 IntVal ^= (uint64_t)isNegative << 63;
4256 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4257 Parser.Lex(); // Eat the token.
4258 if (Val == -1) {
4259 TokError("floating point value out of range");
4260 return MatchOperand_ParseFail;
4261 }
4262 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4263 return MatchOperand_Success;
4264 }
4265 if (Tok.is(AsmToken::Integer)) {
4266 int64_t Val = Tok.getIntVal();
4267 Parser.Lex(); // Eat the token.
4268 if (Val > 255 || Val < 0) {
4269 TokError("encoded floating point value out of range");
4270 return MatchOperand_ParseFail;
4271 }
4272 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4273 return MatchOperand_Success;
4274 }
4275
4276 TokError("invalid floating point immediate");
4277 return MatchOperand_ParseFail;
4278}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004279/// Parse a arm instruction operand. For now this parses the operand regardless
4280/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004281bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004282 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004283 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004284
4285 // Check if the current operand has a custom associated parser, if so, try to
4286 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004287 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4288 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004289 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004290 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4291 // there was a match, but an error occurred, in which case, just return that
4292 // the operand parsing failed.
4293 if (ResTy == MatchOperand_ParseFail)
4294 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004295
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004296 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004297 default:
4298 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004299 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004300 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004301 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004302 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004303 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004304 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004305 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004306 else if (Res == -1) // irrecoverable error
4307 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004308 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004309 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4310 S = Parser.getTok().getLoc();
4311 Parser.Lex();
4312 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4313 return false;
4314 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004315
4316 // Fall though for the Identifier case that is not a register or a
4317 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004318 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004319 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004320 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004321 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004322 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004323 // This was not a register so parse other operands that start with an
4324 // identifier (like labels) as expressions and create them as immediates.
4325 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004326 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004327 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004328 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004329 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004330 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4331 return false;
4332 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004333 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004334 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004335 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004336 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004337 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004338 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004339 // #42 -> immediate.
4340 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004341 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004342 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004343 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004344 const MCExpr *ImmVal;
4345 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004346 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004347 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004348 if (CE) {
4349 int32_t Val = CE->getValue();
4350 if (isNegative && Val == 0)
4351 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004352 }
Sean Callanan76264762010-04-02 22:27:05 +00004353 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004354 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4355 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004356 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004357 case AsmToken::Colon: {
4358 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004359 // FIXME: Check it's an expression prefix,
4360 // e.g. (FOO - :lower16:BAR) isn't legal.
4361 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004362 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004363 return true;
4364
Evan Cheng75972122011-01-13 07:58:56 +00004365 const MCExpr *SubExprVal;
4366 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004367 return true;
4368
Evan Cheng75972122011-01-13 07:58:56 +00004369 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4370 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004371 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004372 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004373 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004374 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004375 }
4376}
4377
Jim Grosbach1355cf12011-07-26 17:10:22 +00004378// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004379// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004380bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004381 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004382
4383 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004384 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004385 Parser.Lex(); // Eat ':'
4386
4387 if (getLexer().isNot(AsmToken::Identifier)) {
4388 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4389 return true;
4390 }
4391
4392 StringRef IDVal = Parser.getTok().getIdentifier();
4393 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004394 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004395 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004396 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004397 } else {
4398 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4399 return true;
4400 }
4401 Parser.Lex();
4402
4403 if (getLexer().isNot(AsmToken::Colon)) {
4404 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4405 return true;
4406 }
4407 Parser.Lex(); // Eat the last ':'
4408 return false;
4409}
4410
Daniel Dunbar352e1482011-01-11 15:59:50 +00004411/// \brief Given a mnemonic, split out possible predication code and carry
4412/// setting letters to form a canonical mnemonic and flags.
4413//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004414// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004415// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004416StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004417 unsigned &PredicationCode,
4418 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004419 unsigned &ProcessorIMod,
4420 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004421 PredicationCode = ARMCC::AL;
4422 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004423 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004424
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004425 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004426 //
4427 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004428 if ((Mnemonic == "movs" && isThumb()) ||
4429 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4430 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4431 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4432 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4433 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4434 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004435 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4436 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004437 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004438
Jim Grosbach3f00e312011-07-11 17:09:57 +00004439 // First, split out any predication code. Ignore mnemonics we know aren't
4440 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004441 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004442 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004443 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004444 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004445 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4446 .Case("eq", ARMCC::EQ)
4447 .Case("ne", ARMCC::NE)
4448 .Case("hs", ARMCC::HS)
4449 .Case("cs", ARMCC::HS)
4450 .Case("lo", ARMCC::LO)
4451 .Case("cc", ARMCC::LO)
4452 .Case("mi", ARMCC::MI)
4453 .Case("pl", ARMCC::PL)
4454 .Case("vs", ARMCC::VS)
4455 .Case("vc", ARMCC::VC)
4456 .Case("hi", ARMCC::HI)
4457 .Case("ls", ARMCC::LS)
4458 .Case("ge", ARMCC::GE)
4459 .Case("lt", ARMCC::LT)
4460 .Case("gt", ARMCC::GT)
4461 .Case("le", ARMCC::LE)
4462 .Case("al", ARMCC::AL)
4463 .Default(~0U);
4464 if (CC != ~0U) {
4465 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4466 PredicationCode = CC;
4467 }
Bill Wendling52925b62010-10-29 23:50:21 +00004468 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004469
Daniel Dunbar352e1482011-01-11 15:59:50 +00004470 // Next, determine if we have a carry setting bit. We explicitly ignore all
4471 // the instructions we know end in 's'.
4472 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004473 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004474 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4475 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4476 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004477 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004478 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004479 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004480 Mnemonic == "fmuls" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004481 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004482 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4483 CarrySetting = true;
4484 }
4485
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004486 // The "cps" instruction can have a interrupt mode operand which is glued into
4487 // the mnemonic. Check if this is the case, split it and parse the imod op
4488 if (Mnemonic.startswith("cps")) {
4489 // Split out any imod code.
4490 unsigned IMod =
4491 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4492 .Case("ie", ARM_PROC::IE)
4493 .Case("id", ARM_PROC::ID)
4494 .Default(~0U);
4495 if (IMod != ~0U) {
4496 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4497 ProcessorIMod = IMod;
4498 }
4499 }
4500
Jim Grosbach89df9962011-08-26 21:43:41 +00004501 // The "it" instruction has the condition mask on the end of the mnemonic.
4502 if (Mnemonic.startswith("it")) {
4503 ITMask = Mnemonic.slice(2, Mnemonic.size());
4504 Mnemonic = Mnemonic.slice(0, 2);
4505 }
4506
Daniel Dunbar352e1482011-01-11 15:59:50 +00004507 return Mnemonic;
4508}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004509
4510/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4511/// inclusion of carry set or predication code operands.
4512//
4513// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004514void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004515getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004516 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004517 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4518 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004519 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004520 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004521 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004522 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004523 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004524 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004525 Mnemonic == "mla" || Mnemonic == "smlal" ||
4526 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004527 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004528 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004529 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004530
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004531 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4532 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4533 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4534 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004535 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4536 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004537 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004538 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4539 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4540 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004541 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4542 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004543 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004544 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004545 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004546 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004547
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004548 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004549 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004550 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004551 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004552 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004553}
4554
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004555bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4556 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004557 // FIXME: This is all horribly hacky. We really need a better way to deal
4558 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004559
4560 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4561 // another does not. Specifically, the MOVW instruction does not. So we
4562 // special case it here and remove the defaulted (non-setting) cc_out
4563 // operand if that's the instruction we're trying to match.
4564 //
4565 // We do this as post-processing of the explicit operands rather than just
4566 // conditionally adding the cc_out in the first place because we need
4567 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004568 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004569 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4570 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4571 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4572 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004573
4574 // Register-register 'add' for thumb does not have a cc_out operand
4575 // when there are only two register operands.
4576 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4577 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4578 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4579 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4580 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004581 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004582 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4583 // have to check the immediate range here since Thumb2 has a variant
4584 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004585 if (((isThumb() && Mnemonic == "add") ||
4586 (isThumbTwo() && Mnemonic == "sub")) &&
4587 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004588 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4589 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4590 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004591 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4592 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4593 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004594 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004595 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4596 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004597 // selecting via the generic "add" mnemonic, so to know that we
4598 // should remove the cc_out operand, we have to explicitly check that
4599 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004600 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4601 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004602 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4603 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4604 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4605 // Nest conditions rather than one big 'if' statement for readability.
4606 //
4607 // If either register is a high reg, it's either one of the SP
4608 // variants (handled above) or a 32-bit encoding, so we just
4609 // check against T3.
4610 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4611 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4612 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4613 return false;
4614 // If both registers are low, we're in an IT block, and the immediate is
4615 // in range, we should use encoding T1 instead, which has a cc_out.
4616 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004617 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004618 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4619 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4620 return false;
4621
4622 // Otherwise, we use encoding T4, which does not have a cc_out
4623 // operand.
4624 return true;
4625 }
4626
Jim Grosbach64944f42011-09-14 21:00:40 +00004627 // The thumb2 multiply instruction doesn't have a CCOut register, so
4628 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4629 // use the 16-bit encoding or not.
4630 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4631 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4632 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4633 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4634 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4635 // If the registers aren't low regs, the destination reg isn't the
4636 // same as one of the source regs, or the cc_out operand is zero
4637 // outside of an IT block, we have to use the 32-bit encoding, so
4638 // remove the cc_out operand.
4639 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4640 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004641 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004642 !inITBlock() ||
4643 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4644 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4645 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4646 static_cast<ARMOperand*>(Operands[4])->getReg())))
4647 return true;
4648
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004649 // Also check the 'mul' syntax variant that doesn't specify an explicit
4650 // destination register.
4651 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4652 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4653 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4654 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4655 // If the registers aren't low regs or the cc_out operand is zero
4656 // outside of an IT block, we have to use the 32-bit encoding, so
4657 // remove the cc_out operand.
4658 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4659 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4660 !inITBlock()))
4661 return true;
4662
Jim Grosbach64944f42011-09-14 21:00:40 +00004663
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004664
Jim Grosbachf69c8042011-08-24 21:42:27 +00004665 // Register-register 'add/sub' for thumb does not have a cc_out operand
4666 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4667 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4668 // right, this will result in better diagnostics (which operand is off)
4669 // anyway.
4670 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4671 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004672 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4673 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4674 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4675 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004676
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004677 return false;
4678}
4679
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004680static bool isDataTypeToken(StringRef Tok) {
4681 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4682 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4683 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4684 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4685 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4686 Tok == ".f" || Tok == ".d";
4687}
4688
4689// FIXME: This bit should probably be handled via an explicit match class
4690// in the .td files that matches the suffix instead of having it be
4691// a literal string token the way it is now.
4692static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4693 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4694}
4695
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004696static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004697/// Parse an arm instruction mnemonic followed by its operands.
4698bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4699 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004700 // Apply mnemonic aliases before doing anything else, as the destination
4701 // mnemnonic may include suffices and we want to handle them normally.
4702 // The generic tblgen'erated code does this later, at the start of
4703 // MatchInstructionImpl(), but that's too late for aliases that include
4704 // any sort of suffix.
4705 unsigned AvailableFeatures = getAvailableFeatures();
4706 applyMnemonicAliases(Name, AvailableFeatures);
4707
Jim Grosbacha39cda72011-12-14 02:16:11 +00004708 // First check for the ARM-specific .req directive.
4709 if (Parser.getTok().is(AsmToken::Identifier) &&
4710 Parser.getTok().getIdentifier() == ".req") {
4711 parseDirectiveReq(Name, NameLoc);
4712 // We always return 'error' for this, as we're done with this
4713 // statement and don't need to match the 'instruction."
4714 return true;
4715 }
4716
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004717 // Create the leading tokens for the mnemonic, split by '.' characters.
4718 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004719 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004720
Daniel Dunbar352e1482011-01-11 15:59:50 +00004721 // Split out the predication code and carry setting flag from the mnemonic.
4722 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004723 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004724 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004725 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004726 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004727 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004728
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004729 // In Thumb1, only the branch (B) instruction can be predicated.
4730 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4731 Parser.EatToEndOfStatement();
4732 return Error(NameLoc, "conditional execution not supported in Thumb1");
4733 }
4734
Jim Grosbachffa32252011-07-19 19:13:28 +00004735 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4736
Jim Grosbach89df9962011-08-26 21:43:41 +00004737 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4738 // is the mask as it will be for the IT encoding if the conditional
4739 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4740 // where the conditional bit0 is zero, the instruction post-processing
4741 // will adjust the mask accordingly.
4742 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004743 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4744 if (ITMask.size() > 3) {
4745 Parser.EatToEndOfStatement();
4746 return Error(Loc, "too many conditions on IT instruction");
4747 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004748 unsigned Mask = 8;
4749 for (unsigned i = ITMask.size(); i != 0; --i) {
4750 char pos = ITMask[i - 1];
4751 if (pos != 't' && pos != 'e') {
4752 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004753 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004754 }
4755 Mask >>= 1;
4756 if (ITMask[i - 1] == 't')
4757 Mask |= 8;
4758 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004759 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004760 }
4761
Jim Grosbachffa32252011-07-19 19:13:28 +00004762 // FIXME: This is all a pretty gross hack. We should automatically handle
4763 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004764
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004765 // Next, add the CCOut and ConditionCode operands, if needed.
4766 //
4767 // For mnemonics which can ever incorporate a carry setting bit or predication
4768 // code, our matching model involves us always generating CCOut and
4769 // ConditionCode operands to match the mnemonic "as written" and then we let
4770 // the matcher deal with finding the right instruction or generating an
4771 // appropriate error.
4772 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004773 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004774
Jim Grosbach33c16a22011-07-14 22:04:21 +00004775 // If we had a carry-set on an instruction that can't do that, issue an
4776 // error.
4777 if (!CanAcceptCarrySet && CarrySetting) {
4778 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004779 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004780 "' can not set flags, but 's' suffix specified");
4781 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004782 // If we had a predication code on an instruction that can't do that, issue an
4783 // error.
4784 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4785 Parser.EatToEndOfStatement();
4786 return Error(NameLoc, "instruction '" + Mnemonic +
4787 "' is not predicable, but condition code specified");
4788 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004789
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004790 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004791 if (CanAcceptCarrySet) {
4792 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004793 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004794 Loc));
4795 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004796
4797 // Add the predication code operand, if necessary.
4798 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004799 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4800 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004801 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004802 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004803 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004804
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004805 // Add the processor imod operand, if necessary.
4806 if (ProcessorIMod) {
4807 Operands.push_back(ARMOperand::CreateImm(
4808 MCConstantExpr::Create(ProcessorIMod, getContext()),
4809 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004810 }
4811
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004812 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004813 while (Next != StringRef::npos) {
4814 Start = Next;
4815 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004816 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004817
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004818 // Some NEON instructions have an optional datatype suffix that is
4819 // completely ignored. Check for that.
4820 if (isDataTypeToken(ExtraToken) &&
4821 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4822 continue;
4823
Jim Grosbach81d2e392011-09-07 16:06:04 +00004824 if (ExtraToken != ".n") {
4825 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4826 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4827 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004828 }
4829
4830 // Read the remaining operands.
4831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004832 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004833 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004834 Parser.EatToEndOfStatement();
4835 return true;
4836 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004837
4838 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004839 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004840
4841 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004842 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004843 Parser.EatToEndOfStatement();
4844 return true;
4845 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004846 }
4847 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004848
Chris Lattnercbf8a982010-09-11 16:18:25 +00004849 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004850 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004851 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004852 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004853 }
Bill Wendling146018f2010-11-06 21:42:12 +00004854
Chris Lattner34e53142010-09-08 05:10:46 +00004855 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004856
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004857 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4858 // do and don't have a cc_out optional-def operand. With some spot-checks
4859 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004860 // parse and adjust accordingly before actually matching. We shouldn't ever
4861 // try to remove a cc_out operand that was explicitly set on the the
4862 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4863 // table driven matcher doesn't fit well with the ARM instruction set.
4864 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004865 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4866 Operands.erase(Operands.begin() + 1);
4867 delete Op;
4868 }
4869
Jim Grosbachcf121c32011-07-28 21:57:55 +00004870 // ARM mode 'blx' need special handling, as the register operand version
4871 // is predicable, but the label operand version is not. So, we can't rely
4872 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004873 // a k_CondCode operand in the list. If we're trying to match the label
4874 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004875 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4876 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4877 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4878 Operands.erase(Operands.begin() + 1);
4879 delete Op;
4880 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004881
4882 // The vector-compare-to-zero instructions have a literal token "#0" at
4883 // the end that comes to here as an immediate operand. Convert it to a
4884 // token to play nicely with the matcher.
4885 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4886 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4887 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4888 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4889 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4890 if (CE && CE->getValue() == 0) {
4891 Operands.erase(Operands.begin() + 5);
4892 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4893 delete Op;
4894 }
4895 }
Jim Grosbach68259142011-10-03 22:30:24 +00004896 // VCMP{E} does the same thing, but with a different operand count.
4897 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4898 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4899 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4900 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4901 if (CE && CE->getValue() == 0) {
4902 Operands.erase(Operands.begin() + 4);
4903 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4904 delete Op;
4905 }
4906 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004907 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004908 // end. Convert it to a token here. Take care not to convert those
4909 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004910 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004911 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4912 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004913 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4914 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4915 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004916 if (CE && CE->getValue() == 0 &&
4917 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004918 // The cc_out operand matches the IT block.
4919 ((inITBlock() != CarrySetting) &&
4920 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004921 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004922 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004923 Operands.erase(Operands.begin() + 5);
4924 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4925 delete Op;
4926 }
4927 }
4928
Chris Lattner98986712010-01-14 22:21:20 +00004929 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004930}
4931
Jim Grosbach189610f2011-07-26 18:25:39 +00004932// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004933
4934// return 'true' if register list contains non-low GPR registers,
4935// 'false' otherwise. If Reg is in the register list or is HiReg, set
4936// 'containsReg' to true.
4937static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4938 unsigned HiReg, bool &containsReg) {
4939 containsReg = false;
4940 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4941 unsigned OpReg = Inst.getOperand(i).getReg();
4942 if (OpReg == Reg)
4943 containsReg = true;
4944 // Anything other than a low register isn't legal here.
4945 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4946 return true;
4947 }
4948 return false;
4949}
4950
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004951// Check if the specified regisgter is in the register list of the inst,
4952// starting at the indicated operand number.
4953static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4954 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4955 unsigned OpReg = Inst.getOperand(i).getReg();
4956 if (OpReg == Reg)
4957 return true;
4958 }
4959 return false;
4960}
4961
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004962// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4963// the ARMInsts array) instead. Getting that here requires awkward
4964// API changes, though. Better way?
4965namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004966extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004967}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004968static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004969 return ARMInsts[Opcode];
4970}
4971
Jim Grosbach189610f2011-07-26 18:25:39 +00004972// FIXME: We would really like to be able to tablegen'erate this.
4973bool ARMAsmParser::
4974validateInstruction(MCInst &Inst,
4975 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004976 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004977 SMLoc Loc = Operands[0]->getStartLoc();
4978 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004979 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4980 // being allowed in IT blocks, but not being predicable. It just always
4981 // executes.
4982 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004983 unsigned bit = 1;
4984 if (ITState.FirstCond)
4985 ITState.FirstCond = false;
4986 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004987 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004988 // The instruction must be predicable.
4989 if (!MCID.isPredicable())
4990 return Error(Loc, "instructions in IT block must be predicable");
4991 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4992 unsigned ITCond = bit ? ITState.Cond :
4993 ARMCC::getOppositeCondition(ITState.Cond);
4994 if (Cond != ITCond) {
4995 // Find the condition code Operand to get its SMLoc information.
4996 SMLoc CondLoc;
4997 for (unsigned i = 1; i < Operands.size(); ++i)
4998 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4999 CondLoc = Operands[i]->getStartLoc();
5000 return Error(CondLoc, "incorrect condition in IT block; got '" +
5001 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5002 "', but expected '" +
5003 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5004 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005005 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005006 } else if (isThumbTwo() && MCID.isPredicable() &&
5007 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005008 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5009 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005010 return Error(Loc, "predicated instructions must be in IT block");
5011
Jim Grosbach189610f2011-07-26 18:25:39 +00005012 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005013 case ARM::LDRD:
5014 case ARM::LDRD_PRE:
5015 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005016 case ARM::LDREXD: {
5017 // Rt2 must be Rt + 1.
5018 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5019 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5020 if (Rt2 != Rt + 1)
5021 return Error(Operands[3]->getStartLoc(),
5022 "destination operands must be sequential");
5023 return false;
5024 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005025 case ARM::STRD: {
5026 // Rt2 must be Rt + 1.
5027 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5028 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5029 if (Rt2 != Rt + 1)
5030 return Error(Operands[3]->getStartLoc(),
5031 "source operands must be sequential");
5032 return false;
5033 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005034 case ARM::STRD_PRE:
5035 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005036 case ARM::STREXD: {
5037 // Rt2 must be Rt + 1.
5038 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5039 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5040 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005041 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005042 "source operands must be sequential");
5043 return false;
5044 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005045 case ARM::SBFX:
5046 case ARM::UBFX: {
5047 // width must be in range [1, 32-lsb]
5048 unsigned lsb = Inst.getOperand(2).getImm();
5049 unsigned widthm1 = Inst.getOperand(3).getImm();
5050 if (widthm1 >= 32 - lsb)
5051 return Error(Operands[5]->getStartLoc(),
5052 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005053 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005054 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005055 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005056 // If we're parsing Thumb2, the .w variant is available and handles
5057 // most cases that are normally illegal for a Thumb1 LDM
5058 // instruction. We'll make the transformation in processInstruction()
5059 // if necessary.
5060 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005061 // Thumb LDM instructions are writeback iff the base register is not
5062 // in the register list.
5063 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005064 bool hasWritebackToken =
5065 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5066 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005067 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005068 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005069 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5070 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005071 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005072 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005073 return Error(Operands[2]->getStartLoc(),
5074 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005075 // If we should not have writeback, there must not be a '!'. This is
5076 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005077 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005078 return Error(Operands[3]->getStartLoc(),
5079 "writeback operator '!' not allowed when base register "
5080 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005081
5082 break;
5083 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005084 case ARM::t2LDMIA_UPD: {
5085 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5086 return Error(Operands[4]->getStartLoc(),
5087 "writeback operator '!' not allowed when base register "
5088 "in register list");
5089 break;
5090 }
Jim Grosbach54026372011-11-10 23:17:11 +00005091 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5092 // so only issue a diagnostic for thumb1. The instructions will be
5093 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005094 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005095 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005096 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5097 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005098 return Error(Operands[2]->getStartLoc(),
5099 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005100 break;
5101 }
5102 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005103 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005104 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5105 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005106 return Error(Operands[2]->getStartLoc(),
5107 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005108 break;
5109 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005110 case ARM::tSTMIA_UPD: {
5111 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005112 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005113 return Error(Operands[4]->getStartLoc(),
5114 "registers must be in range r0-r7");
5115 break;
5116 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005117 }
5118
5119 return false;
5120}
5121
Jim Grosbach5b484312011-12-20 20:46:29 +00005122static unsigned getRealVSTLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005123 switch(Opc) {
5124 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005125 // VST1LN
5126 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5127 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5128 case ARM::VST1LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005129 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005130 return ARM::VST1LNd8_UPD;
5131 case ARM::VST1LNdWB_fixed_Asm_16: case ARM::VST1LNdWB_fixed_Asm_P16:
5132 case ARM::VST1LNdWB_fixed_Asm_I16: case ARM::VST1LNdWB_fixed_Asm_S16:
5133 case ARM::VST1LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005134 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005135 return ARM::VST1LNd16_UPD;
5136 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5137 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5138 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005139 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005140 return ARM::VST1LNd32_UPD;
5141 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5142 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5143 case ARM::VST1LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005144 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005145 return ARM::VST1LNd8_UPD;
5146 case ARM::VST1LNdWB_register_Asm_16: case ARM::VST1LNdWB_register_Asm_P16:
5147 case ARM::VST1LNdWB_register_Asm_I16: case ARM::VST1LNdWB_register_Asm_S16:
5148 case ARM::VST1LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005149 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005150 return ARM::VST1LNd16_UPD;
5151 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5152 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5153 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005154 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005155 return ARM::VST1LNd32_UPD;
5156 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8:
5157 case ARM::VST1LNdAsm_I8: case ARM::VST1LNdAsm_S8:
5158 case ARM::VST1LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005159 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005160 return ARM::VST1LNd8;
5161 case ARM::VST1LNdAsm_16: case ARM::VST1LNdAsm_P16:
5162 case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5163 case ARM::VST1LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005164 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005165 return ARM::VST1LNd16;
5166 case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5167 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32:
5168 case ARM::VST1LNdAsm_S32: case ARM::VST1LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005169 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005170 return ARM::VST1LNd32;
5171
5172 // VST2LN
5173 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5174 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5175 case ARM::VST2LNdWB_fixed_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005176 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005177 return ARM::VST2LNd8_UPD;
5178 case ARM::VST2LNdWB_fixed_Asm_16: case ARM::VST2LNdWB_fixed_Asm_P16:
5179 case ARM::VST2LNdWB_fixed_Asm_I16: case ARM::VST2LNdWB_fixed_Asm_S16:
5180 case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005181 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005182 return ARM::VST2LNd16_UPD;
5183 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
5184 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
5185 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005186 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005187 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005188 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5189 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5190 case ARM::VST2LNqWB_fixed_Asm_U16:
5191 Spacing = 2;
5192 return ARM::VST2LNq16_UPD;
5193 case ARM::VST2LNqWB_fixed_Asm_32: case ARM::VST2LNqWB_fixed_Asm_F:
5194 case ARM::VST2LNqWB_fixed_Asm_F32: case ARM::VST2LNqWB_fixed_Asm_I32:
5195 case ARM::VST2LNqWB_fixed_Asm_S32: case ARM::VST2LNqWB_fixed_Asm_U32:
5196 Spacing = 2;
5197 return ARM::VST2LNq32_UPD;
5198
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005199 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5200 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5201 case ARM::VST2LNdWB_register_Asm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005202 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005203 return ARM::VST2LNd8_UPD;
5204 case ARM::VST2LNdWB_register_Asm_16: case ARM::VST2LNdWB_register_Asm_P16:
5205 case ARM::VST2LNdWB_register_Asm_I16: case ARM::VST2LNdWB_register_Asm_S16:
5206 case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005207 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005208 return ARM::VST2LNd16_UPD;
5209 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
5210 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
5211 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005212 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005213 return ARM::VST2LNd32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005214 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5215 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5216 case ARM::VST2LNqWB_register_Asm_U16:
5217 Spacing = 2;
5218 return ARM::VST2LNq16_UPD;
5219 case ARM::VST2LNqWB_register_Asm_32: case ARM::VST2LNqWB_register_Asm_F:
5220 case ARM::VST2LNqWB_register_Asm_F32: case ARM::VST2LNqWB_register_Asm_I32:
5221 case ARM::VST2LNqWB_register_Asm_S32: case ARM::VST2LNqWB_register_Asm_U32:
5222 Spacing = 2;
5223 return ARM::VST2LNq32_UPD;
5224
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005225 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8:
5226 case ARM::VST2LNdAsm_I8: case ARM::VST2LNdAsm_S8:
5227 case ARM::VST2LNdAsm_U8:
Jim Grosbach5b484312011-12-20 20:46:29 +00005228 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005229 return ARM::VST2LNd8;
5230 case ARM::VST2LNdAsm_16: case ARM::VST2LNdAsm_P16:
5231 case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
5232 case ARM::VST2LNdAsm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005233 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005234 return ARM::VST2LNd16;
5235 case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
5236 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32:
5237 case ARM::VST2LNdAsm_S32: case ARM::VST2LNdAsm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005238 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005239 return ARM::VST2LNd32;
Jim Grosbach5b484312011-12-20 20:46:29 +00005240 case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5241 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16:
5242 case ARM::VST2LNqAsm_U16:
5243 Spacing = 2;
5244 return ARM::VST2LNq16;
5245 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F:
5246 case ARM::VST2LNqAsm_F32: case ARM::VST2LNqAsm_I32:
5247 case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:
5248 Spacing = 2;
5249 return ARM::VST2LNq32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005250 }
5251}
5252
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005253static unsigned getRealVLDLNOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005254 switch(Opc) {
5255 default: assert(0 && "unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005256 // VLD1LN
5257 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5258 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5259 case ARM::VLD1LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005260 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005261 return ARM::VLD1LNd8_UPD;
5262 case ARM::VLD1LNdWB_fixed_Asm_16: case ARM::VLD1LNdWB_fixed_Asm_P16:
5263 case ARM::VLD1LNdWB_fixed_Asm_I16: case ARM::VLD1LNdWB_fixed_Asm_S16:
5264 case ARM::VLD1LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005265 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005266 return ARM::VLD1LNd16_UPD;
5267 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5268 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5269 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005270 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005271 return ARM::VLD1LNd32_UPD;
5272 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5273 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5274 case ARM::VLD1LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005275 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005276 return ARM::VLD1LNd8_UPD;
5277 case ARM::VLD1LNdWB_register_Asm_16: case ARM::VLD1LNdWB_register_Asm_P16:
5278 case ARM::VLD1LNdWB_register_Asm_I16: case ARM::VLD1LNdWB_register_Asm_S16:
5279 case ARM::VLD1LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005280 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005281 return ARM::VLD1LNd16_UPD;
5282 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5283 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5284 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005285 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005286 return ARM::VLD1LNd32_UPD;
5287 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8:
5288 case ARM::VLD1LNdAsm_I8: case ARM::VLD1LNdAsm_S8:
5289 case ARM::VLD1LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005290 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005291 return ARM::VLD1LNd8;
5292 case ARM::VLD1LNdAsm_16: case ARM::VLD1LNdAsm_P16:
5293 case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
5294 case ARM::VLD1LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005295 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005296 return ARM::VLD1LNd16;
5297 case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
5298 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32:
5299 case ARM::VLD1LNdAsm_S32: case ARM::VLD1LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005300 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005301 return ARM::VLD1LNd32;
5302
5303 // VLD2LN
5304 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5305 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5306 case ARM::VLD2LNdWB_fixed_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005307 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005308 return ARM::VLD2LNd8_UPD;
5309 case ARM::VLD2LNdWB_fixed_Asm_16: case ARM::VLD2LNdWB_fixed_Asm_P16:
5310 case ARM::VLD2LNdWB_fixed_Asm_I16: case ARM::VLD2LNdWB_fixed_Asm_S16:
5311 case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005312 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005313 return ARM::VLD2LNd16_UPD;
5314 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
5315 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
5316 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005317 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005318 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005319 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5320 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5321 case ARM::VLD2LNqWB_fixed_Asm_U16:
5322 Spacing = 1;
5323 return ARM::VLD2LNq16_UPD;
5324 case ARM::VLD2LNqWB_fixed_Asm_32: case ARM::VLD2LNqWB_fixed_Asm_F:
5325 case ARM::VLD2LNqWB_fixed_Asm_F32: case ARM::VLD2LNqWB_fixed_Asm_I32:
5326 case ARM::VLD2LNqWB_fixed_Asm_S32: case ARM::VLD2LNqWB_fixed_Asm_U32:
5327 Spacing = 2;
5328 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005329 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5330 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5331 case ARM::VLD2LNdWB_register_Asm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005332 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005333 return ARM::VLD2LNd8_UPD;
5334 case ARM::VLD2LNdWB_register_Asm_16: case ARM::VLD2LNdWB_register_Asm_P16:
5335 case ARM::VLD2LNdWB_register_Asm_I16: case ARM::VLD2LNdWB_register_Asm_S16:
5336 case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005337 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005338 return ARM::VLD2LNd16_UPD;
5339 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
5340 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
5341 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005342 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005343 return ARM::VLD2LNd32_UPD;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005344 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5345 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5346 case ARM::VLD2LNqWB_register_Asm_U16:
5347 Spacing = 2;
5348 return ARM::VLD2LNq16_UPD;
5349 case ARM::VLD2LNqWB_register_Asm_32: case ARM::VLD2LNqWB_register_Asm_F:
5350 case ARM::VLD2LNqWB_register_Asm_F32: case ARM::VLD2LNqWB_register_Asm_I32:
5351 case ARM::VLD2LNqWB_register_Asm_S32: case ARM::VLD2LNqWB_register_Asm_U32:
5352 Spacing = 2;
5353 return ARM::VLD2LNq32_UPD;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005354 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8:
5355 case ARM::VLD2LNdAsm_I8: case ARM::VLD2LNdAsm_S8:
5356 case ARM::VLD2LNdAsm_U8:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005357 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005358 return ARM::VLD2LNd8;
5359 case ARM::VLD2LNdAsm_16: case ARM::VLD2LNdAsm_P16:
5360 case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
5361 case ARM::VLD2LNdAsm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005362 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005363 return ARM::VLD2LNd16;
5364 case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
5365 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32:
5366 case ARM::VLD2LNdAsm_S32: case ARM::VLD2LNdAsm_U32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005367 Spacing = 1;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005368 return ARM::VLD2LNd32;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005369 case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5370 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16:
5371 case ARM::VLD2LNqAsm_U16:
5372 Spacing = 2;
5373 return ARM::VLD2LNq16;
5374 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F:
5375 case ARM::VLD2LNqAsm_F32: case ARM::VLD2LNqAsm_I32:
5376 case ARM::VLD2LNqAsm_S32: case ARM::VLD2LNqAsm_U32:
5377 Spacing = 2;
5378 return ARM::VLD2LNq32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005379 }
5380}
5381
Jim Grosbach83ec8772011-11-10 23:42:14 +00005382bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005383processInstruction(MCInst &Inst,
5384 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5385 switch (Inst.getOpcode()) {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005386 // Handle NEON VST complex aliases.
5387 case ARM::VST1LNdWB_register_Asm_8: case ARM::VST1LNdWB_register_Asm_P8:
5388 case ARM::VST1LNdWB_register_Asm_I8: case ARM::VST1LNdWB_register_Asm_S8:
5389 case ARM::VST1LNdWB_register_Asm_U8: case ARM::VST1LNdWB_register_Asm_16:
5390 case ARM::VST1LNdWB_register_Asm_P16: case ARM::VST1LNdWB_register_Asm_I16:
5391 case ARM::VST1LNdWB_register_Asm_S16: case ARM::VST1LNdWB_register_Asm_U16:
5392 case ARM::VST1LNdWB_register_Asm_32: case ARM::VST1LNdWB_register_Asm_F:
5393 case ARM::VST1LNdWB_register_Asm_F32: case ARM::VST1LNdWB_register_Asm_I32:
5394 case ARM::VST1LNdWB_register_Asm_S32: case ARM::VST1LNdWB_register_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005395 MCInst TmpInst;
5396 // Shuffle the operands around so the lane index operand is in the
5397 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005398 unsigned Spacing;
5399 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005400 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5401 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5402 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5403 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5404 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5405 TmpInst.addOperand(Inst.getOperand(1)); // lane
5406 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5407 TmpInst.addOperand(Inst.getOperand(6));
5408 Inst = TmpInst;
5409 return true;
5410 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005411
Jim Grosbach5b484312011-12-20 20:46:29 +00005412 case ARM::VST2LNdWB_register_Asm_8: case ARM::VST2LNdWB_register_Asm_P8:
5413 case ARM::VST2LNdWB_register_Asm_I8: case ARM::VST2LNdWB_register_Asm_S8:
5414 case ARM::VST2LNdWB_register_Asm_U8: case ARM::VST2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005415 case ARM::VST2LNdWB_register_Asm_P16: case ARM::VST2LNdWB_register_Asm_I16:
5416 case ARM::VST2LNdWB_register_Asm_S16: case ARM::VST2LNdWB_register_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005417 case ARM::VST2LNdWB_register_Asm_32: case ARM::VST2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005418 case ARM::VST2LNdWB_register_Asm_F32: case ARM::VST2LNdWB_register_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005419 case ARM::VST2LNdWB_register_Asm_S32: case ARM::VST2LNdWB_register_Asm_U32:
5420 case ARM::VST2LNqWB_register_Asm_16: case ARM::VST2LNqWB_register_Asm_P16:
5421 case ARM::VST2LNqWB_register_Asm_I16: case ARM::VST2LNqWB_register_Asm_S16:
5422 case ARM::VST2LNqWB_register_Asm_U16: case ARM::VST2LNqWB_register_Asm_32:
5423 case ARM::VST2LNqWB_register_Asm_F: case ARM::VST2LNqWB_register_Asm_F32:
5424 case ARM::VST2LNqWB_register_Asm_I32: case ARM::VST2LNqWB_register_Asm_S32:
5425 case ARM::VST2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005426 MCInst TmpInst;
5427 // Shuffle the operands around so the lane index operand is in the
5428 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005429 unsigned Spacing;
5430 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005431 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5432 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5433 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5434 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5435 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005436 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5437 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005438 TmpInst.addOperand(Inst.getOperand(1)); // lane
5439 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5440 TmpInst.addOperand(Inst.getOperand(6));
5441 Inst = TmpInst;
5442 return true;
5443 }
5444 case ARM::VST1LNdWB_fixed_Asm_8: case ARM::VST1LNdWB_fixed_Asm_P8:
5445 case ARM::VST1LNdWB_fixed_Asm_I8: case ARM::VST1LNdWB_fixed_Asm_S8:
5446 case ARM::VST1LNdWB_fixed_Asm_U8: case ARM::VST1LNdWB_fixed_Asm_16:
5447 case ARM::VST1LNdWB_fixed_Asm_P16: case ARM::VST1LNdWB_fixed_Asm_I16:
5448 case ARM::VST1LNdWB_fixed_Asm_S16: case ARM::VST1LNdWB_fixed_Asm_U16:
5449 case ARM::VST1LNdWB_fixed_Asm_32: case ARM::VST1LNdWB_fixed_Asm_F:
5450 case ARM::VST1LNdWB_fixed_Asm_F32: case ARM::VST1LNdWB_fixed_Asm_I32:
5451 case ARM::VST1LNdWB_fixed_Asm_S32: case ARM::VST1LNdWB_fixed_Asm_U32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005452 MCInst TmpInst;
5453 // Shuffle the operands around so the lane index operand is in the
5454 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005455 unsigned Spacing;
5456 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005457 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5458 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5459 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5460 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5461 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5462 TmpInst.addOperand(Inst.getOperand(1)); // lane
5463 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5464 TmpInst.addOperand(Inst.getOperand(5));
5465 Inst = TmpInst;
5466 return true;
5467 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005468
Jim Grosbach5b484312011-12-20 20:46:29 +00005469 case ARM::VST2LNdWB_fixed_Asm_8: case ARM::VST2LNdWB_fixed_Asm_P8:
5470 case ARM::VST2LNdWB_fixed_Asm_I8: case ARM::VST2LNdWB_fixed_Asm_S8:
5471 case ARM::VST2LNdWB_fixed_Asm_U8: case ARM::VST2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005472 case ARM::VST2LNdWB_fixed_Asm_P16: case ARM::VST2LNdWB_fixed_Asm_I16:
5473 case ARM::VST2LNdWB_fixed_Asm_S16: case ARM::VST2LNdWB_fixed_Asm_U16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005474 case ARM::VST2LNdWB_fixed_Asm_32: case ARM::VST2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005475 case ARM::VST2LNdWB_fixed_Asm_F32: case ARM::VST2LNdWB_fixed_Asm_I32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005476 case ARM::VST2LNdWB_fixed_Asm_S32: case ARM::VST2LNdWB_fixed_Asm_U32:
5477 case ARM::VST2LNqWB_fixed_Asm_16: case ARM::VST2LNqWB_fixed_Asm_P16:
5478 case ARM::VST2LNqWB_fixed_Asm_I16: case ARM::VST2LNqWB_fixed_Asm_S16:
5479 case ARM::VST2LNqWB_fixed_Asm_U16: case ARM::VST2LNqWB_fixed_Asm_32:
5480 case ARM::VST2LNqWB_fixed_Asm_F: case ARM::VST2LNqWB_fixed_Asm_F32:
5481 case ARM::VST2LNqWB_fixed_Asm_I32: case ARM::VST2LNqWB_fixed_Asm_S32:
5482 case ARM::VST2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005483 MCInst TmpInst;
5484 // Shuffle the operands around so the lane index operand is in the
5485 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005486 unsigned Spacing;
5487 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005488 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5489 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5490 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5491 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5492 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005493 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5494 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005495 TmpInst.addOperand(Inst.getOperand(1)); // lane
5496 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5497 TmpInst.addOperand(Inst.getOperand(5));
5498 Inst = TmpInst;
5499 return true;
5500 }
5501 case ARM::VST1LNdAsm_8: case ARM::VST1LNdAsm_P8: case ARM::VST1LNdAsm_I8:
5502 case ARM::VST1LNdAsm_S8: case ARM::VST1LNdAsm_U8: case ARM::VST1LNdAsm_16:
5503 case ARM::VST1LNdAsm_P16: case ARM::VST1LNdAsm_I16: case ARM::VST1LNdAsm_S16:
5504 case ARM::VST1LNdAsm_U16: case ARM::VST1LNdAsm_32: case ARM::VST1LNdAsm_F:
5505 case ARM::VST1LNdAsm_F32: case ARM::VST1LNdAsm_I32: case ARM::VST1LNdAsm_S32:
Jim Grosbach84defb52011-12-02 22:34:51 +00005506 case ARM::VST1LNdAsm_U32: {
5507 MCInst TmpInst;
5508 // Shuffle the operands around so the lane index operand is in the
5509 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005510 unsigned Spacing;
5511 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005512 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5513 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5514 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5515 TmpInst.addOperand(Inst.getOperand(1)); // lane
5516 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5517 TmpInst.addOperand(Inst.getOperand(5));
5518 Inst = TmpInst;
5519 return true;
5520 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005521
Jim Grosbach5b484312011-12-20 20:46:29 +00005522 case ARM::VST2LNdAsm_8: case ARM::VST2LNdAsm_P8: case ARM::VST2LNdAsm_I8:
5523 case ARM::VST2LNdAsm_S8: case ARM::VST2LNdAsm_U8: case ARM::VST2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005524 case ARM::VST2LNdAsm_P16: case ARM::VST2LNdAsm_I16: case ARM::VST2LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005525 case ARM::VST2LNdAsm_U16: case ARM::VST2LNdAsm_32: case ARM::VST2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005526 case ARM::VST2LNdAsm_F32: case ARM::VST2LNdAsm_I32: case ARM::VST2LNdAsm_S32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005527 case ARM::VST2LNdAsm_U32: case ARM::VST2LNqAsm_16: case ARM::VST2LNqAsm_P16:
5528 case ARM::VST2LNqAsm_I16: case ARM::VST2LNqAsm_S16: case ARM::VST2LNqAsm_U16:
5529 case ARM::VST2LNqAsm_32: case ARM::VST2LNqAsm_F: case ARM::VST2LNqAsm_F32:
5530 case ARM::VST2LNqAsm_I32: case ARM::VST2LNqAsm_S32: case ARM::VST2LNqAsm_U32:{
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005531 MCInst TmpInst;
5532 // Shuffle the operands around so the lane index operand is in the
5533 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005534 unsigned Spacing;
5535 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005536 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5537 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5538 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005539 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5540 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005541 TmpInst.addOperand(Inst.getOperand(1)); // lane
5542 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5543 TmpInst.addOperand(Inst.getOperand(5));
5544 Inst = TmpInst;
5545 return true;
5546 }
5547 // Handle NEON VLD complex aliases.
5548 case ARM::VLD1LNdWB_register_Asm_8: case ARM::VLD1LNdWB_register_Asm_P8:
5549 case ARM::VLD1LNdWB_register_Asm_I8: case ARM::VLD1LNdWB_register_Asm_S8:
5550 case ARM::VLD1LNdWB_register_Asm_U8: case ARM::VLD1LNdWB_register_Asm_16:
5551 case ARM::VLD1LNdWB_register_Asm_P16: case ARM::VLD1LNdWB_register_Asm_I16:
5552 case ARM::VLD1LNdWB_register_Asm_S16: case ARM::VLD1LNdWB_register_Asm_U16:
5553 case ARM::VLD1LNdWB_register_Asm_32: case ARM::VLD1LNdWB_register_Asm_F:
5554 case ARM::VLD1LNdWB_register_Asm_F32: case ARM::VLD1LNdWB_register_Asm_I32:
5555 case ARM::VLD1LNdWB_register_Asm_S32: case ARM::VLD1LNdWB_register_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005556 MCInst TmpInst;
5557 // Shuffle the operands around so the lane index operand is in the
5558 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005559 unsigned Spacing;
5560 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005561 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5562 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5563 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5564 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5565 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5566 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5567 TmpInst.addOperand(Inst.getOperand(1)); // lane
5568 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5569 TmpInst.addOperand(Inst.getOperand(6));
5570 Inst = TmpInst;
5571 return true;
5572 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005573
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005574 case ARM::VLD2LNdWB_register_Asm_8: case ARM::VLD2LNdWB_register_Asm_P8:
5575 case ARM::VLD2LNdWB_register_Asm_I8: case ARM::VLD2LNdWB_register_Asm_S8:
5576 case ARM::VLD2LNdWB_register_Asm_U8: case ARM::VLD2LNdWB_register_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005577 case ARM::VLD2LNdWB_register_Asm_P16: case ARM::VLD2LNdWB_register_Asm_I16:
5578 case ARM::VLD2LNdWB_register_Asm_S16: case ARM::VLD2LNdWB_register_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005579 case ARM::VLD2LNdWB_register_Asm_32: case ARM::VLD2LNdWB_register_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005580 case ARM::VLD2LNdWB_register_Asm_F32: case ARM::VLD2LNdWB_register_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005581 case ARM::VLD2LNdWB_register_Asm_S32: case ARM::VLD2LNdWB_register_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005582 case ARM::VLD2LNqWB_register_Asm_16: case ARM::VLD2LNqWB_register_Asm_P16:
5583 case ARM::VLD2LNqWB_register_Asm_I16: case ARM::VLD2LNqWB_register_Asm_S16:
5584 case ARM::VLD2LNqWB_register_Asm_U16: case ARM::VLD2LNqWB_register_Asm_32:
5585 case ARM::VLD2LNqWB_register_Asm_F: case ARM::VLD2LNqWB_register_Asm_F32:
5586 case ARM::VLD2LNqWB_register_Asm_I32: case ARM::VLD2LNqWB_register_Asm_S32:
5587 case ARM::VLD2LNqWB_register_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005588 MCInst TmpInst;
5589 // Shuffle the operands around so the lane index operand is in the
5590 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005591 unsigned Spacing;
5592 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005593 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005594 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5595 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005596 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5597 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5598 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5599 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5600 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005601 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5602 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005603 TmpInst.addOperand(Inst.getOperand(1)); // lane
5604 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5605 TmpInst.addOperand(Inst.getOperand(6));
5606 Inst = TmpInst;
5607 return true;
5608 }
5609
5610 case ARM::VLD1LNdWB_fixed_Asm_8: case ARM::VLD1LNdWB_fixed_Asm_P8:
5611 case ARM::VLD1LNdWB_fixed_Asm_I8: case ARM::VLD1LNdWB_fixed_Asm_S8:
5612 case ARM::VLD1LNdWB_fixed_Asm_U8: case ARM::VLD1LNdWB_fixed_Asm_16:
5613 case ARM::VLD1LNdWB_fixed_Asm_P16: case ARM::VLD1LNdWB_fixed_Asm_I16:
5614 case ARM::VLD1LNdWB_fixed_Asm_S16: case ARM::VLD1LNdWB_fixed_Asm_U16:
5615 case ARM::VLD1LNdWB_fixed_Asm_32: case ARM::VLD1LNdWB_fixed_Asm_F:
5616 case ARM::VLD1LNdWB_fixed_Asm_F32: case ARM::VLD1LNdWB_fixed_Asm_I32:
5617 case ARM::VLD1LNdWB_fixed_Asm_S32: case ARM::VLD1LNdWB_fixed_Asm_U32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005618 MCInst TmpInst;
5619 // Shuffle the operands around so the lane index operand is in the
5620 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005621 unsigned Spacing;
5622 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005623 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5624 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5625 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5626 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5627 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5628 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5629 TmpInst.addOperand(Inst.getOperand(1)); // lane
5630 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5631 TmpInst.addOperand(Inst.getOperand(5));
5632 Inst = TmpInst;
5633 return true;
5634 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005635
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005636 case ARM::VLD2LNdWB_fixed_Asm_8: case ARM::VLD2LNdWB_fixed_Asm_P8:
5637 case ARM::VLD2LNdWB_fixed_Asm_I8: case ARM::VLD2LNdWB_fixed_Asm_S8:
5638 case ARM::VLD2LNdWB_fixed_Asm_U8: case ARM::VLD2LNdWB_fixed_Asm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005639 case ARM::VLD2LNdWB_fixed_Asm_P16: case ARM::VLD2LNdWB_fixed_Asm_I16:
5640 case ARM::VLD2LNdWB_fixed_Asm_S16: case ARM::VLD2LNdWB_fixed_Asm_U16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005641 case ARM::VLD2LNdWB_fixed_Asm_32: case ARM::VLD2LNdWB_fixed_Asm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005642 case ARM::VLD2LNdWB_fixed_Asm_F32: case ARM::VLD2LNdWB_fixed_Asm_I32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005643 case ARM::VLD2LNdWB_fixed_Asm_S32: case ARM::VLD2LNdWB_fixed_Asm_U32:
Jim Grosbach5b484312011-12-20 20:46:29 +00005644 case ARM::VLD2LNqWB_fixed_Asm_16: case ARM::VLD2LNqWB_fixed_Asm_P16:
5645 case ARM::VLD2LNqWB_fixed_Asm_I16: case ARM::VLD2LNqWB_fixed_Asm_S16:
5646 case ARM::VLD2LNqWB_fixed_Asm_U16: case ARM::VLD2LNqWB_fixed_Asm_32:
5647 case ARM::VLD2LNqWB_fixed_Asm_F: case ARM::VLD2LNqWB_fixed_Asm_F32:
5648 case ARM::VLD2LNqWB_fixed_Asm_I32: case ARM::VLD2LNqWB_fixed_Asm_S32:
5649 case ARM::VLD2LNqWB_fixed_Asm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005650 MCInst TmpInst;
5651 // Shuffle the operands around so the lane index operand is in the
5652 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005653 unsigned Spacing;
5654 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005655 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005656 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5657 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005658 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5659 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5660 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5661 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5662 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005663 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5664 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005665 TmpInst.addOperand(Inst.getOperand(1)); // lane
5666 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5667 TmpInst.addOperand(Inst.getOperand(5));
5668 Inst = TmpInst;
5669 return true;
5670 }
5671
Jim Grosbach5b484312011-12-20 20:46:29 +00005672 case ARM::VLD1LNdAsm_8: case ARM::VLD1LNdAsm_P8: case ARM::VLD1LNdAsm_I8:
5673 case ARM::VLD1LNdAsm_S8: case ARM::VLD1LNdAsm_U8: case ARM::VLD1LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005674 case ARM::VLD1LNdAsm_P16: case ARM::VLD1LNdAsm_I16: case ARM::VLD1LNdAsm_S16:
Jim Grosbach5b484312011-12-20 20:46:29 +00005675 case ARM::VLD1LNdAsm_U16: case ARM::VLD1LNdAsm_32: case ARM::VLD1LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005676 case ARM::VLD1LNdAsm_F32: case ARM::VLD1LNdAsm_I32: case ARM::VLD1LNdAsm_S32:
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005677 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005678 MCInst TmpInst;
5679 // Shuffle the operands around so the lane index operand is in the
5680 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005681 unsigned Spacing;
5682 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005683 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5684 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5685 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5686 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5687 TmpInst.addOperand(Inst.getOperand(1)); // lane
5688 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5689 TmpInst.addOperand(Inst.getOperand(5));
5690 Inst = TmpInst;
5691 return true;
5692 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005693
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005694 case ARM::VLD2LNdAsm_8: case ARM::VLD2LNdAsm_P8: case ARM::VLD2LNdAsm_I8:
5695 case ARM::VLD2LNdAsm_S8: case ARM::VLD2LNdAsm_U8: case ARM::VLD2LNdAsm_16:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005696 case ARM::VLD2LNdAsm_P16: case ARM::VLD2LNdAsm_I16: case ARM::VLD2LNdAsm_S16:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005697 case ARM::VLD2LNdAsm_U16: case ARM::VLD2LNdAsm_32: case ARM::VLD2LNdAsm_F:
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005698 case ARM::VLD2LNdAsm_F32: case ARM::VLD2LNdAsm_I32: case ARM::VLD2LNdAsm_S32:
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005699 case ARM::VLD2LNdAsm_U32: case ARM::VLD2LNqAsm_16: case ARM::VLD2LNqAsm_P16:
5700 case ARM::VLD2LNqAsm_I16: case ARM::VLD2LNqAsm_S16: case ARM::VLD2LNqAsm_U16:
5701 case ARM::VLD2LNqAsm_32: case ARM::VLD2LNqAsm_F: case ARM::VLD2LNqAsm_F32:
5702 case ARM::VLD2LNqAsm_I32: case ARM::VLD2LNqAsm_S32:
5703 case ARM::VLD2LNqAsm_U32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005704 MCInst TmpInst;
5705 // Shuffle the operands around so the lane index operand is in the
5706 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005707 unsigned Spacing;
5708 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005709 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005710 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5711 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005712 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5713 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5714 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005715 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5716 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005717 TmpInst.addOperand(Inst.getOperand(1)); // lane
5718 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5719 TmpInst.addOperand(Inst.getOperand(5));
5720 Inst = TmpInst;
5721 return true;
5722 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005723 // Handle the Thumb2 mode MOV complex aliases.
5724 case ARM::t2MOVsi:
5725 case ARM::t2MOVSsi: {
5726 // Which instruction to expand to depends on the CCOut operand and
5727 // whether we're in an IT block if the register operands are low
5728 // registers.
5729 bool isNarrow = false;
5730 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5731 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5732 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5733 isNarrow = true;
5734 MCInst TmpInst;
5735 unsigned newOpc;
5736 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5737 default: llvm_unreachable("unexpected opcode!");
5738 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5739 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5740 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5741 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5742 }
5743 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5744 if (Ammount == 32) Ammount = 0;
5745 TmpInst.setOpcode(newOpc);
5746 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5747 if (isNarrow)
5748 TmpInst.addOperand(MCOperand::CreateReg(
5749 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5750 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5751 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5752 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5753 TmpInst.addOperand(Inst.getOperand(4));
5754 if (!isNarrow)
5755 TmpInst.addOperand(MCOperand::CreateReg(
5756 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5757 Inst = TmpInst;
5758 return true;
5759 }
5760 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005761 case ARM::ASRr:
5762 case ARM::LSRr:
5763 case ARM::LSLr:
5764 case ARM::RORr: {
5765 ARM_AM::ShiftOpc ShiftTy;
5766 switch(Inst.getOpcode()) {
5767 default: llvm_unreachable("unexpected opcode!");
5768 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5769 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5770 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5771 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5772 }
5773 // A shift by zero is a plain MOVr, not a MOVsi.
5774 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5775 MCInst TmpInst;
5776 TmpInst.setOpcode(ARM::MOVsr);
5777 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5778 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5779 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5780 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5781 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5782 TmpInst.addOperand(Inst.getOperand(4));
5783 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5784 Inst = TmpInst;
5785 return true;
5786 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005787 case ARM::ASRi:
5788 case ARM::LSRi:
5789 case ARM::LSLi:
5790 case ARM::RORi: {
5791 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005792 switch(Inst.getOpcode()) {
5793 default: llvm_unreachable("unexpected opcode!");
5794 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5795 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5796 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5797 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5798 }
5799 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005800 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005801 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5802 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005803 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005804 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005805 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5806 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005807 if (Opc == ARM::MOVsi)
5808 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005809 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5810 TmpInst.addOperand(Inst.getOperand(4));
5811 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5812 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005813 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005814 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005815 case ARM::RRXi: {
5816 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5817 MCInst TmpInst;
5818 TmpInst.setOpcode(ARM::MOVsi);
5819 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5820 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5821 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5822 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5823 TmpInst.addOperand(Inst.getOperand(3));
5824 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5825 Inst = TmpInst;
5826 return true;
5827 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005828 case ARM::t2LDMIA_UPD: {
5829 // If this is a load of a single register, then we should use
5830 // a post-indexed LDR instruction instead, per the ARM ARM.
5831 if (Inst.getNumOperands() != 5)
5832 return false;
5833 MCInst TmpInst;
5834 TmpInst.setOpcode(ARM::t2LDR_POST);
5835 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5836 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5837 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5838 TmpInst.addOperand(MCOperand::CreateImm(4));
5839 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5840 TmpInst.addOperand(Inst.getOperand(3));
5841 Inst = TmpInst;
5842 return true;
5843 }
5844 case ARM::t2STMDB_UPD: {
5845 // If this is a store of a single register, then we should use
5846 // a pre-indexed STR instruction instead, per the ARM ARM.
5847 if (Inst.getNumOperands() != 5)
5848 return false;
5849 MCInst TmpInst;
5850 TmpInst.setOpcode(ARM::t2STR_PRE);
5851 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5852 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5853 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5854 TmpInst.addOperand(MCOperand::CreateImm(-4));
5855 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5856 TmpInst.addOperand(Inst.getOperand(3));
5857 Inst = TmpInst;
5858 return true;
5859 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005860 case ARM::LDMIA_UPD:
5861 // If this is a load of a single register via a 'pop', then we should use
5862 // a post-indexed LDR instruction instead, per the ARM ARM.
5863 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5864 Inst.getNumOperands() == 5) {
5865 MCInst TmpInst;
5866 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5867 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5868 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5869 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5870 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5871 TmpInst.addOperand(MCOperand::CreateImm(4));
5872 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5873 TmpInst.addOperand(Inst.getOperand(3));
5874 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005875 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005876 }
5877 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005878 case ARM::STMDB_UPD:
5879 // If this is a store of a single register via a 'push', then we should use
5880 // a pre-indexed STR instruction instead, per the ARM ARM.
5881 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5882 Inst.getNumOperands() == 5) {
5883 MCInst TmpInst;
5884 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5885 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5886 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5887 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5888 TmpInst.addOperand(MCOperand::CreateImm(-4));
5889 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5890 TmpInst.addOperand(Inst.getOperand(3));
5891 Inst = TmpInst;
5892 }
5893 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005894 case ARM::t2ADDri12:
5895 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5896 // mnemonic was used (not "addw"), encoding T3 is preferred.
5897 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5898 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5899 break;
5900 Inst.setOpcode(ARM::t2ADDri);
5901 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5902 break;
5903 case ARM::t2SUBri12:
5904 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5905 // mnemonic was used (not "subw"), encoding T3 is preferred.
5906 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5907 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5908 break;
5909 Inst.setOpcode(ARM::t2SUBri);
5910 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5911 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005912 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005913 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5914 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5915 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5916 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005917 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005918 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005919 return true;
5920 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005921 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005922 case ARM::tSUBi8:
5923 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5924 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5925 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5926 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005927 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005928 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005929 return true;
5930 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005931 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005932 case ARM::t2ADDrr: {
5933 // If the destination and first source operand are the same, and
5934 // there's no setting of the flags, use encoding T2 instead of T3.
5935 // Note that this is only for ADD, not SUB. This mirrors the system
5936 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5937 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5938 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005939 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5940 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005941 break;
5942 MCInst TmpInst;
5943 TmpInst.setOpcode(ARM::tADDhirr);
5944 TmpInst.addOperand(Inst.getOperand(0));
5945 TmpInst.addOperand(Inst.getOperand(0));
5946 TmpInst.addOperand(Inst.getOperand(2));
5947 TmpInst.addOperand(Inst.getOperand(3));
5948 TmpInst.addOperand(Inst.getOperand(4));
5949 Inst = TmpInst;
5950 return true;
5951 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005952 case ARM::tB:
5953 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005954 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005955 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005956 return true;
5957 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005958 break;
5959 case ARM::t2B:
5960 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005961 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005962 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005963 return true;
5964 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005965 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005966 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005967 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005968 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005969 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005970 return true;
5971 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005972 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005973 case ARM::tBcc:
5974 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005975 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005976 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005977 return true;
5978 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005979 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005980 case ARM::tLDMIA: {
5981 // If the register list contains any high registers, or if the writeback
5982 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5983 // instead if we're in Thumb2. Otherwise, this should have generated
5984 // an error in validateInstruction().
5985 unsigned Rn = Inst.getOperand(0).getReg();
5986 bool hasWritebackToken =
5987 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5988 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5989 bool listContainsBase;
5990 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5991 (!listContainsBase && !hasWritebackToken) ||
5992 (listContainsBase && hasWritebackToken)) {
5993 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5994 assert (isThumbTwo());
5995 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5996 // If we're switching to the updating version, we need to insert
5997 // the writeback tied operand.
5998 if (hasWritebackToken)
5999 Inst.insert(Inst.begin(),
6000 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006001 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00006002 }
6003 break;
6004 }
Jim Grosbach8213c962011-09-16 20:50:13 +00006005 case ARM::tSTMIA_UPD: {
6006 // If the register list contains any high registers, we need to use
6007 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6008 // should have generated an error in validateInstruction().
6009 unsigned Rn = Inst.getOperand(0).getReg();
6010 bool listContainsBase;
6011 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
6012 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
6013 assert (isThumbTwo());
6014 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006015 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00006016 }
6017 break;
6018 }
Jim Grosbach54026372011-11-10 23:17:11 +00006019 case ARM::tPOP: {
6020 bool listContainsBase;
6021 // If the register list contains any high registers, we need to use
6022 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
6023 // should have generated an error in validateInstruction().
6024 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006025 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006026 assert (isThumbTwo());
6027 Inst.setOpcode(ARM::t2LDMIA_UPD);
6028 // Add the base register and writeback operands.
6029 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6030 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006031 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006032 }
6033 case ARM::tPUSH: {
6034 bool listContainsBase;
6035 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00006036 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00006037 assert (isThumbTwo());
6038 Inst.setOpcode(ARM::t2STMDB_UPD);
6039 // Add the base register and writeback operands.
6040 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
6041 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00006042 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00006043 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006044 case ARM::t2MOVi: {
6045 // If we can use the 16-bit encoding and the user didn't explicitly
6046 // request the 32-bit variant, transform it here.
6047 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6048 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00006049 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
6050 Inst.getOperand(4).getReg() == ARM::CPSR) ||
6051 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006052 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6053 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6054 // The operands aren't in the same order for tMOVi8...
6055 MCInst TmpInst;
6056 TmpInst.setOpcode(ARM::tMOVi8);
6057 TmpInst.addOperand(Inst.getOperand(0));
6058 TmpInst.addOperand(Inst.getOperand(4));
6059 TmpInst.addOperand(Inst.getOperand(1));
6060 TmpInst.addOperand(Inst.getOperand(2));
6061 TmpInst.addOperand(Inst.getOperand(3));
6062 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006063 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006064 }
6065 break;
6066 }
6067 case ARM::t2MOVr: {
6068 // If we can use the 16-bit encoding and the user didn't explicitly
6069 // request the 32-bit variant, transform it here.
6070 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6071 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6072 Inst.getOperand(2).getImm() == ARMCC::AL &&
6073 Inst.getOperand(4).getReg() == ARM::CPSR &&
6074 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6075 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
6076 // The operands aren't the same for tMOV[S]r... (no cc_out)
6077 MCInst TmpInst;
6078 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
6079 TmpInst.addOperand(Inst.getOperand(0));
6080 TmpInst.addOperand(Inst.getOperand(1));
6081 TmpInst.addOperand(Inst.getOperand(2));
6082 TmpInst.addOperand(Inst.getOperand(3));
6083 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006084 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00006085 }
6086 break;
6087 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006088 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00006089 case ARM::t2SXTB:
6090 case ARM::t2UXTH:
6091 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00006092 // If we can use the 16-bit encoding and the user didn't explicitly
6093 // request the 32-bit variant, transform it here.
6094 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6095 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6096 Inst.getOperand(2).getImm() == 0 &&
6097 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
6098 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00006099 unsigned NewOpc;
6100 switch (Inst.getOpcode()) {
6101 default: llvm_unreachable("Illegal opcode!");
6102 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
6103 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
6104 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
6105 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
6106 }
Jim Grosbach326efe52011-09-19 20:29:33 +00006107 // The operands aren't the same for thumb1 (no rotate operand).
6108 MCInst TmpInst;
6109 TmpInst.setOpcode(NewOpc);
6110 TmpInst.addOperand(Inst.getOperand(0));
6111 TmpInst.addOperand(Inst.getOperand(1));
6112 TmpInst.addOperand(Inst.getOperand(3));
6113 TmpInst.addOperand(Inst.getOperand(4));
6114 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006115 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00006116 }
6117 break;
6118 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00006119 case ARM::MOVsi: {
6120 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
6121 if (SOpc == ARM_AM::rrx) return false;
6122 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
6123 // Shifting by zero is accepted as a vanilla 'MOVr'
6124 MCInst TmpInst;
6125 TmpInst.setOpcode(ARM::MOVr);
6126 TmpInst.addOperand(Inst.getOperand(0));
6127 TmpInst.addOperand(Inst.getOperand(1));
6128 TmpInst.addOperand(Inst.getOperand(3));
6129 TmpInst.addOperand(Inst.getOperand(4));
6130 TmpInst.addOperand(Inst.getOperand(5));
6131 Inst = TmpInst;
6132 return true;
6133 }
6134 return false;
6135 }
Jim Grosbach89df9962011-08-26 21:43:41 +00006136 case ARM::t2IT: {
6137 // The mask bits for all but the first condition are represented as
6138 // the low bit of the condition code value implies 't'. We currently
6139 // always have 1 implies 't', so XOR toggle the bits if the low bit
6140 // of the condition code is zero. The encoding also expects the low
6141 // bit of the condition to be encoded as bit 4 of the mask operand,
6142 // so mask that in if needed
6143 MCOperand &MO = Inst.getOperand(1);
6144 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006145 unsigned OrigMask = Mask;
6146 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00006147 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00006148 assert(Mask && TZ <= 3 && "illegal IT mask value!");
6149 for (unsigned i = 3; i != TZ; --i)
6150 Mask ^= 1 << i;
6151 } else
6152 Mask |= 0x10;
6153 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006154
6155 // Set up the IT block state according to the IT instruction we just
6156 // matched.
6157 assert(!inITBlock() && "nested IT blocks?!");
6158 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
6159 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
6160 ITState.CurPosition = 0;
6161 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00006162 break;
6163 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006164 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00006165 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006166}
6167
Jim Grosbach47a0d522011-08-16 20:45:50 +00006168unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
6169 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
6170 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00006171 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00006172 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00006173 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
6174 assert(MCID.hasOptionalDef() &&
6175 "optionally flag setting instruction missing optional def operand");
6176 assert(MCID.NumOperands == Inst.getNumOperands() &&
6177 "operand count mismatch!");
6178 // Find the optional-def operand (cc_out).
6179 unsigned OpNo;
6180 for (OpNo = 0;
6181 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
6182 ++OpNo)
6183 ;
6184 // If we're parsing Thumb1, reject it completely.
6185 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
6186 return Match_MnemonicFail;
6187 // If we're parsing Thumb2, which form is legal depends on whether we're
6188 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006189 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
6190 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00006191 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006192 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
6193 inITBlock())
6194 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006195 }
Jim Grosbach194bd892011-08-16 22:20:01 +00006196 // Some high-register supporting Thumb1 encodings only allow both registers
6197 // to be from r0-r7 when in Thumb2.
6198 else if (Opc == ARM::tADDhirr && isThumbOne() &&
6199 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6200 isARMLowRegister(Inst.getOperand(2).getReg()))
6201 return Match_RequiresThumb2;
6202 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00006203 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00006204 isARMLowRegister(Inst.getOperand(0).getReg()) &&
6205 isARMLowRegister(Inst.getOperand(1).getReg()))
6206 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00006207 return Match_Success;
6208}
6209
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006210bool ARMAsmParser::
6211MatchAndEmitInstruction(SMLoc IDLoc,
6212 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
6213 MCStreamer &Out) {
6214 MCInst Inst;
6215 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006216 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006217 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00006218 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00006219 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006220 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00006221 // Context sensitive operand constraints aren't handled by the matcher,
6222 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00006223 if (validateInstruction(Inst, Operands)) {
6224 // Still progress the IT block, otherwise one wrong condition causes
6225 // nasty cascading errors.
6226 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00006227 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00006228 }
Jim Grosbach189610f2011-07-26 18:25:39 +00006229
Jim Grosbachf8fce712011-08-11 17:35:48 +00006230 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00006231 // encoding is selected. Loop on it while changes happen so the
6232 // individual transformations can chain off each other. E.g.,
6233 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
6234 while (processInstruction(Inst, Operands))
6235 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006236
Jim Grosbacha1109882011-09-02 23:22:08 +00006237 // Only move forward at the very end so that everything in validate
6238 // and process gets a consistent answer about whether we're in an IT
6239 // block.
6240 forwardITPosition();
6241
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006242 Out.EmitInstruction(Inst);
6243 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00006244 case Match_MissingFeature:
6245 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
6246 return true;
6247 case Match_InvalidOperand: {
6248 SMLoc ErrorLoc = IDLoc;
6249 if (ErrorInfo != ~0U) {
6250 if (ErrorInfo >= Operands.size())
6251 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00006252
Chris Lattnere73d4f82010-10-28 21:41:58 +00006253 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
6254 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
6255 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006256
Chris Lattnere73d4f82010-10-28 21:41:58 +00006257 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006258 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00006259 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00006260 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00006261 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00006262 // The converter function will have already emited a diagnostic.
6263 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00006264 case Match_RequiresNotITBlock:
6265 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00006266 case Match_RequiresITBlock:
6267 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00006268 case Match_RequiresV6:
6269 return Error(IDLoc, "instruction variant requires ARMv6 or later");
6270 case Match_RequiresThumb2:
6271 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00006272 }
Jim Grosbach16c74252010-10-29 14:46:02 +00006273
Eric Christopherc223e2b2010-10-29 09:26:59 +00006274 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00006275 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00006276}
6277
Jim Grosbach1355cf12011-07-26 17:10:22 +00006278/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006279bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
6280 StringRef IDVal = DirectiveID.getIdentifier();
6281 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006282 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006283 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006284 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00006285 else if (IDVal == ".arm")
6286 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006287 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006288 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006289 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006290 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00006291 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00006292 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00006293 else if (IDVal == ".unreq")
6294 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00006295 else if (IDVal == ".arch")
6296 return parseDirectiveArch(DirectiveID.getLoc());
6297 else if (IDVal == ".eabi_attribute")
6298 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006299 return true;
6300}
6301
Jim Grosbach1355cf12011-07-26 17:10:22 +00006302/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006303/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00006304bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006305 if (getLexer().isNot(AsmToken::EndOfStatement)) {
6306 for (;;) {
6307 const MCExpr *Value;
6308 if (getParser().ParseExpression(Value))
6309 return true;
6310
Chris Lattneraaec2052010-01-19 19:46:13 +00006311 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006312
6313 if (getLexer().is(AsmToken::EndOfStatement))
6314 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00006315
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006316 // FIXME: Improve diagnostic.
6317 if (getLexer().isNot(AsmToken::Comma))
6318 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006319 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006320 }
6321 }
6322
Sean Callananb9a25b72010-01-19 20:27:46 +00006323 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006324 return false;
6325}
6326
Jim Grosbach1355cf12011-07-26 17:10:22 +00006327/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00006328/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00006329bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00006330 if (getLexer().isNot(AsmToken::EndOfStatement))
6331 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006332 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006333
Jim Grosbach9a70df92011-12-07 18:04:19 +00006334 if (!isThumb())
6335 SwitchMode();
6336 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
6337 return false;
6338}
6339
6340/// parseDirectiveARM
6341/// ::= .arm
6342bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
6343 if (getLexer().isNot(AsmToken::EndOfStatement))
6344 return Error(L, "unexpected token in directive");
6345 Parser.Lex();
6346
6347 if (isThumb())
6348 SwitchMode();
6349 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00006350 return false;
6351}
6352
Jim Grosbach1355cf12011-07-26 17:10:22 +00006353/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00006354/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00006355bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00006356 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
6357 bool isMachO = MAI.hasSubsectionsViaSymbols();
6358 StringRef Name;
6359
6360 // Darwin asm has function name after .thumb_func direction
6361 // ELF doesn't
6362 if (isMachO) {
6363 const AsmToken &Tok = Parser.getTok();
6364 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
6365 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00006366 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006367 Parser.Lex(); // Consume the identifier token.
6368 }
6369
Jim Grosbachd475f862011-11-10 20:48:53 +00006370 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00006371 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006372 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006373
Rafael Espindola64695402011-05-16 16:17:21 +00006374 // FIXME: assuming function name will be the line following .thumb_func
6375 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00006376 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00006377 }
6378
Jim Grosbach642fc9c2010-11-05 22:33:53 +00006379 // Mark symbol as a thumb symbol.
6380 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
6381 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00006382 return false;
6383}
6384
Jim Grosbach1355cf12011-07-26 17:10:22 +00006385/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00006386/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00006387bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006388 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006389 if (Tok.isNot(AsmToken::Identifier))
6390 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00006391 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00006392 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00006393 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006394 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00006395 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00006396 else
6397 return Error(L, "unrecognized syntax mode in .syntax directive");
6398
6399 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006400 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006401 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006402
6403 // TODO tell the MC streamer the mode
6404 // getParser().getStreamer().Emit???();
6405 return false;
6406}
6407
Jim Grosbach1355cf12011-07-26 17:10:22 +00006408/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00006409/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00006410bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00006411 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00006412 if (Tok.isNot(AsmToken::Integer))
6413 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00006414 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00006415 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00006416 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00006417 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00006418 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006419 else
6420 return Error(L, "invalid operand to .code directive");
6421
6422 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00006423 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00006424 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00006425
Evan Cheng32869202011-07-08 22:36:29 +00006426 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00006427 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006428 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006429 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00006430 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00006431 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00006432 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00006433 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00006434 }
Jim Grosbach2a301702010-11-05 22:40:53 +00006435
Kevin Enderby515d5092009-10-15 20:48:48 +00006436 return false;
6437}
6438
Jim Grosbacha39cda72011-12-14 02:16:11 +00006439/// parseDirectiveReq
6440/// ::= name .req registername
6441bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
6442 Parser.Lex(); // Eat the '.req' token.
6443 unsigned Reg;
6444 SMLoc SRegLoc, ERegLoc;
6445 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
6446 Parser.EatToEndOfStatement();
6447 return Error(SRegLoc, "register name expected");
6448 }
6449
6450 // Shouldn't be anything else.
6451 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
6452 Parser.EatToEndOfStatement();
6453 return Error(Parser.getTok().getLoc(),
6454 "unexpected input in .req directive.");
6455 }
6456
6457 Parser.Lex(); // Consume the EndOfStatement
6458
6459 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
6460 return Error(SRegLoc, "redefinition of '" + Name +
6461 "' does not match original.");
6462
6463 return false;
6464}
6465
6466/// parseDirectiveUneq
6467/// ::= .unreq registername
6468bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6469 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6470 Parser.EatToEndOfStatement();
6471 return Error(L, "unexpected input in .unreq directive.");
6472 }
6473 RegisterReqs.erase(Parser.getTok().getIdentifier());
6474 Parser.Lex(); // Eat the identifier.
6475 return false;
6476}
6477
Jason W Kimd7c9e082011-12-20 17:38:12 +00006478/// parseDirectiveArch
6479/// ::= .arch token
6480bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
6481 return true;
6482}
6483
6484/// parseDirectiveEabiAttr
6485/// ::= .eabi_attribute int, int
6486bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
6487 return true;
6488}
6489
Sean Callanan90b70972010-04-07 20:29:34 +00006490extern "C" void LLVMInitializeARMAsmLexer();
6491
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006492/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006493extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006494 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6495 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006496 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006497}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006498
Chris Lattner0692ee62010-09-06 19:11:01 +00006499#define GET_REGISTER_MATCHER
6500#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006501#include "ARMGenAsmMatcher.inc"