blob: f22c2abcf7fb00767f386c2d9435744ca004f799 [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);
Kevin Enderby515d5092009-10-15 20:48:48 +0000104
Jim Grosbach1355cf12011-07-26 17:10:22 +0000105 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000106 bool &CarrySetting, unsigned &ProcessorIMod,
107 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000108 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000109 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000110
Evan Chengebdeeab2011-07-08 01:53:10 +0000111 bool isThumb() const {
112 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000113 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000114 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000115 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000116 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000117 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000118 bool isThumbTwo() const {
119 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
120 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000121 bool hasV6Ops() const {
122 return STI.getFeatureBits() & ARM::HasV6Ops;
123 }
James Molloyacad68d2011-09-28 14:21:38 +0000124 bool hasV7Ops() const {
125 return STI.getFeatureBits() & ARM::HasV7Ops;
126 }
Evan Cheng32869202011-07-08 22:36:29 +0000127 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000128 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
129 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000130 }
James Molloyacad68d2011-09-28 14:21:38 +0000131 bool isMClass() const {
132 return STI.getFeatureBits() & ARM::FeatureMClass;
133 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000134
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000135 /// @name Auto-generated Match Functions
136 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000137
Chris Lattner0692ee62010-09-06 19:11:01 +0000138#define GET_ASSEMBLER_HEADER
139#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000140
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000141 /// }
142
Jim Grosbach89df9962011-08-26 21:43:41 +0000143 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000144 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000145 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000146 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000147 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000148 OperandMatchResultTy parseCoprocOptionOperand(
149 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000150 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000151 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000152 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000153 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000154 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000155 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000156 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
157 StringRef Op, int Low, int High);
158 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
159 return parsePKHImm(O, "lsl", 0, 31);
160 }
161 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
162 return parsePKHImm(O, "asr", 1, 32);
163 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000164 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000165 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000166 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000167 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000168 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000169 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000170 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000171 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000172 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000173
174 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000175 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
176 const SmallVectorImpl<MCParsedAsmOperand*> &);
177 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
178 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000179 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
180 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000181 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
182 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000183 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000184 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000185 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
186 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000187 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
188 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000189 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000190 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000191 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
192 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000193 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
194 const SmallVectorImpl<MCParsedAsmOperand*> &);
195 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
196 const SmallVectorImpl<MCParsedAsmOperand*> &);
197 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
198 const SmallVectorImpl<MCParsedAsmOperand*> &);
199 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
200 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000201 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
202 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000203 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
204 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000205 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
206 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000207 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
208 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000209 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
210 const SmallVectorImpl<MCParsedAsmOperand*> &);
211 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
212 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000213 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
214 const SmallVectorImpl<MCParsedAsmOperand*> &);
215 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
216 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000217
218 bool validateInstruction(MCInst &Inst,
219 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000220 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000221 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000222 bool shouldOmitCCOutOperand(StringRef Mnemonic,
223 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000224
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000225public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000226 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000227 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000228 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000229 Match_RequiresV6,
230 Match_RequiresThumb2
Jim Grosbach47a0d522011-08-16 20:45:50 +0000231 };
232
Evan Chengffc0e732011-07-09 05:47:46 +0000233 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000234 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000235 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000236
Evan Chengebdeeab2011-07-08 01:53:10 +0000237 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000238 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000239
240 // Not in an ITBlock to start with.
241 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000242 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000243
Jim Grosbach1355cf12011-07-26 17:10:22 +0000244 // Implementation of the MCTargetAsmParser interface:
245 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
246 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000247 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000248 bool ParseDirective(AsmToken DirectiveID);
249
Jim Grosbach47a0d522011-08-16 20:45:50 +0000250 unsigned checkTargetMatchPredicate(MCInst &Inst);
251
Jim Grosbach1355cf12011-07-26 17:10:22 +0000252 bool MatchAndEmitInstruction(SMLoc IDLoc,
253 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
254 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000255};
Jim Grosbach16c74252010-10-29 14:46:02 +0000256} // end anonymous namespace
257
Chris Lattner3a697562010-10-28 17:20:03 +0000258namespace {
259
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000260/// ARMOperand - Instances of this class represent a parsed ARM machine
261/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000262class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000263 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000264 k_CondCode,
265 k_CCOut,
266 k_ITCondMask,
267 k_CoprocNum,
268 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000269 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000270 k_Immediate,
271 k_FPImmediate,
272 k_MemBarrierOpt,
273 k_Memory,
274 k_PostIndexRegister,
275 k_MSRMask,
276 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000277 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000278 k_Register,
279 k_RegisterList,
280 k_DPRRegisterList,
281 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000282 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000283 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000284 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000285 k_ShiftedRegister,
286 k_ShiftedImmediate,
287 k_ShifterImmediate,
288 k_RotateImmediate,
289 k_BitfieldDescriptor,
290 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000291 } Kind;
292
Sean Callanan76264762010-04-02 22:27:05 +0000293 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000294 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000295
296 union {
297 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000298 ARMCC::CondCodes Val;
299 } CC;
300
301 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000302 unsigned Val;
303 } Cop;
304
305 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000306 unsigned Val;
307 } CoprocOption;
308
309 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000310 unsigned Mask:4;
311 } ITMask;
312
313 struct {
314 ARM_MB::MemBOpt Val;
315 } MBOpt;
316
317 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000318 ARM_PROC::IFlags Val;
319 } IFlags;
320
321 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000322 unsigned Val;
323 } MMask;
324
325 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000326 const char *Data;
327 unsigned Length;
328 } Tok;
329
330 struct {
331 unsigned RegNum;
332 } Reg;
333
Jim Grosbach862019c2011-10-18 23:02:30 +0000334 // A vector register list is a sequential list of 1 to 4 registers.
335 struct {
336 unsigned RegNum;
337 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000338 unsigned LaneIndex;
Jim Grosbach862019c2011-10-18 23:02:30 +0000339 } VectorList;
340
Bill Wendling8155e5b2010-11-06 22:19:43 +0000341 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000342 unsigned Val;
343 } VectorIndex;
344
345 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000346 const MCExpr *Val;
347 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000348
Jim Grosbach9d390362011-10-03 23:38:36 +0000349 struct {
350 unsigned Val; // encoded 8-bit representation
351 } FPImm;
352
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000353 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000354 struct {
355 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000356 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
357 // was specified.
358 const MCConstantExpr *OffsetImm; // Offset immediate value
359 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
360 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000361 unsigned ShiftImm; // shift for OffsetReg.
362 unsigned Alignment; // 0 = no alignment specified
363 // n = alignment in bytes (8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000364 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000365 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000366
367 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000368 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000369 bool isAdd;
370 ARM_AM::ShiftOpc ShiftTy;
371 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000372 } PostIdxReg;
373
374 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000375 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000376 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000377 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000378 struct {
379 ARM_AM::ShiftOpc ShiftTy;
380 unsigned SrcReg;
381 unsigned ShiftReg;
382 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000383 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000384 struct {
385 ARM_AM::ShiftOpc ShiftTy;
386 unsigned SrcReg;
387 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000388 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000389 struct {
390 unsigned Imm;
391 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000392 struct {
393 unsigned LSB;
394 unsigned Width;
395 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000396 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000397
Bill Wendling146018f2010-11-06 21:42:12 +0000398 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
399public:
Sean Callanan76264762010-04-02 22:27:05 +0000400 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
401 Kind = o.Kind;
402 StartLoc = o.StartLoc;
403 EndLoc = o.EndLoc;
404 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000405 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000406 CC = o.CC;
407 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000408 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000409 ITMask = o.ITMask;
410 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000411 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000412 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000413 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000414 case k_CCOut:
415 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000416 Reg = o.Reg;
417 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000418 case k_RegisterList:
419 case k_DPRRegisterList:
420 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000421 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000422 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000423 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000424 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000425 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000426 VectorList = o.VectorList;
427 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000428 case k_CoprocNum:
429 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000430 Cop = o.Cop;
431 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000432 case k_CoprocOption:
433 CoprocOption = o.CoprocOption;
434 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000435 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000436 Imm = o.Imm;
437 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000438 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +0000439 FPImm = o.FPImm;
440 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000441 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000442 MBOpt = o.MBOpt;
443 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000444 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000445 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000446 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000447 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000448 PostIdxReg = o.PostIdxReg;
449 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000450 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000451 MMask = o.MMask;
452 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000453 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000454 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000455 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000456 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000457 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000458 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000459 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000460 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000461 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000462 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000463 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000464 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000465 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000466 RotImm = o.RotImm;
467 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000468 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000469 Bitfield = o.Bitfield;
470 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000471 case k_VectorIndex:
472 VectorIndex = o.VectorIndex;
473 break;
Sean Callanan76264762010-04-02 22:27:05 +0000474 }
475 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000476
Sean Callanan76264762010-04-02 22:27:05 +0000477 /// getStartLoc - Get the location of the first token of this operand.
478 SMLoc getStartLoc() const { return StartLoc; }
479 /// getEndLoc - Get the location of the last token of this operand.
480 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000481
Daniel Dunbar8462b302010-08-11 06:36:53 +0000482 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000483 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000484 return CC.Val;
485 }
486
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000487 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000488 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000489 return Cop.Val;
490 }
491
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000492 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000494 return StringRef(Tok.Data, Tok.Length);
495 }
496
497 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000499 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000500 }
501
Bill Wendling5fa22a12010-11-09 23:28:44 +0000502 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000503 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
504 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000505 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000506 }
507
Kevin Enderbycfe07242009-10-13 22:19:02 +0000508 const MCExpr *getImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000509 assert(Kind == k_Immediate && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000510 return Imm.Val;
511 }
512
Jim Grosbach9d390362011-10-03 23:38:36 +0000513 unsigned getFPImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000514 assert(Kind == k_FPImmediate && "Invalid access!");
Jim Grosbach9d390362011-10-03 23:38:36 +0000515 return FPImm.Val;
516 }
517
Jim Grosbach460a9052011-10-07 23:56:00 +0000518 unsigned getVectorIndex() const {
519 assert(Kind == k_VectorIndex && "Invalid access!");
520 return VectorIndex.Val;
521 }
522
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000523 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000524 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000525 return MBOpt.Val;
526 }
527
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000528 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000530 return IFlags.Val;
531 }
532
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000533 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000534 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000535 return MMask.Val;
536 }
537
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000538 bool isCoprocNum() const { return Kind == k_CoprocNum; }
539 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000540 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000541 bool isCondCode() const { return Kind == k_CondCode; }
542 bool isCCOut() const { return Kind == k_CCOut; }
543 bool isITMask() const { return Kind == k_ITCondMask; }
544 bool isITCondCode() const { return Kind == k_CondCode; }
545 bool isImm() const { return Kind == k_Immediate; }
546 bool isFPImm() const { return Kind == k_FPImmediate; }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000547 bool isImm8s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000548 if (Kind != k_Immediate)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000549 return false;
550 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
551 if (!CE) return false;
552 int64_t Value = CE->getValue();
553 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
554 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000555 bool isImm0_1020s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000556 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000557 return false;
558 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
559 if (!CE) return false;
560 int64_t Value = CE->getValue();
561 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
562 }
563 bool isImm0_508s4() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000564 if (Kind != k_Immediate)
Jim Grosbach72f39f82011-08-24 21:22:15 +0000565 return false;
566 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
567 if (!CE) return false;
568 int64_t Value = CE->getValue();
569 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
570 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000571 bool isImm0_255() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000572 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000573 return false;
574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
575 if (!CE) return false;
576 int64_t Value = CE->getValue();
577 return Value >= 0 && Value < 256;
578 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000579 bool isImm0_1() const {
580 if (Kind != k_Immediate)
581 return false;
582 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
583 if (!CE) return false;
584 int64_t Value = CE->getValue();
585 return Value >= 0 && Value < 2;
586 }
587 bool isImm0_3() const {
588 if (Kind != k_Immediate)
589 return false;
590 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
591 if (!CE) return false;
592 int64_t Value = CE->getValue();
593 return Value >= 0 && Value < 4;
594 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000595 bool isImm0_7() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000596 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000597 return false;
598 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
599 if (!CE) return false;
600 int64_t Value = CE->getValue();
601 return Value >= 0 && Value < 8;
602 }
603 bool isImm0_15() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000604 if (Kind != k_Immediate)
Jim Grosbach83ab0702011-07-13 22:01:08 +0000605 return false;
606 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
607 if (!CE) return false;
608 int64_t Value = CE->getValue();
609 return Value >= 0 && Value < 16;
610 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000611 bool isImm0_31() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000612 if (Kind != k_Immediate)
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000613 return false;
614 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
615 if (!CE) return false;
616 int64_t Value = CE->getValue();
617 return Value >= 0 && Value < 32;
618 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000619 bool isImm0_63() const {
620 if (Kind != k_Immediate)
621 return false;
622 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623 if (!CE) return false;
624 int64_t Value = CE->getValue();
625 return Value >= 0 && Value < 64;
626 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000627 bool isImm8() const {
628 if (Kind != k_Immediate)
629 return false;
630 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
631 if (!CE) return false;
632 int64_t Value = CE->getValue();
633 return Value == 8;
634 }
635 bool isImm16() const {
636 if (Kind != k_Immediate)
637 return false;
638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
639 if (!CE) return false;
640 int64_t Value = CE->getValue();
641 return Value == 16;
642 }
643 bool isImm32() const {
644 if (Kind != k_Immediate)
645 return false;
646 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
647 if (!CE) return false;
648 int64_t Value = CE->getValue();
649 return Value == 32;
650 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000651 bool isShrImm8() const {
652 if (Kind != k_Immediate)
653 return false;
654 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
655 if (!CE) return false;
656 int64_t Value = CE->getValue();
657 return Value > 0 && Value <= 8;
658 }
659 bool isShrImm16() const {
660 if (Kind != k_Immediate)
661 return false;
662 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
663 if (!CE) return false;
664 int64_t Value = CE->getValue();
665 return Value > 0 && Value <= 16;
666 }
667 bool isShrImm32() const {
668 if (Kind != k_Immediate)
669 return false;
670 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
671 if (!CE) return false;
672 int64_t Value = CE->getValue();
673 return Value > 0 && Value <= 32;
674 }
675 bool isShrImm64() const {
676 if (Kind != k_Immediate)
677 return false;
678 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679 if (!CE) return false;
680 int64_t Value = CE->getValue();
681 return Value > 0 && Value <= 64;
682 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000683 bool isImm1_7() const {
684 if (Kind != k_Immediate)
685 return false;
686 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
687 if (!CE) return false;
688 int64_t Value = CE->getValue();
689 return Value > 0 && Value < 8;
690 }
691 bool isImm1_15() const {
692 if (Kind != k_Immediate)
693 return false;
694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
695 if (!CE) return false;
696 int64_t Value = CE->getValue();
697 return Value > 0 && Value < 16;
698 }
699 bool isImm1_31() const {
700 if (Kind != k_Immediate)
701 return false;
702 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
703 if (!CE) return false;
704 int64_t Value = CE->getValue();
705 return Value > 0 && Value < 32;
706 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000707 bool isImm1_16() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000708 if (Kind != k_Immediate)
Jim Grosbachf4943352011-07-25 23:09:14 +0000709 return false;
710 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
711 if (!CE) return false;
712 int64_t Value = CE->getValue();
713 return Value > 0 && Value < 17;
714 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000715 bool isImm1_32() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000716 if (Kind != k_Immediate)
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000717 return false;
718 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
719 if (!CE) return false;
720 int64_t Value = CE->getValue();
721 return Value > 0 && Value < 33;
722 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000723 bool isImm0_32() const {
724 if (Kind != k_Immediate)
725 return false;
726 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
727 if (!CE) return false;
728 int64_t Value = CE->getValue();
729 return Value >= 0 && Value < 33;
730 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000731 bool isImm0_65535() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000732 if (Kind != k_Immediate)
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000733 return false;
734 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
735 if (!CE) return false;
736 int64_t Value = CE->getValue();
737 return Value >= 0 && Value < 65536;
738 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000739 bool isImm0_65535Expr() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000740 if (Kind != k_Immediate)
Jim Grosbachffa32252011-07-19 19:13:28 +0000741 return false;
742 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
743 // If it's not a constant expression, it'll generate a fixup and be
744 // handled later.
745 if (!CE) return true;
746 int64_t Value = CE->getValue();
747 return Value >= 0 && Value < 65536;
748 }
Jim Grosbached838482011-07-26 16:24:27 +0000749 bool isImm24bit() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000750 if (Kind != k_Immediate)
Jim Grosbached838482011-07-26 16:24:27 +0000751 return false;
752 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
753 if (!CE) return false;
754 int64_t Value = CE->getValue();
755 return Value >= 0 && Value <= 0xffffff;
756 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000757 bool isImmThumbSR() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000758 if (Kind != k_Immediate)
Jim Grosbach70939ee2011-08-17 21:51:27 +0000759 return false;
760 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
761 if (!CE) return false;
762 int64_t Value = CE->getValue();
763 return Value > 0 && Value < 33;
764 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000765 bool isPKHLSLImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000766 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000767 return false;
768 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
769 if (!CE) return false;
770 int64_t Value = CE->getValue();
771 return Value >= 0 && Value < 32;
772 }
773 bool isPKHASRImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000774 if (Kind != k_Immediate)
Jim Grosbachf6c05252011-07-21 17:23:04 +0000775 return false;
776 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
777 if (!CE) return false;
778 int64_t Value = CE->getValue();
779 return Value > 0 && Value <= 32;
780 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000781 bool isARMSOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000782 if (Kind != k_Immediate)
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000783 return false;
784 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
785 if (!CE) return false;
786 int64_t Value = CE->getValue();
787 return ARM_AM::getSOImmVal(Value) != -1;
788 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000789 bool isARMSOImmNot() const {
790 if (Kind != k_Immediate)
791 return false;
792 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793 if (!CE) return false;
794 int64_t Value = CE->getValue();
795 return ARM_AM::getSOImmVal(~Value) != -1;
796 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000797 bool isARMSOImmNeg() const {
798 if (Kind != k_Immediate)
799 return false;
800 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
801 if (!CE) return false;
802 int64_t Value = CE->getValue();
803 return ARM_AM::getSOImmVal(-Value) != -1;
804 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000805 bool isT2SOImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000806 if (Kind != k_Immediate)
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000807 return false;
808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
809 if (!CE) return false;
810 int64_t Value = CE->getValue();
811 return ARM_AM::getT2SOImmVal(Value) != -1;
812 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000813 bool isT2SOImmNot() const {
814 if (Kind != k_Immediate)
815 return false;
816 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
817 if (!CE) return false;
818 int64_t Value = CE->getValue();
819 return ARM_AM::getT2SOImmVal(~Value) != -1;
820 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000821 bool isT2SOImmNeg() const {
822 if (Kind != k_Immediate)
823 return false;
824 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
825 if (!CE) return false;
826 int64_t Value = CE->getValue();
827 return ARM_AM::getT2SOImmVal(-Value) != -1;
828 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000829 bool isSetEndImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000830 if (Kind != k_Immediate)
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000831 return false;
832 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
833 if (!CE) return false;
834 int64_t Value = CE->getValue();
835 return Value == 1 || Value == 0;
836 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000837 bool isReg() const { return Kind == k_Register; }
838 bool isRegList() const { return Kind == k_RegisterList; }
839 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
840 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
841 bool isToken() const { return Kind == k_Token; }
842 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
843 bool isMemory() const { return Kind == k_Memory; }
844 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
845 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
846 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
847 bool isRotImm() const { return Kind == k_RotateImmediate; }
848 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
849 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000850 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000851 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000852 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000853 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000854 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000855 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000856 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000857 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
858 (alignOK || Memory.Alignment == 0);
859 }
860 bool isAlignedMemory() const {
861 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000862 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000863 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000864 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000865 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000866 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000867 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000868 if (!Memory.OffsetImm) return true;
869 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000870 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000871 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000872 bool isAM2OffsetImm() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000873 if (Kind != k_Immediate)
Jim Grosbach039c2e12011-08-04 23:01:30 +0000874 return false;
875 // Immediate offset in range [-4095, 4095].
876 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
877 if (!CE) return false;
878 int64_t Val = CE->getValue();
879 return Val > -4096 && Val < 4096;
880 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000881 bool isAddrMode3() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000882 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000883 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000884 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000885 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000886 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000887 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000888 if (!Memory.OffsetImm) return true;
889 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000890 return Val > -256 && Val < 256;
891 }
892 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000893 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000894 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000895 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000896 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
897 // Immediate offset in range [-255, 255].
898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
899 if (!CE) return false;
900 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000901 // Special case, #-0 is INT32_MIN.
902 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000903 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000904 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000905 // If we have an immediate that's not a constant, treat it as a label
906 // reference needing a fixup. If it is a constant, it's something else
907 // and we reject it.
908 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
909 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000910 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000911 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000912 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000913 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000914 if (!Memory.OffsetImm) return true;
915 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000916 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000917 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000918 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000919 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000920 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000921 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000922 return false;
923 return true;
924 }
925 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000926 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000927 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
928 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000929 return false;
930 return true;
931 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000932 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000933 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000934 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000935 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000936 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000937 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000938 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
939 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000940 return false;
941 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000942 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000943 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000945 return false;
946 return true;
947 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000948 bool isMemThumbRR() const {
949 // Thumb reg+reg addressing is simple. Just two registers, a base and
950 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000951 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000952 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000953 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000954 return isARMLowRegister(Memory.BaseRegNum) &&
955 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000956 }
957 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000958 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000959 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000960 return false;
961 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000962 if (!Memory.OffsetImm) return true;
963 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000964 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
965 }
Jim Grosbach38466302011-08-19 18:55:51 +0000966 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000967 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000968 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +0000969 return false;
970 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000971 if (!Memory.OffsetImm) return true;
972 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +0000973 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
974 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000975 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000977 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000978 return false;
979 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000980 if (!Memory.OffsetImm) return true;
981 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +0000982 return Val >= 0 && Val <= 31;
983 }
Jim Grosbachecd85892011-08-19 18:13:48 +0000984 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000985 if (!isMemory() || Memory.OffsetRegNum != 0 ||
986 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +0000987 return false;
988 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000989 if (!Memory.OffsetImm) return true;
990 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000991 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000992 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000993 bool isMemImm8s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000994 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +0000995 return false;
996 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000997 if (!Memory.OffsetImm) return true;
998 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +0000999 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1000 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001001 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001002 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001003 return false;
1004 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001005 if (!Memory.OffsetImm) return true;
1006 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001007 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1008 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001009 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001010 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001011 return false;
1012 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001013 if (!Memory.OffsetImm) return true;
1014 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001015 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001016 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001017 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001018 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001019 return false;
1020 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001023 return Val >= 0 && Val < 256;
1024 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001025 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001026 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001027 return false;
1028 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001029 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001030 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001031 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001032 }
1033 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001034 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001035 return false;
1036 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001037 if (!Memory.OffsetImm) return true;
1038 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001039 return (Val >= 0 && Val < 4096);
1040 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001041 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001042 // If we have an immediate that's not a constant, treat it as a label
1043 // reference needing a fixup. If it is a constant, it's something else
1044 // and we reject it.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001045 if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001046 return true;
1047
Jim Grosbach57dcb852011-10-11 17:29:55 +00001048 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001049 return false;
1050 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001051 if (!Memory.OffsetImm) return true;
1052 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001053 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001054 }
1055 bool isPostIdxImm8() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001056 if (Kind != k_Immediate)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001057 return false;
1058 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1059 if (!CE) return false;
1060 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001061 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001062 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001063 bool isPostIdxImm8s4() const {
1064 if (Kind != k_Immediate)
1065 return false;
1066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 if (!CE) return false;
1068 int64_t Val = CE->getValue();
1069 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1070 (Val == INT32_MIN);
1071 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001072
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001073 bool isMSRMask() const { return Kind == k_MSRMask; }
1074 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001075
Jim Grosbach0e387b22011-10-17 22:26:03 +00001076 // NEON operands.
Jim Grosbach862019c2011-10-18 23:02:30 +00001077 bool isVecListOneD() const {
1078 if (Kind != k_VectorList) return false;
1079 return VectorList.Count == 1;
1080 }
1081
Jim Grosbach280dfad2011-10-21 18:54:25 +00001082 bool isVecListTwoD() const {
1083 if (Kind != k_VectorList) return false;
1084 return VectorList.Count == 2;
1085 }
1086
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001087 bool isVecListThreeD() const {
1088 if (Kind != k_VectorList) return false;
1089 return VectorList.Count == 3;
1090 }
1091
Jim Grosbachb6310312011-10-21 20:35:01 +00001092 bool isVecListFourD() const {
1093 if (Kind != k_VectorList) return false;
1094 return VectorList.Count == 4;
1095 }
1096
Jim Grosbach4661d4c2011-10-21 22:21:10 +00001097 bool isVecListTwoQ() const {
1098 if (Kind != k_VectorList) return false;
1099 //FIXME: We haven't taught the parser to handle by-two register lists
1100 // yet, so don't pretend to know one.
1101 return VectorList.Count == 2 && false;
1102 }
1103
Jim Grosbach98b05a52011-11-30 01:09:44 +00001104 bool isVecListOneDAllLanes() const {
1105 if (Kind != k_VectorListAllLanes) return false;
1106 return VectorList.Count == 1;
1107 }
1108
Jim Grosbach13af2222011-11-30 18:21:25 +00001109 bool isVecListTwoDAllLanes() const {
1110 if (Kind != k_VectorListAllLanes) return false;
1111 return VectorList.Count == 2;
1112 }
1113
Jim Grosbach7636bf62011-12-02 00:35:16 +00001114 bool isVecListOneDByteIndexed() const {
1115 if (Kind != k_VectorListIndexed) return false;
1116 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1117 }
1118
Jim Grosbach460a9052011-10-07 23:56:00 +00001119 bool isVectorIndex8() const {
1120 if (Kind != k_VectorIndex) return false;
1121 return VectorIndex.Val < 8;
1122 }
1123 bool isVectorIndex16() const {
1124 if (Kind != k_VectorIndex) return false;
1125 return VectorIndex.Val < 4;
1126 }
1127 bool isVectorIndex32() const {
1128 if (Kind != k_VectorIndex) return false;
1129 return VectorIndex.Val < 2;
1130 }
1131
Jim Grosbach0e387b22011-10-17 22:26:03 +00001132 bool isNEONi8splat() const {
1133 if (Kind != k_Immediate)
1134 return false;
1135 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1136 // Must be a constant.
1137 if (!CE) return false;
1138 int64_t Value = CE->getValue();
1139 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1140 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001141 return Value >= 0 && Value < 256;
1142 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001143
Jim Grosbachea461102011-10-17 23:09:09 +00001144 bool isNEONi16splat() const {
1145 if (Kind != k_Immediate)
1146 return false;
1147 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1148 // Must be a constant.
1149 if (!CE) return false;
1150 int64_t Value = CE->getValue();
1151 // i16 value in the range [0,255] or [0x0100, 0xff00]
1152 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1153 }
1154
Jim Grosbach6248a542011-10-18 00:22:00 +00001155 bool isNEONi32splat() const {
1156 if (Kind != k_Immediate)
1157 return false;
1158 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1159 // Must be a constant.
1160 if (!CE) return false;
1161 int64_t Value = CE->getValue();
1162 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1163 return (Value >= 0 && Value < 256) ||
1164 (Value >= 0x0100 && Value <= 0xff00) ||
1165 (Value >= 0x010000 && Value <= 0xff0000) ||
1166 (Value >= 0x01000000 && Value <= 0xff000000);
1167 }
1168
1169 bool isNEONi32vmov() const {
1170 if (Kind != k_Immediate)
1171 return false;
1172 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1173 // Must be a constant.
1174 if (!CE) return false;
1175 int64_t Value = CE->getValue();
1176 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1177 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1178 return (Value >= 0 && Value < 256) ||
1179 (Value >= 0x0100 && Value <= 0xff00) ||
1180 (Value >= 0x010000 && Value <= 0xff0000) ||
1181 (Value >= 0x01000000 && Value <= 0xff000000) ||
1182 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1183 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1184 }
1185
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001186 bool isNEONi64splat() const {
1187 if (Kind != k_Immediate)
1188 return false;
1189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1190 // Must be a constant.
1191 if (!CE) return false;
1192 uint64_t Value = CE->getValue();
1193 // i64 value with each byte being either 0 or 0xff.
1194 for (unsigned i = 0; i < 8; ++i)
1195 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1196 return true;
1197 }
1198
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001199 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001200 // Add as immediates when possible. Null MCExpr = 0.
1201 if (Expr == 0)
1202 Inst.addOperand(MCOperand::CreateImm(0));
1203 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001204 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1205 else
1206 Inst.addOperand(MCOperand::CreateExpr(Expr));
1207 }
1208
Daniel Dunbar8462b302010-08-11 06:36:53 +00001209 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001210 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001211 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001212 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1213 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001214 }
1215
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001216 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1217 assert(N == 1 && "Invalid number of operands!");
1218 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1219 }
1220
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001221 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1222 assert(N == 1 && "Invalid number of operands!");
1223 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1224 }
1225
1226 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1227 assert(N == 1 && "Invalid number of operands!");
1228 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1229 }
1230
Jim Grosbach89df9962011-08-26 21:43:41 +00001231 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1232 assert(N == 1 && "Invalid number of operands!");
1233 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1234 }
1235
1236 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1237 assert(N == 1 && "Invalid number of operands!");
1238 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1239 }
1240
Jim Grosbachd67641b2010-12-06 18:21:12 +00001241 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1242 assert(N == 1 && "Invalid number of operands!");
1243 Inst.addOperand(MCOperand::CreateReg(getReg()));
1244 }
1245
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001246 void addRegOperands(MCInst &Inst, unsigned N) const {
1247 assert(N == 1 && "Invalid number of operands!");
1248 Inst.addOperand(MCOperand::CreateReg(getReg()));
1249 }
1250
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001251 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001252 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001253 assert(isRegShiftedReg() &&
1254 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001255 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1256 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001257 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001258 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001259 }
1260
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001261 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001262 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001263 assert(isRegShiftedImm() &&
1264 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001265 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Owen Anderson92a20222011-07-21 18:54:16 +00001266 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001267 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001268 }
1269
Jim Grosbach580f4a92011-07-25 22:20:28 +00001270 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001271 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001272 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1273 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001274 }
1275
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001276 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001277 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001278 const SmallVectorImpl<unsigned> &RegList = getRegList();
1279 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001280 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1281 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001282 }
1283
Bill Wendling0f630752010-11-17 04:32:08 +00001284 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1285 addRegListOperands(Inst, N);
1286 }
1287
1288 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1289 addRegListOperands(Inst, N);
1290 }
1291
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001292 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1293 assert(N == 1 && "Invalid number of operands!");
1294 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1295 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1296 }
1297
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001298 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1299 assert(N == 1 && "Invalid number of operands!");
1300 // Munge the lsb/width into a bitfield mask.
1301 unsigned lsb = Bitfield.LSB;
1302 unsigned width = Bitfield.Width;
1303 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1304 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1305 (32 - (lsb + width)));
1306 Inst.addOperand(MCOperand::CreateImm(Mask));
1307 }
1308
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001309 void addImmOperands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
1311 addExpr(Inst, getImm());
1312 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001313
Jim Grosbach9d390362011-10-03 23:38:36 +00001314 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1315 assert(N == 1 && "Invalid number of operands!");
1316 Inst.addOperand(MCOperand::CreateImm(getFPImm()));
1317 }
1318
Jim Grosbacha77295d2011-09-08 22:07:06 +00001319 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1320 assert(N == 1 && "Invalid number of operands!");
1321 // FIXME: We really want to scale the value here, but the LDRD/STRD
1322 // instruction don't encode operands that way yet.
1323 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1324 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1325 }
1326
Jim Grosbach72f39f82011-08-24 21:22:15 +00001327 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1328 assert(N == 1 && "Invalid number of operands!");
1329 // The immediate is scaled by four in the encoding and is stored
1330 // in the MCInst as such. Lop off the low two bits here.
1331 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1332 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1333 }
1334
1335 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1336 assert(N == 1 && "Invalid number of operands!");
1337 // The immediate is scaled by four in the encoding and is stored
1338 // in the MCInst as such. Lop off the low two bits here.
1339 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1340 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1341 }
1342
Jim Grosbachf4943352011-07-25 23:09:14 +00001343 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1344 assert(N == 1 && "Invalid number of operands!");
1345 // The constant encodes as the immediate-1, and we store in the instruction
1346 // the bits as encoded, so subtract off one here.
1347 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1348 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1349 }
1350
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001351 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1352 assert(N == 1 && "Invalid number of operands!");
1353 // The constant encodes as the immediate-1, and we store in the instruction
1354 // the bits as encoded, so subtract off one here.
1355 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1356 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1357 }
1358
Jim Grosbach70939ee2011-08-17 21:51:27 +00001359 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1360 assert(N == 1 && "Invalid number of operands!");
1361 // The constant encodes as the immediate, except for 32, which encodes as
1362 // zero.
1363 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1364 unsigned Imm = CE->getValue();
1365 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1366 }
1367
Jim Grosbachf6c05252011-07-21 17:23:04 +00001368 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1369 assert(N == 1 && "Invalid number of operands!");
1370 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1371 // the instruction as well.
1372 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1373 int Val = CE->getValue();
1374 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1375 }
1376
Jim Grosbach89a63372011-10-28 22:36:30 +00001377 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 // The operand is actually a t2_so_imm, but we have its bitwise
1380 // negation in the assembly source, so twiddle it here.
1381 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1382 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1383 }
1384
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001385 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1386 assert(N == 1 && "Invalid number of operands!");
1387 // The operand is actually a t2_so_imm, but we have its
1388 // negation in the assembly source, so twiddle it here.
1389 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1390 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1391 }
1392
Jim Grosbache70ec842011-10-28 22:50:54 +00001393 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1394 assert(N == 1 && "Invalid number of operands!");
1395 // The operand is actually a so_imm, but we have its bitwise
1396 // negation in the assembly source, so twiddle it here.
1397 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1398 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1399 }
1400
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001401 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
1403 // The operand is actually a so_imm, but we have its
1404 // negation in the assembly source, so twiddle it here.
1405 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1406 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1407 }
1408
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001409 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1412 }
1413
Jim Grosbach7ce05792011-08-03 23:50:40 +00001414 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001416 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001417 }
1418
Jim Grosbach57dcb852011-10-11 17:29:55 +00001419 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 2 && "Invalid number of operands!");
1421 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1422 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1423 }
1424
Jim Grosbach7ce05792011-08-03 23:50:40 +00001425 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001427 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1428 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001429 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1430 // Special case for #-0
1431 if (Val == INT32_MIN) Val = 0;
1432 if (Val < 0) Val = -Val;
1433 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1434 } else {
1435 // For register offset, we encode the shift type and negation flag
1436 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001437 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1438 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001439 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001440 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1441 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001442 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001443 }
1444
Jim Grosbach039c2e12011-08-04 23:01:30 +00001445 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1446 assert(N == 2 && "Invalid number of operands!");
1447 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1448 assert(CE && "non-constant AM2OffsetImm operand!");
1449 int32_t Val = CE->getValue();
1450 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1451 // Special case for #-0
1452 if (Val == INT32_MIN) Val = 0;
1453 if (Val < 0) Val = -Val;
1454 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1455 Inst.addOperand(MCOperand::CreateReg(0));
1456 Inst.addOperand(MCOperand::CreateImm(Val));
1457 }
1458
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001459 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1460 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001461 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1462 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001463 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1464 // Special case for #-0
1465 if (Val == INT32_MIN) Val = 0;
1466 if (Val < 0) Val = -Val;
1467 Val = ARM_AM::getAM3Opc(AddSub, Val);
1468 } else {
1469 // For register offset, we encode the shift type and negation flag
1470 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001471 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001472 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001473 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1474 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001475 Inst.addOperand(MCOperand::CreateImm(Val));
1476 }
1477
1478 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1479 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001480 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001481 int32_t Val =
1482 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1483 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1484 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001485 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001486 }
1487
1488 // Constant offset.
1489 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1490 int32_t Val = CE->getValue();
1491 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1492 // Special case for #-0
1493 if (Val == INT32_MIN) Val = 0;
1494 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001495 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001496 Inst.addOperand(MCOperand::CreateReg(0));
1497 Inst.addOperand(MCOperand::CreateImm(Val));
1498 }
1499
Jim Grosbach7ce05792011-08-03 23:50:40 +00001500 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1501 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001502 // If we have an immediate that's not a constant, treat it as a label
1503 // reference needing a fixup. If it is a constant, it's something else
1504 // and we reject it.
1505 if (isImm()) {
1506 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1507 Inst.addOperand(MCOperand::CreateImm(0));
1508 return;
1509 }
1510
Jim Grosbach7ce05792011-08-03 23:50:40 +00001511 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001512 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001513 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1514 // Special case for #-0
1515 if (Val == INT32_MIN) Val = 0;
1516 if (Val < 0) Val = -Val;
1517 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001518 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001519 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001520 }
1521
Jim Grosbacha77295d2011-09-08 22:07:06 +00001522 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001524 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1525 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001526 Inst.addOperand(MCOperand::CreateImm(Val));
1527 }
1528
Jim Grosbachb6aed502011-09-09 18:37:27 +00001529 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1530 assert(N == 2 && "Invalid number of operands!");
1531 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001532 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1533 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001534 Inst.addOperand(MCOperand::CreateImm(Val));
1535 }
1536
Jim Grosbach7ce05792011-08-03 23:50:40 +00001537 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001539 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1540 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001541 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001542 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001543
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001544 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1545 addMemImm8OffsetOperands(Inst, N);
1546 }
1547
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001548 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001549 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001550 }
1551
1552 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 2 && "Invalid number of operands!");
1554 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001555 if (Kind == k_Immediate) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001556 addExpr(Inst, getImm());
1557 Inst.addOperand(MCOperand::CreateImm(0));
1558 return;
1559 }
1560
1561 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001562 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1563 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001564 Inst.addOperand(MCOperand::CreateImm(Val));
1565 }
1566
Jim Grosbach7ce05792011-08-03 23:50:40 +00001567 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1568 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001569 // If this is an immediate, it's a label reference.
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001570 if (Kind == k_Immediate) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001571 addExpr(Inst, getImm());
1572 Inst.addOperand(MCOperand::CreateImm(0));
1573 return;
1574 }
1575
1576 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001577 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1578 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001579 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001580 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001581
Jim Grosbach7f739be2011-09-19 22:21:13 +00001582 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001584 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1585 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001586 }
1587
1588 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1589 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001590 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1591 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001592 }
1593
Jim Grosbach7ce05792011-08-03 23:50:40 +00001594 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1595 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001596 unsigned Val =
1597 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1598 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001599 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1600 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001601 Inst.addOperand(MCOperand::CreateImm(Val));
1602 }
1603
Jim Grosbachab899c12011-09-07 23:10:15 +00001604 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1605 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001606 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1607 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1608 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001609 }
1610
Jim Grosbach7ce05792011-08-03 23:50:40 +00001611 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1612 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001613 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1614 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001615 }
1616
Jim Grosbach60f91a32011-08-19 17:55:24 +00001617 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1618 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001619 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1620 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001621 Inst.addOperand(MCOperand::CreateImm(Val));
1622 }
1623
Jim Grosbach38466302011-08-19 18:55:51 +00001624 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1625 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001626 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1627 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001628 Inst.addOperand(MCOperand::CreateImm(Val));
1629 }
1630
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001631 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1632 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001633 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1634 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001635 Inst.addOperand(MCOperand::CreateImm(Val));
1636 }
1637
Jim Grosbachecd85892011-08-19 18:13:48 +00001638 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1639 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001640 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1641 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001642 Inst.addOperand(MCOperand::CreateImm(Val));
1643 }
1644
Jim Grosbach7ce05792011-08-03 23:50:40 +00001645 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1646 assert(N == 1 && "Invalid number of operands!");
1647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1648 assert(CE && "non-constant post-idx-imm8 operand!");
1649 int Imm = CE->getValue();
1650 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001651 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001652 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1653 Inst.addOperand(MCOperand::CreateImm(Imm));
1654 }
1655
Jim Grosbach2bd01182011-10-11 21:55:36 +00001656 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1657 assert(N == 1 && "Invalid number of operands!");
1658 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1659 assert(CE && "non-constant post-idx-imm8s4 operand!");
1660 int Imm = CE->getValue();
1661 bool isAdd = Imm >= 0;
1662 if (Imm == INT32_MIN) Imm = 0;
1663 // Immediate is scaled by 4.
1664 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1665 Inst.addOperand(MCOperand::CreateImm(Imm));
1666 }
1667
Jim Grosbach7ce05792011-08-03 23:50:40 +00001668 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1669 assert(N == 2 && "Invalid number of operands!");
1670 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001671 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1672 }
1673
1674 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1675 assert(N == 2 && "Invalid number of operands!");
1676 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1677 // The sign, shift type, and shift amount are encoded in a single operand
1678 // using the AM2 encoding helpers.
1679 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1680 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1681 PostIdxReg.ShiftTy);
1682 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001683 }
1684
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001685 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1686 assert(N == 1 && "Invalid number of operands!");
1687 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1688 }
1689
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001690 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1691 assert(N == 1 && "Invalid number of operands!");
1692 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1693 }
1694
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001695 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001696 assert(N == 1 && "Invalid number of operands!");
1697 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1698 }
1699
Jim Grosbach7636bf62011-12-02 00:35:16 +00001700 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1701 assert(N == 2 && "Invalid number of operands!");
1702 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1703 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1704 }
1705
Jim Grosbach460a9052011-10-07 23:56:00 +00001706 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1707 assert(N == 1 && "Invalid number of operands!");
1708 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1709 }
1710
1711 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1712 assert(N == 1 && "Invalid number of operands!");
1713 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1714 }
1715
1716 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1717 assert(N == 1 && "Invalid number of operands!");
1718 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1719 }
1720
Jim Grosbach0e387b22011-10-17 22:26:03 +00001721 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1722 assert(N == 1 && "Invalid number of operands!");
1723 // The immediate encodes the type of constant as well as the value.
1724 // Mask in that this is an i8 splat.
1725 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1726 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1727 }
1728
Jim Grosbachea461102011-10-17 23:09:09 +00001729 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1730 assert(N == 1 && "Invalid number of operands!");
1731 // The immediate encodes the type of constant as well as the value.
1732 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1733 unsigned Value = CE->getValue();
1734 if (Value >= 256)
1735 Value = (Value >> 8) | 0xa00;
1736 else
1737 Value |= 0x800;
1738 Inst.addOperand(MCOperand::CreateImm(Value));
1739 }
1740
Jim Grosbach6248a542011-10-18 00:22:00 +00001741 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1742 assert(N == 1 && "Invalid number of operands!");
1743 // The immediate encodes the type of constant as well as the value.
1744 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1745 unsigned Value = CE->getValue();
1746 if (Value >= 256 && Value <= 0xff00)
1747 Value = (Value >> 8) | 0x200;
1748 else if (Value > 0xffff && Value <= 0xff0000)
1749 Value = (Value >> 16) | 0x400;
1750 else if (Value > 0xffffff)
1751 Value = (Value >> 24) | 0x600;
1752 Inst.addOperand(MCOperand::CreateImm(Value));
1753 }
1754
1755 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
1756 assert(N == 1 && "Invalid number of operands!");
1757 // The immediate encodes the type of constant as well as the value.
1758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1759 unsigned Value = CE->getValue();
1760 if (Value >= 256 && Value <= 0xffff)
1761 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
1762 else if (Value > 0xffff && Value <= 0xffffff)
1763 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
1764 else if (Value > 0xffffff)
1765 Value = (Value >> 24) | 0x600;
1766 Inst.addOperand(MCOperand::CreateImm(Value));
1767 }
1768
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001769 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
1770 assert(N == 1 && "Invalid number of operands!");
1771 // The immediate encodes the type of constant as well as the value.
1772 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1773 uint64_t Value = CE->getValue();
1774 unsigned Imm = 0;
1775 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
1776 Imm |= (Value & 1) << i;
1777 }
1778 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
1779 }
1780
Jim Grosbachb7f689b2011-07-13 15:34:57 +00001781 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00001782
Jim Grosbach89df9962011-08-26 21:43:41 +00001783 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001784 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00001785 Op->ITMask.Mask = Mask;
1786 Op->StartLoc = S;
1787 Op->EndLoc = S;
1788 return Op;
1789 }
1790
Chris Lattner3a697562010-10-28 17:20:03 +00001791 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001792 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001793 Op->CC.Val = CC;
1794 Op->StartLoc = S;
1795 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001796 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001797 }
1798
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001799 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001800 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001801 Op->Cop.Val = CopVal;
1802 Op->StartLoc = S;
1803 Op->EndLoc = S;
1804 return Op;
1805 }
1806
1807 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001808 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001809 Op->Cop.Val = CopVal;
1810 Op->StartLoc = S;
1811 Op->EndLoc = S;
1812 return Op;
1813 }
1814
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001815 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
1816 ARMOperand *Op = new ARMOperand(k_CoprocOption);
1817 Op->Cop.Val = Val;
1818 Op->StartLoc = S;
1819 Op->EndLoc = E;
1820 return Op;
1821 }
1822
Jim Grosbachd67641b2010-12-06 18:21:12 +00001823 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001824 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00001825 Op->Reg.RegNum = RegNum;
1826 Op->StartLoc = S;
1827 Op->EndLoc = S;
1828 return Op;
1829 }
1830
Chris Lattner3a697562010-10-28 17:20:03 +00001831 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001832 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00001833 Op->Tok.Data = Str.data();
1834 Op->Tok.Length = Str.size();
1835 Op->StartLoc = S;
1836 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00001837 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001838 }
1839
Bill Wendling50d0f582010-11-18 23:43:05 +00001840 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001841 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00001842 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00001843 Op->StartLoc = S;
1844 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001845 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001846 }
1847
Jim Grosbache8606dc2011-07-13 17:50:29 +00001848 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
1849 unsigned SrcReg,
1850 unsigned ShiftReg,
1851 unsigned ShiftImm,
1852 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001853 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001854 Op->RegShiftedReg.ShiftTy = ShTy;
1855 Op->RegShiftedReg.SrcReg = SrcReg;
1856 Op->RegShiftedReg.ShiftReg = ShiftReg;
1857 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00001858 Op->StartLoc = S;
1859 Op->EndLoc = E;
1860 return Op;
1861 }
1862
Owen Anderson92a20222011-07-21 18:54:16 +00001863 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
1864 unsigned SrcReg,
1865 unsigned ShiftImm,
1866 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001867 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001868 Op->RegShiftedImm.ShiftTy = ShTy;
1869 Op->RegShiftedImm.SrcReg = SrcReg;
1870 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00001871 Op->StartLoc = S;
1872 Op->EndLoc = E;
1873 return Op;
1874 }
1875
Jim Grosbach580f4a92011-07-25 22:20:28 +00001876 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00001877 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001878 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00001879 Op->ShifterImm.isASR = isASR;
1880 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00001881 Op->StartLoc = S;
1882 Op->EndLoc = E;
1883 return Op;
1884 }
1885
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001886 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001887 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001888 Op->RotImm.Imm = Imm;
1889 Op->StartLoc = S;
1890 Op->EndLoc = E;
1891 return Op;
1892 }
1893
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001894 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
1895 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001896 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001897 Op->Bitfield.LSB = LSB;
1898 Op->Bitfield.Width = Width;
1899 Op->StartLoc = S;
1900 Op->EndLoc = E;
1901 return Op;
1902 }
1903
Bill Wendling7729e062010-11-09 22:44:22 +00001904 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00001905 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001906 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001907 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001908
Jim Grosbachd300b942011-09-13 22:56:44 +00001909 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001910 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00001911 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00001912 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001913 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00001914
1915 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00001916 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001917 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00001918 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00001919 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00001920 Op->StartLoc = StartLoc;
1921 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00001922 return Op;
1923 }
1924
Jim Grosbach862019c2011-10-18 23:02:30 +00001925 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
1926 SMLoc S, SMLoc E) {
1927 ARMOperand *Op = new ARMOperand(k_VectorList);
1928 Op->VectorList.RegNum = RegNum;
1929 Op->VectorList.Count = Count;
1930 Op->StartLoc = S;
1931 Op->EndLoc = E;
1932 return Op;
1933 }
1934
Jim Grosbach98b05a52011-11-30 01:09:44 +00001935 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
1936 SMLoc S, SMLoc E) {
1937 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
1938 Op->VectorList.RegNum = RegNum;
1939 Op->VectorList.Count = Count;
1940 Op->StartLoc = S;
1941 Op->EndLoc = E;
1942 return Op;
1943 }
1944
Jim Grosbach7636bf62011-12-02 00:35:16 +00001945 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
1946 unsigned Index, SMLoc S, SMLoc E) {
1947 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
1948 Op->VectorList.RegNum = RegNum;
1949 Op->VectorList.Count = Count;
1950 Op->VectorList.LaneIndex = Index;
1951 Op->StartLoc = S;
1952 Op->EndLoc = E;
1953 return Op;
1954 }
1955
Jim Grosbach460a9052011-10-07 23:56:00 +00001956 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
1957 MCContext &Ctx) {
1958 ARMOperand *Op = new ARMOperand(k_VectorIndex);
1959 Op->VectorIndex.Val = Idx;
1960 Op->StartLoc = S;
1961 Op->EndLoc = E;
1962 return Op;
1963 }
1964
Chris Lattner3a697562010-10-28 17:20:03 +00001965 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001966 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00001967 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00001968 Op->StartLoc = S;
1969 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00001970 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00001971 }
1972
Jim Grosbach9d390362011-10-03 23:38:36 +00001973 static ARMOperand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001974 ARMOperand *Op = new ARMOperand(k_FPImmediate);
Jim Grosbach9d390362011-10-03 23:38:36 +00001975 Op->FPImm.Val = Val;
1976 Op->StartLoc = S;
1977 Op->EndLoc = S;
1978 return Op;
1979 }
1980
Jim Grosbach7ce05792011-08-03 23:50:40 +00001981 static ARMOperand *CreateMem(unsigned BaseRegNum,
1982 const MCConstantExpr *OffsetImm,
1983 unsigned OffsetRegNum,
1984 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00001985 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00001986 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00001987 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00001988 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001989 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001990 Op->Memory.BaseRegNum = BaseRegNum;
1991 Op->Memory.OffsetImm = OffsetImm;
1992 Op->Memory.OffsetRegNum = OffsetRegNum;
1993 Op->Memory.ShiftType = ShiftType;
1994 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001995 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001996 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001997 Op->StartLoc = S;
1998 Op->EndLoc = E;
1999 return Op;
2000 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002001
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002002 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2003 ARM_AM::ShiftOpc ShiftTy,
2004 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002005 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002006 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002007 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002008 Op->PostIdxReg.isAdd = isAdd;
2009 Op->PostIdxReg.ShiftTy = ShiftTy;
2010 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002011 Op->StartLoc = S;
2012 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002013 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002014 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002015
2016 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002017 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002018 Op->MBOpt.Val = Opt;
2019 Op->StartLoc = S;
2020 Op->EndLoc = S;
2021 return Op;
2022 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002023
2024 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002025 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002026 Op->IFlags.Val = IFlags;
2027 Op->StartLoc = S;
2028 Op->EndLoc = S;
2029 return Op;
2030 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002031
2032 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002033 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002034 Op->MMask.Val = MMask;
2035 Op->StartLoc = S;
2036 Op->EndLoc = S;
2037 return Op;
2038 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002039};
2040
2041} // end anonymous namespace.
2042
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002043void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002044 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 case k_FPImmediate:
Jim Grosbach9d390362011-10-03 23:38:36 +00002046 OS << "<fpimm " << getFPImm() << "(" << ARM_AM::getFPImmFloat(getFPImm())
2047 << ") >";
2048 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002049 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002050 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002051 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002052 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002053 OS << "<ccout " << getReg() << ">";
2054 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002055 case k_ITCondMask: {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002056 static const char *MaskStr[] = {
2057 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2058 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2059 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002060 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2061 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2062 break;
2063 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002064 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002065 OS << "<coprocessor number: " << getCoproc() << ">";
2066 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002067 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002068 OS << "<coprocessor register: " << getCoproc() << ">";
2069 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002070 case k_CoprocOption:
2071 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2072 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002073 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002074 OS << "<mask: " << getMSRMask() << ">";
2075 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002076 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002077 getImm()->print(OS);
2078 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002079 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002080 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2081 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002082 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002083 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002084 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002085 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002086 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002087 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002088 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2089 << PostIdxReg.RegNum;
2090 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2091 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2092 << PostIdxReg.ShiftImm;
2093 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002094 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002095 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002096 OS << "<ARM_PROC::";
2097 unsigned IFlags = getProcIFlags();
2098 for (int i=2; i >= 0; --i)
2099 if (IFlags & (1 << i))
2100 OS << ARM_PROC::IFlagsToString(1 << i);
2101 OS << ">";
2102 break;
2103 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002104 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002105 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002106 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002107 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002108 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2109 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002110 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002111 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002112 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002113 << RegShiftedReg.SrcReg << " "
2114 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2115 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002116 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002117 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002118 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002119 << RegShiftedImm.SrcReg << " "
2120 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2121 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002122 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002123 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002124 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2125 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002126 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002127 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2128 << ", width: " << Bitfield.Width << ">";
2129 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002130 case k_RegisterList:
2131 case k_DPRRegisterList:
2132 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002133 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002134
Bill Wendling5fa22a12010-11-09 23:28:44 +00002135 const SmallVectorImpl<unsigned> &RegList = getRegList();
2136 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002137 I = RegList.begin(), E = RegList.end(); I != E; ) {
2138 OS << *I;
2139 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002140 }
2141
2142 OS << ">";
2143 break;
2144 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002145 case k_VectorList:
2146 OS << "<vector_list " << VectorList.Count << " * "
2147 << VectorList.RegNum << ">";
2148 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002149 case k_VectorListAllLanes:
2150 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2151 << VectorList.RegNum << ">";
2152 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002153 case k_VectorListIndexed:
2154 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2155 << VectorList.Count << " * " << VectorList.RegNum << ">";
2156 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002157 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002158 OS << "'" << getToken() << "'";
2159 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002160 case k_VectorIndex:
2161 OS << "<vectorindex " << getVectorIndex() << ">";
2162 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002163 }
2164}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002165
2166/// @name Auto-generated Match Functions
2167/// {
2168
2169static unsigned MatchRegisterName(StringRef Name);
2170
2171/// }
2172
Bob Wilson69df7232011-02-03 21:46:10 +00002173bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2174 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002175 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002176 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002177 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002178
2179 return (RegNo == (unsigned)-1);
2180}
2181
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002182/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002183/// and if it is a register name the token is eaten and the register number is
2184/// returned. Otherwise return -1.
2185///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002186int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002187 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002188 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002189
Benjamin Kramer59085362011-11-06 20:37:06 +00002190 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002191 unsigned RegNum = MatchRegisterName(lowerCase);
2192 if (!RegNum) {
2193 RegNum = StringSwitch<unsigned>(lowerCase)
2194 .Case("r13", ARM::SP)
2195 .Case("r14", ARM::LR)
2196 .Case("r15", ARM::PC)
2197 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002198 // Additional register name aliases for 'gas' compatibility.
2199 .Case("a1", ARM::R0)
2200 .Case("a2", ARM::R1)
2201 .Case("a3", ARM::R2)
2202 .Case("a4", ARM::R3)
2203 .Case("v1", ARM::R4)
2204 .Case("v2", ARM::R5)
2205 .Case("v3", ARM::R6)
2206 .Case("v4", ARM::R7)
2207 .Case("v5", ARM::R8)
2208 .Case("v6", ARM::R9)
2209 .Case("v7", ARM::R10)
2210 .Case("v8", ARM::R11)
2211 .Case("sb", ARM::R9)
2212 .Case("sl", ARM::R10)
2213 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002214 .Default(0);
2215 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002216 if (!RegNum) {
2217 // Check for aliases registered via .req.
2218 StringMap<unsigned>::const_iterator Entry =
2219 RegisterReqs.find(Tok.getIdentifier());
2220 // If no match, return failure.
2221 if (Entry == RegisterReqs.end())
2222 return -1;
2223 Parser.Lex(); // Eat identifier token.
2224 return Entry->getValue();
2225 }
Bob Wilson69df7232011-02-03 21:46:10 +00002226
Chris Lattnere5658fa2010-10-30 04:09:10 +00002227 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002228
Chris Lattnere5658fa2010-10-30 04:09:10 +00002229 return RegNum;
2230}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002231
Jim Grosbach19906722011-07-13 18:49:30 +00002232// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2233// If a recoverable error occurs, return 1. If an irrecoverable error
2234// occurs, return -1. An irrecoverable error is one where tokens have been
2235// consumed in the process of trying to parse the shifter (i.e., when it is
2236// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002237int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002238 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2239 SMLoc S = Parser.getTok().getLoc();
2240 const AsmToken &Tok = Parser.getTok();
2241 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2242
Benjamin Kramer59085362011-11-06 20:37:06 +00002243 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002244 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002245 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002246 .Case("lsl", ARM_AM::lsl)
2247 .Case("lsr", ARM_AM::lsr)
2248 .Case("asr", ARM_AM::asr)
2249 .Case("ror", ARM_AM::ror)
2250 .Case("rrx", ARM_AM::rrx)
2251 .Default(ARM_AM::no_shift);
2252
2253 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002254 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002255
Jim Grosbache8606dc2011-07-13 17:50:29 +00002256 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002257
Jim Grosbache8606dc2011-07-13 17:50:29 +00002258 // The source register for the shift has already been added to the
2259 // operand list, so we need to pop it off and combine it into the shifted
2260 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002261 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002262 if (!PrevOp->isReg())
2263 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2264 int SrcReg = PrevOp->getReg();
2265 int64_t Imm = 0;
2266 int ShiftReg = 0;
2267 if (ShiftTy == ARM_AM::rrx) {
2268 // RRX Doesn't have an explicit shift amount. The encoder expects
2269 // the shift register to be the same as the source register. Seems odd,
2270 // but OK.
2271 ShiftReg = SrcReg;
2272 } else {
2273 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002274 if (Parser.getTok().is(AsmToken::Hash) ||
2275 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002276 Parser.Lex(); // Eat hash.
2277 SMLoc ImmLoc = Parser.getTok().getLoc();
2278 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002279 if (getParser().ParseExpression(ShiftExpr)) {
2280 Error(ImmLoc, "invalid immediate shift value");
2281 return -1;
2282 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002283 // The expression must be evaluatable as an immediate.
2284 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002285 if (!CE) {
2286 Error(ImmLoc, "invalid immediate shift value");
2287 return -1;
2288 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002289 // Range check the immediate.
2290 // lsl, ror: 0 <= imm <= 31
2291 // lsr, asr: 0 <= imm <= 32
2292 Imm = CE->getValue();
2293 if (Imm < 0 ||
2294 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2295 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002296 Error(ImmLoc, "immediate shift value out of range");
2297 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002298 }
2299 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002300 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002301 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002302 if (ShiftReg == -1) {
2303 Error (L, "expected immediate or register in shift operand");
2304 return -1;
2305 }
2306 } else {
2307 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002308 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002309 return -1;
2310 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002311 }
2312
Owen Anderson92a20222011-07-21 18:54:16 +00002313 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2314 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002315 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002316 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002317 else
2318 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2319 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002320
Jim Grosbach19906722011-07-13 18:49:30 +00002321 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002322}
2323
2324
Bill Wendling50d0f582010-11-18 23:43:05 +00002325/// Try to parse a register name. The token must be an Identifier when called.
2326/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2327/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002328///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002329/// TODO this is likely to change to allow different register types and or to
2330/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002331bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002332tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002333 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002334 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002335 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002336 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002337
Bill Wendling50d0f582010-11-18 23:43:05 +00002338 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002339
Chris Lattnere5658fa2010-10-30 04:09:10 +00002340 const AsmToken &ExclaimTok = Parser.getTok();
2341 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002342 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2343 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002344 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002345 return false;
2346 }
2347
2348 // Also check for an index operand. This is only legal for vector registers,
2349 // but that'll get caught OK in operand matching, so we don't need to
2350 // explicitly filter everything else out here.
2351 if (Parser.getTok().is(AsmToken::LBrac)) {
2352 SMLoc SIdx = Parser.getTok().getLoc();
2353 Parser.Lex(); // Eat left bracket token.
2354
2355 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002356 if (getParser().ParseExpression(ImmVal))
2357 return MatchOperand_ParseFail;
2358 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2359 if (!MCE) {
2360 TokError("immediate value expected for vector index");
2361 return MatchOperand_ParseFail;
2362 }
2363
2364 SMLoc E = Parser.getTok().getLoc();
2365 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2366 Error(E, "']' expected");
2367 return MatchOperand_ParseFail;
2368 }
2369
2370 Parser.Lex(); // Eat right bracket token.
2371
2372 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2373 SIdx, E,
2374 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002375 }
2376
Bill Wendling50d0f582010-11-18 23:43:05 +00002377 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002378}
2379
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002380/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2381/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2382/// "c5", ...
2383static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002384 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2385 // but efficient.
2386 switch (Name.size()) {
2387 default: break;
2388 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002389 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002390 return -1;
2391 switch (Name[1]) {
2392 default: return -1;
2393 case '0': return 0;
2394 case '1': return 1;
2395 case '2': return 2;
2396 case '3': return 3;
2397 case '4': return 4;
2398 case '5': return 5;
2399 case '6': return 6;
2400 case '7': return 7;
2401 case '8': return 8;
2402 case '9': return 9;
2403 }
2404 break;
2405 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002406 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002407 return -1;
2408 switch (Name[2]) {
2409 default: return -1;
2410 case '0': return 10;
2411 case '1': return 11;
2412 case '2': return 12;
2413 case '3': return 13;
2414 case '4': return 14;
2415 case '5': return 15;
2416 }
2417 break;
2418 }
2419
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002420 return -1;
2421}
2422
Jim Grosbach89df9962011-08-26 21:43:41 +00002423/// parseITCondCode - Try to parse a condition code for an IT instruction.
2424ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2425parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2426 SMLoc S = Parser.getTok().getLoc();
2427 const AsmToken &Tok = Parser.getTok();
2428 if (!Tok.is(AsmToken::Identifier))
2429 return MatchOperand_NoMatch;
2430 unsigned CC = StringSwitch<unsigned>(Tok.getString())
2431 .Case("eq", ARMCC::EQ)
2432 .Case("ne", ARMCC::NE)
2433 .Case("hs", ARMCC::HS)
2434 .Case("cs", ARMCC::HS)
2435 .Case("lo", ARMCC::LO)
2436 .Case("cc", ARMCC::LO)
2437 .Case("mi", ARMCC::MI)
2438 .Case("pl", ARMCC::PL)
2439 .Case("vs", ARMCC::VS)
2440 .Case("vc", ARMCC::VC)
2441 .Case("hi", ARMCC::HI)
2442 .Case("ls", ARMCC::LS)
2443 .Case("ge", ARMCC::GE)
2444 .Case("lt", ARMCC::LT)
2445 .Case("gt", ARMCC::GT)
2446 .Case("le", ARMCC::LE)
2447 .Case("al", ARMCC::AL)
2448 .Default(~0U);
2449 if (CC == ~0U)
2450 return MatchOperand_NoMatch;
2451 Parser.Lex(); // Eat the token.
2452
2453 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2454
2455 return MatchOperand_Success;
2456}
2457
Jim Grosbach43904292011-07-25 20:14:50 +00002458/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002459/// token must be an Identifier when called, and if it is a coprocessor
2460/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002461ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002462parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002463 SMLoc S = Parser.getTok().getLoc();
2464 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002465 if (Tok.isNot(AsmToken::Identifier))
2466 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002467
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002468 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002469 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002470 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002471
2472 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002473 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002474 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002475}
2476
Jim Grosbach43904292011-07-25 20:14:50 +00002477/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002478/// token must be an Identifier when called, and if it is a coprocessor
2479/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002480ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002481parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002482 SMLoc S = Parser.getTok().getLoc();
2483 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002484 if (Tok.isNot(AsmToken::Identifier))
2485 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002486
2487 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2488 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002489 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002490
2491 Parser.Lex(); // Eat identifier token.
2492 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002493 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002494}
2495
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002496/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2497/// coproc_option : '{' imm0_255 '}'
2498ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2499parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2500 SMLoc S = Parser.getTok().getLoc();
2501
2502 // If this isn't a '{', this isn't a coprocessor immediate operand.
2503 if (Parser.getTok().isNot(AsmToken::LCurly))
2504 return MatchOperand_NoMatch;
2505 Parser.Lex(); // Eat the '{'
2506
2507 const MCExpr *Expr;
2508 SMLoc Loc = Parser.getTok().getLoc();
2509 if (getParser().ParseExpression(Expr)) {
2510 Error(Loc, "illegal expression");
2511 return MatchOperand_ParseFail;
2512 }
2513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2514 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2515 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2516 return MatchOperand_ParseFail;
2517 }
2518 int Val = CE->getValue();
2519
2520 // Check for and consume the closing '}'
2521 if (Parser.getTok().isNot(AsmToken::RCurly))
2522 return MatchOperand_ParseFail;
2523 SMLoc E = Parser.getTok().getLoc();
2524 Parser.Lex(); // Eat the '}'
2525
2526 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2527 return MatchOperand_Success;
2528}
2529
Jim Grosbachd0588e22011-09-14 18:08:35 +00002530// For register list parsing, we need to map from raw GPR register numbering
2531// to the enumeration values. The enumeration values aren't sorted by
2532// register number due to our using "sp", "lr" and "pc" as canonical names.
2533static unsigned getNextRegister(unsigned Reg) {
2534 // If this is a GPR, we need to do it manually, otherwise we can rely
2535 // on the sort ordering of the enumeration since the other reg-classes
2536 // are sane.
2537 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2538 return Reg + 1;
2539 switch(Reg) {
2540 default: assert(0 && "Invalid GPR number!");
2541 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2542 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2543 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2544 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2545 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2546 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2547 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2548 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2549 }
2550}
2551
Jim Grosbachce485e72011-11-11 21:27:40 +00002552// Return the low-subreg of a given Q register.
2553static unsigned getDRegFromQReg(unsigned QReg) {
2554 switch (QReg) {
2555 default: llvm_unreachable("expected a Q register!");
2556 case ARM::Q0: return ARM::D0;
2557 case ARM::Q1: return ARM::D2;
2558 case ARM::Q2: return ARM::D4;
2559 case ARM::Q3: return ARM::D6;
2560 case ARM::Q4: return ARM::D8;
2561 case ARM::Q5: return ARM::D10;
2562 case ARM::Q6: return ARM::D12;
2563 case ARM::Q7: return ARM::D14;
2564 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002565 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002566 case ARM::Q10: return ARM::D20;
2567 case ARM::Q11: return ARM::D22;
2568 case ARM::Q12: return ARM::D24;
2569 case ARM::Q13: return ARM::D26;
2570 case ARM::Q14: return ARM::D28;
2571 case ARM::Q15: return ARM::D30;
2572 }
2573}
2574
Jim Grosbachd0588e22011-09-14 18:08:35 +00002575/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002576bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002577parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002578 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002579 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002580 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002581 Parser.Lex(); // Eat '{' token.
2582 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002583
Jim Grosbachd0588e22011-09-14 18:08:35 +00002584 // Check the first register in the list to see what register class
2585 // this is a list of.
2586 int Reg = tryParseRegister();
2587 if (Reg == -1)
2588 return Error(RegLoc, "register expected");
2589
Jim Grosbachce485e72011-11-11 21:27:40 +00002590 // The reglist instructions have at most 16 registers, so reserve
2591 // space for that many.
2592 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2593
2594 // Allow Q regs and just interpret them as the two D sub-registers.
2595 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2596 Reg = getDRegFromQReg(Reg);
2597 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2598 ++Reg;
2599 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002600 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002601 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2602 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2603 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2604 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2605 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2606 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2607 else
2608 return Error(RegLoc, "invalid register in register list");
2609
Jim Grosbachce485e72011-11-11 21:27:40 +00002610 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002611 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002612
Jim Grosbachd0588e22011-09-14 18:08:35 +00002613 // This starts immediately after the first register token in the list,
2614 // so we can see either a comma or a minus (range separator) as a legal
2615 // next token.
2616 while (Parser.getTok().is(AsmToken::Comma) ||
2617 Parser.getTok().is(AsmToken::Minus)) {
2618 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002619 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002620 SMLoc EndLoc = Parser.getTok().getLoc();
2621 int EndReg = tryParseRegister();
2622 if (EndReg == -1)
2623 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002624 // Allow Q regs and just interpret them as the two D sub-registers.
2625 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2626 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002627 // If the register is the same as the start reg, there's nothing
2628 // more to do.
2629 if (Reg == EndReg)
2630 continue;
2631 // The register must be in the same register class as the first.
2632 if (!RC->contains(EndReg))
2633 return Error(EndLoc, "invalid register in register list");
2634 // Ranges must go from low to high.
2635 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2636 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002637
Jim Grosbachd0588e22011-09-14 18:08:35 +00002638 // Add all the registers in the range to the register list.
2639 while (Reg != EndReg) {
2640 Reg = getNextRegister(Reg);
2641 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2642 }
2643 continue;
2644 }
2645 Parser.Lex(); // Eat the comma.
2646 RegLoc = Parser.getTok().getLoc();
2647 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002648 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002649 Reg = tryParseRegister();
2650 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002651 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002652 // Allow Q regs and just interpret them as the two D sub-registers.
2653 bool isQReg = false;
2654 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2655 Reg = getDRegFromQReg(Reg);
2656 isQReg = true;
2657 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002658 // The register must be in the same register class as the first.
2659 if (!RC->contains(Reg))
2660 return Error(RegLoc, "invalid register in register list");
2661 // List must be monotonically increasing.
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002662 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg))
Jim Grosbachd0588e22011-09-14 18:08:35 +00002663 return Error(RegLoc, "register list not in ascending order");
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002664 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2665 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2666 ") in register list");
2667 continue;
2668 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002669 // VFP register lists must also be contiguous.
2670 // It's OK to use the enumeration values directly here rather, as the
2671 // VFP register classes have the enum sorted properly.
2672 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2673 Reg != OldReg + 1)
2674 return Error(RegLoc, "non-contiguous register range");
2675 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002676 if (isQReg)
2677 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002678 }
2679
Jim Grosbachd0588e22011-09-14 18:08:35 +00002680 SMLoc E = Parser.getTok().getLoc();
2681 if (Parser.getTok().isNot(AsmToken::RCurly))
2682 return Error(E, "'}' expected");
2683 Parser.Lex(); // Eat '}' token.
2684
Jim Grosbach27debd62011-12-13 21:48:29 +00002685 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002686 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002687
2688 // The ARM system instruction variants for LDM/STM have a '^' token here.
2689 if (Parser.getTok().is(AsmToken::Caret)) {
2690 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2691 Parser.Lex(); // Eat '^' token.
2692 }
2693
Bill Wendling50d0f582010-11-18 23:43:05 +00002694 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002695}
2696
Jim Grosbach98b05a52011-11-30 01:09:44 +00002697// Helper function to parse the lane index for vector lists.
2698ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002699parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2700 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002701 if (Parser.getTok().is(AsmToken::LBrac)) {
2702 Parser.Lex(); // Eat the '['.
2703 if (Parser.getTok().is(AsmToken::RBrac)) {
2704 // "Dn[]" is the 'all lanes' syntax.
2705 LaneKind = AllLanes;
2706 Parser.Lex(); // Eat the ']'.
2707 return MatchOperand_Success;
2708 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002709 if (Parser.getTok().is(AsmToken::Integer)) {
2710 int64_t Val = Parser.getTok().getIntVal();
2711 // Make this range check context sensitive for .8, .16, .32.
2712 if (Val < 0 && Val > 7)
2713 Error(Parser.getTok().getLoc(), "lane index out of range");
2714 Index = Val;
2715 LaneKind = IndexedLane;
2716 Parser.Lex(); // Eat the token;
2717 if (Parser.getTok().isNot(AsmToken::RBrac))
2718 Error(Parser.getTok().getLoc(), "']' expected");
2719 Parser.Lex(); // Eat the ']'.
2720 return MatchOperand_Success;
2721 }
2722 Error(Parser.getTok().getLoc(), "lane index must be empty or an integer");
Jim Grosbach98b05a52011-11-30 01:09:44 +00002723 return MatchOperand_ParseFail;
2724 }
2725 LaneKind = NoLanes;
2726 return MatchOperand_Success;
2727}
2728
Jim Grosbach862019c2011-10-18 23:02:30 +00002729// parse a vector register list
2730ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2731parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002732 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002733 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00002734 SMLoc S = Parser.getTok().getLoc();
2735 // As an extension (to match gas), support a plain D register or Q register
2736 // (without encosing curly braces) as a single or double entry list,
2737 // respectively.
2738 if (Parser.getTok().is(AsmToken::Identifier)) {
2739 int Reg = tryParseRegister();
2740 if (Reg == -1)
2741 return MatchOperand_NoMatch;
2742 SMLoc E = Parser.getTok().getLoc();
2743 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002744 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002745 if (Res != MatchOperand_Success)
2746 return Res;
2747 switch (LaneKind) {
2748 default:
2749 assert(0 && "unexpected lane kind!");
2750 case NoLanes:
2751 E = Parser.getTok().getLoc();
2752 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, S, E));
2753 break;
2754 case AllLanes:
2755 E = Parser.getTok().getLoc();
2756 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, S, E));
2757 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002758 case IndexedLane:
2759 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
2760 LaneIndex, S,E));
2761 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002762 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002763 return MatchOperand_Success;
2764 }
2765 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2766 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00002767 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00002768 if (Res != MatchOperand_Success)
2769 return Res;
2770 switch (LaneKind) {
2771 default:
2772 assert(0 && "unexpected lane kind!");
2773 case NoLanes:
2774 E = Parser.getTok().getLoc();
2775 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, S, E));
2776 break;
2777 case AllLanes:
2778 E = Parser.getTok().getLoc();
2779 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, S, E));
2780 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002781 case IndexedLane:
2782 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
2783 LaneIndex, S,E));
2784 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002785 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00002786 return MatchOperand_Success;
2787 }
2788 Error(S, "vector register expected");
2789 return MatchOperand_ParseFail;
2790 }
2791
2792 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00002793 return MatchOperand_NoMatch;
2794
Jim Grosbach862019c2011-10-18 23:02:30 +00002795 Parser.Lex(); // Eat '{' token.
2796 SMLoc RegLoc = Parser.getTok().getLoc();
2797
2798 int Reg = tryParseRegister();
2799 if (Reg == -1) {
2800 Error(RegLoc, "register expected");
2801 return MatchOperand_ParseFail;
2802 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002803 unsigned Count = 1;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002804 unsigned FirstReg = Reg;
2805 // The list is of D registers, but we also allow Q regs and just interpret
2806 // them as the two D sub-registers.
2807 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2808 FirstReg = Reg = getDRegFromQReg(Reg);
2809 ++Reg;
2810 ++Count;
2811 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00002812 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002813 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002814
Jim Grosbache43862b2011-11-15 23:19:15 +00002815 while (Parser.getTok().is(AsmToken::Comma) ||
2816 Parser.getTok().is(AsmToken::Minus)) {
2817 if (Parser.getTok().is(AsmToken::Minus)) {
2818 Parser.Lex(); // Eat the minus.
2819 SMLoc EndLoc = Parser.getTok().getLoc();
2820 int EndReg = tryParseRegister();
2821 if (EndReg == -1) {
2822 Error(EndLoc, "register expected");
2823 return MatchOperand_ParseFail;
2824 }
2825 // Allow Q regs and just interpret them as the two D sub-registers.
2826 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2827 EndReg = getDRegFromQReg(EndReg) + 1;
2828 // If the register is the same as the start reg, there's nothing
2829 // more to do.
2830 if (Reg == EndReg)
2831 continue;
2832 // The register must be in the same register class as the first.
2833 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
2834 Error(EndLoc, "invalid register in register list");
2835 return MatchOperand_ParseFail;
2836 }
2837 // Ranges must go from low to high.
2838 if (Reg > EndReg) {
2839 Error(EndLoc, "bad range in register list");
2840 return MatchOperand_ParseFail;
2841 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00002842 // Parse the lane specifier if present.
2843 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002844 unsigned NextLaneIndex;
2845 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002846 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002847 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002848 Error(EndLoc, "mismatched lane index in register list");
2849 return MatchOperand_ParseFail;
2850 }
2851 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00002852
2853 // Add all the registers in the range to the register list.
2854 Count += EndReg - Reg;
2855 Reg = EndReg;
2856 continue;
2857 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002858 Parser.Lex(); // Eat the comma.
2859 RegLoc = Parser.getTok().getLoc();
2860 int OldReg = Reg;
2861 Reg = tryParseRegister();
2862 if (Reg == -1) {
2863 Error(RegLoc, "register expected");
2864 return MatchOperand_ParseFail;
2865 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002866 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00002867 // It's OK to use the enumeration values directly here rather, as the
2868 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002869 //
2870 // The list is of D registers, but we also allow Q regs and just interpret
2871 // them as the two D sub-registers.
2872 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2873 Reg = getDRegFromQReg(Reg);
2874 if (Reg != OldReg + 1) {
2875 Error(RegLoc, "non-contiguous register range");
2876 return MatchOperand_ParseFail;
2877 }
2878 ++Reg;
2879 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002880 // Parse the lane specifier if present.
2881 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002882 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002883 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002884 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002885 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002886 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002887 Error(EndLoc, "mismatched lane index in register list");
2888 return MatchOperand_ParseFail;
2889 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00002890 continue;
2891 }
2892 // Normal D register. Just check that it's contiguous and keep going.
Jim Grosbach862019c2011-10-18 23:02:30 +00002893 if (Reg != OldReg + 1) {
2894 Error(RegLoc, "non-contiguous register range");
2895 return MatchOperand_ParseFail;
2896 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002897 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002898 // Parse the lane specifier if present.
2899 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002900 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002901 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00002902 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00002903 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002904 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00002905 Error(EndLoc, "mismatched lane index in register list");
2906 return MatchOperand_ParseFail;
2907 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002908 }
2909
2910 SMLoc E = Parser.getTok().getLoc();
2911 if (Parser.getTok().isNot(AsmToken::RCurly)) {
2912 Error(E, "'}' expected");
2913 return MatchOperand_ParseFail;
2914 }
2915 Parser.Lex(); // Eat '}' token.
2916
Jim Grosbach98b05a52011-11-30 01:09:44 +00002917 switch (LaneKind) {
2918 default:
2919 assert(0 && "unexpected lane kind in register list.");
2920 case NoLanes:
2921 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count, S, E));
2922 break;
2923 case AllLanes:
2924 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
2925 S, E));
2926 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002927 case IndexedLane:
2928 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
2929 LaneIndex, S, E));
2930 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002931 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002932 return MatchOperand_Success;
2933}
2934
Jim Grosbach43904292011-07-25 20:14:50 +00002935/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00002936ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002937parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002938 SMLoc S = Parser.getTok().getLoc();
2939 const AsmToken &Tok = Parser.getTok();
2940 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2941 StringRef OptStr = Tok.getString();
2942
2943 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
2944 .Case("sy", ARM_MB::SY)
2945 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002946 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002947 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002948 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002949 .Case("ishst", ARM_MB::ISHST)
2950 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00002951 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002952 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00002953 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002954 .Case("osh", ARM_MB::OSH)
2955 .Case("oshst", ARM_MB::OSHST)
2956 .Default(~0U);
2957
2958 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00002959 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002960
2961 Parser.Lex(); // Eat identifier token.
2962 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002963 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002964}
2965
Jim Grosbach43904292011-07-25 20:14:50 +00002966/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002967ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002968parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002969 SMLoc S = Parser.getTok().getLoc();
2970 const AsmToken &Tok = Parser.getTok();
2971 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2972 StringRef IFlagsStr = Tok.getString();
2973
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002974 // An iflags string of "none" is interpreted to mean that none of the AIF
2975 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002976 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002977 if (IFlagsStr != "none") {
2978 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
2979 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
2980 .Case("a", ARM_PROC::A)
2981 .Case("i", ARM_PROC::I)
2982 .Case("f", ARM_PROC::F)
2983 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002984
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002985 // If some specific iflag is already set, it means that some letter is
2986 // present more than once, this is not acceptable.
2987 if (Flag == ~0U || (IFlags & Flag))
2988 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002989
Owen Anderson2dbb46a2011-10-05 17:16:40 +00002990 IFlags |= Flag;
2991 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002992 }
2993
2994 Parser.Lex(); // Eat identifier token.
2995 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
2996 return MatchOperand_Success;
2997}
2998
Jim Grosbach43904292011-07-25 20:14:50 +00002999/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003000ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003001parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003002 SMLoc S = Parser.getTok().getLoc();
3003 const AsmToken &Tok = Parser.getTok();
3004 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3005 StringRef Mask = Tok.getString();
3006
James Molloyacad68d2011-09-28 14:21:38 +00003007 if (isMClass()) {
3008 // See ARMv6-M 10.1.1
3009 unsigned FlagsVal = StringSwitch<unsigned>(Mask)
3010 .Case("apsr", 0)
3011 .Case("iapsr", 1)
3012 .Case("eapsr", 2)
3013 .Case("xpsr", 3)
3014 .Case("ipsr", 5)
3015 .Case("epsr", 6)
3016 .Case("iepsr", 7)
3017 .Case("msp", 8)
3018 .Case("psp", 9)
3019 .Case("primask", 16)
3020 .Case("basepri", 17)
3021 .Case("basepri_max", 18)
3022 .Case("faultmask", 19)
3023 .Case("control", 20)
3024 .Default(~0U);
3025
3026 if (FlagsVal == ~0U)
3027 return MatchOperand_NoMatch;
3028
3029 if (!hasV7Ops() && FlagsVal >= 17 && FlagsVal <= 19)
3030 // basepri, basepri_max and faultmask only valid for V7m.
3031 return MatchOperand_NoMatch;
3032
3033 Parser.Lex(); // Eat identifier token.
3034 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3035 return MatchOperand_Success;
3036 }
3037
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003038 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3039 size_t Start = 0, Next = Mask.find('_');
3040 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003041 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003042 if (Next != StringRef::npos)
3043 Flags = Mask.slice(Next+1, Mask.size());
3044
3045 // FlagsVal contains the complete mask:
3046 // 3-0: Mask
3047 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3048 unsigned FlagsVal = 0;
3049
3050 if (SpecReg == "apsr") {
3051 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003052 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003053 .Case("g", 0x4) // same as CPSR_s
3054 .Case("nzcvqg", 0xc) // same as CPSR_fs
3055 .Default(~0U);
3056
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003057 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003058 if (!Flags.empty())
3059 return MatchOperand_NoMatch;
3060 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003061 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003062 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003063 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003064 if (Flags == "all") // cpsr_all is an alias for cpsr_fc
3065 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003066 for (int i = 0, e = Flags.size(); i != e; ++i) {
3067 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3068 .Case("c", 1)
3069 .Case("x", 2)
3070 .Case("s", 4)
3071 .Case("f", 8)
3072 .Default(~0U);
3073
3074 // If some specific flag is already set, it means that some letter is
3075 // present more than once, this is not acceptable.
3076 if (FlagsVal == ~0U || (FlagsVal & Flag))
3077 return MatchOperand_NoMatch;
3078 FlagsVal |= Flag;
3079 }
3080 } else // No match for special register.
3081 return MatchOperand_NoMatch;
3082
Owen Anderson7784f1d2011-10-21 18:43:28 +00003083 // Special register without flags is NOT equivalent to "fc" flags.
3084 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3085 // two lines would enable gas compatibility at the expense of breaking
3086 // round-tripping.
3087 //
3088 // if (!FlagsVal)
3089 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003090
3091 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3092 if (SpecReg == "spsr")
3093 FlagsVal |= 16;
3094
3095 Parser.Lex(); // Eat identifier token.
3096 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3097 return MatchOperand_Success;
3098}
3099
Jim Grosbachf6c05252011-07-21 17:23:04 +00003100ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3101parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3102 int Low, int High) {
3103 const AsmToken &Tok = Parser.getTok();
3104 if (Tok.isNot(AsmToken::Identifier)) {
3105 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3106 return MatchOperand_ParseFail;
3107 }
3108 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003109 std::string LowerOp = Op.lower();
3110 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003111 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3112 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3113 return MatchOperand_ParseFail;
3114 }
3115 Parser.Lex(); // Eat shift type token.
3116
3117 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003118 if (Parser.getTok().isNot(AsmToken::Hash) &&
3119 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003120 Error(Parser.getTok().getLoc(), "'#' expected");
3121 return MatchOperand_ParseFail;
3122 }
3123 Parser.Lex(); // Eat hash token.
3124
3125 const MCExpr *ShiftAmount;
3126 SMLoc Loc = Parser.getTok().getLoc();
3127 if (getParser().ParseExpression(ShiftAmount)) {
3128 Error(Loc, "illegal expression");
3129 return MatchOperand_ParseFail;
3130 }
3131 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3132 if (!CE) {
3133 Error(Loc, "constant expression expected");
3134 return MatchOperand_ParseFail;
3135 }
3136 int Val = CE->getValue();
3137 if (Val < Low || Val > High) {
3138 Error(Loc, "immediate value out of range");
3139 return MatchOperand_ParseFail;
3140 }
3141
3142 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3143
3144 return MatchOperand_Success;
3145}
3146
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003147ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3148parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3149 const AsmToken &Tok = Parser.getTok();
3150 SMLoc S = Tok.getLoc();
3151 if (Tok.isNot(AsmToken::Identifier)) {
3152 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3153 return MatchOperand_ParseFail;
3154 }
3155 int Val = StringSwitch<int>(Tok.getString())
3156 .Case("be", 1)
3157 .Case("le", 0)
3158 .Default(-1);
3159 Parser.Lex(); // Eat the token.
3160
3161 if (Val == -1) {
3162 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3163 return MatchOperand_ParseFail;
3164 }
3165 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3166 getContext()),
3167 S, Parser.getTok().getLoc()));
3168 return MatchOperand_Success;
3169}
3170
Jim Grosbach580f4a92011-07-25 22:20:28 +00003171/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3172/// instructions. Legal values are:
3173/// lsl #n 'n' in [0,31]
3174/// asr #n 'n' in [1,32]
3175/// n == 32 encoded as n == 0.
3176ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3177parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3178 const AsmToken &Tok = Parser.getTok();
3179 SMLoc S = Tok.getLoc();
3180 if (Tok.isNot(AsmToken::Identifier)) {
3181 Error(S, "shift operator 'asr' or 'lsl' expected");
3182 return MatchOperand_ParseFail;
3183 }
3184 StringRef ShiftName = Tok.getString();
3185 bool isASR;
3186 if (ShiftName == "lsl" || ShiftName == "LSL")
3187 isASR = false;
3188 else if (ShiftName == "asr" || ShiftName == "ASR")
3189 isASR = true;
3190 else {
3191 Error(S, "shift operator 'asr' or 'lsl' expected");
3192 return MatchOperand_ParseFail;
3193 }
3194 Parser.Lex(); // Eat the operator.
3195
3196 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003197 if (Parser.getTok().isNot(AsmToken::Hash) &&
3198 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003199 Error(Parser.getTok().getLoc(), "'#' expected");
3200 return MatchOperand_ParseFail;
3201 }
3202 Parser.Lex(); // Eat hash token.
3203
3204 const MCExpr *ShiftAmount;
3205 SMLoc E = Parser.getTok().getLoc();
3206 if (getParser().ParseExpression(ShiftAmount)) {
3207 Error(E, "malformed shift expression");
3208 return MatchOperand_ParseFail;
3209 }
3210 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3211 if (!CE) {
3212 Error(E, "shift amount must be an immediate");
3213 return MatchOperand_ParseFail;
3214 }
3215
3216 int64_t Val = CE->getValue();
3217 if (isASR) {
3218 // Shift amount must be in [1,32]
3219 if (Val < 1 || Val > 32) {
3220 Error(E, "'asr' shift amount must be in range [1,32]");
3221 return MatchOperand_ParseFail;
3222 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003223 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3224 if (isThumb() && Val == 32) {
3225 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3226 return MatchOperand_ParseFail;
3227 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003228 if (Val == 32) Val = 0;
3229 } else {
3230 // Shift amount must be in [1,32]
3231 if (Val < 0 || Val > 31) {
3232 Error(E, "'lsr' shift amount must be in range [0,31]");
3233 return MatchOperand_ParseFail;
3234 }
3235 }
3236
3237 E = Parser.getTok().getLoc();
3238 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3239
3240 return MatchOperand_Success;
3241}
3242
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003243/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3244/// of instructions. Legal values are:
3245/// ror #n 'n' in {0, 8, 16, 24}
3246ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3247parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3248 const AsmToken &Tok = Parser.getTok();
3249 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003250 if (Tok.isNot(AsmToken::Identifier))
3251 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003252 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003253 if (ShiftName != "ror" && ShiftName != "ROR")
3254 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003255 Parser.Lex(); // Eat the operator.
3256
3257 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003258 if (Parser.getTok().isNot(AsmToken::Hash) &&
3259 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003260 Error(Parser.getTok().getLoc(), "'#' expected");
3261 return MatchOperand_ParseFail;
3262 }
3263 Parser.Lex(); // Eat hash token.
3264
3265 const MCExpr *ShiftAmount;
3266 SMLoc E = Parser.getTok().getLoc();
3267 if (getParser().ParseExpression(ShiftAmount)) {
3268 Error(E, "malformed rotate expression");
3269 return MatchOperand_ParseFail;
3270 }
3271 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3272 if (!CE) {
3273 Error(E, "rotate amount must be an immediate");
3274 return MatchOperand_ParseFail;
3275 }
3276
3277 int64_t Val = CE->getValue();
3278 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3279 // normally, zero is represented in asm by omitting the rotate operand
3280 // entirely.
3281 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3282 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3283 return MatchOperand_ParseFail;
3284 }
3285
3286 E = Parser.getTok().getLoc();
3287 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3288
3289 return MatchOperand_Success;
3290}
3291
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003292ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3293parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3294 SMLoc S = Parser.getTok().getLoc();
3295 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003296 if (Parser.getTok().isNot(AsmToken::Hash) &&
3297 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003298 Error(Parser.getTok().getLoc(), "'#' expected");
3299 return MatchOperand_ParseFail;
3300 }
3301 Parser.Lex(); // Eat hash token.
3302
3303 const MCExpr *LSBExpr;
3304 SMLoc E = Parser.getTok().getLoc();
3305 if (getParser().ParseExpression(LSBExpr)) {
3306 Error(E, "malformed immediate expression");
3307 return MatchOperand_ParseFail;
3308 }
3309 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3310 if (!CE) {
3311 Error(E, "'lsb' operand must be an immediate");
3312 return MatchOperand_ParseFail;
3313 }
3314
3315 int64_t LSB = CE->getValue();
3316 // The LSB must be in the range [0,31]
3317 if (LSB < 0 || LSB > 31) {
3318 Error(E, "'lsb' operand must be in the range [0,31]");
3319 return MatchOperand_ParseFail;
3320 }
3321 E = Parser.getTok().getLoc();
3322
3323 // Expect another immediate operand.
3324 if (Parser.getTok().isNot(AsmToken::Comma)) {
3325 Error(Parser.getTok().getLoc(), "too few operands");
3326 return MatchOperand_ParseFail;
3327 }
3328 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003329 if (Parser.getTok().isNot(AsmToken::Hash) &&
3330 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003331 Error(Parser.getTok().getLoc(), "'#' expected");
3332 return MatchOperand_ParseFail;
3333 }
3334 Parser.Lex(); // Eat hash token.
3335
3336 const MCExpr *WidthExpr;
3337 if (getParser().ParseExpression(WidthExpr)) {
3338 Error(E, "malformed immediate expression");
3339 return MatchOperand_ParseFail;
3340 }
3341 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3342 if (!CE) {
3343 Error(E, "'width' operand must be an immediate");
3344 return MatchOperand_ParseFail;
3345 }
3346
3347 int64_t Width = CE->getValue();
3348 // The LSB must be in the range [1,32-lsb]
3349 if (Width < 1 || Width > 32 - LSB) {
3350 Error(E, "'width' operand must be in the range [1,32-lsb]");
3351 return MatchOperand_ParseFail;
3352 }
3353 E = Parser.getTok().getLoc();
3354
3355 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3356
3357 return MatchOperand_Success;
3358}
3359
Jim Grosbach7ce05792011-08-03 23:50:40 +00003360ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3361parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3362 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003363 // postidx_reg := '+' register {, shift}
3364 // | '-' register {, shift}
3365 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003366
3367 // This method must return MatchOperand_NoMatch without consuming any tokens
3368 // in the case where there is no match, as other alternatives take other
3369 // parse methods.
3370 AsmToken Tok = Parser.getTok();
3371 SMLoc S = Tok.getLoc();
3372 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003373 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003374 int Reg = -1;
3375 if (Tok.is(AsmToken::Plus)) {
3376 Parser.Lex(); // Eat the '+' token.
3377 haveEaten = true;
3378 } else if (Tok.is(AsmToken::Minus)) {
3379 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003380 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003381 haveEaten = true;
3382 }
3383 if (Parser.getTok().is(AsmToken::Identifier))
3384 Reg = tryParseRegister();
3385 if (Reg == -1) {
3386 if (!haveEaten)
3387 return MatchOperand_NoMatch;
3388 Error(Parser.getTok().getLoc(), "register expected");
3389 return MatchOperand_ParseFail;
3390 }
3391 SMLoc E = Parser.getTok().getLoc();
3392
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003393 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3394 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003395 if (Parser.getTok().is(AsmToken::Comma)) {
3396 Parser.Lex(); // Eat the ','.
3397 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3398 return MatchOperand_ParseFail;
3399 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003400
3401 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3402 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003403
3404 return MatchOperand_Success;
3405}
3406
Jim Grosbach251bf252011-08-10 21:56:18 +00003407ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3408parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3409 // Check for a post-index addressing register operand. Specifically:
3410 // am3offset := '+' register
3411 // | '-' register
3412 // | register
3413 // | # imm
3414 // | # + imm
3415 // | # - imm
3416
3417 // This method must return MatchOperand_NoMatch without consuming any tokens
3418 // in the case where there is no match, as other alternatives take other
3419 // parse methods.
3420 AsmToken Tok = Parser.getTok();
3421 SMLoc S = Tok.getLoc();
3422
3423 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003424 if (Parser.getTok().is(AsmToken::Hash) ||
3425 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003426 Parser.Lex(); // Eat the '#'.
3427 // Explicitly look for a '-', as we need to encode negative zero
3428 // differently.
3429 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3430 const MCExpr *Offset;
3431 if (getParser().ParseExpression(Offset))
3432 return MatchOperand_ParseFail;
3433 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3434 if (!CE) {
3435 Error(S, "constant expression expected");
3436 return MatchOperand_ParseFail;
3437 }
3438 SMLoc E = Tok.getLoc();
3439 // Negative zero is encoded as the flag value INT32_MIN.
3440 int32_t Val = CE->getValue();
3441 if (isNegative && Val == 0)
3442 Val = INT32_MIN;
3443
3444 Operands.push_back(
3445 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3446
3447 return MatchOperand_Success;
3448 }
3449
3450
3451 bool haveEaten = false;
3452 bool isAdd = true;
3453 int Reg = -1;
3454 if (Tok.is(AsmToken::Plus)) {
3455 Parser.Lex(); // Eat the '+' token.
3456 haveEaten = true;
3457 } else if (Tok.is(AsmToken::Minus)) {
3458 Parser.Lex(); // Eat the '-' token.
3459 isAdd = false;
3460 haveEaten = true;
3461 }
3462 if (Parser.getTok().is(AsmToken::Identifier))
3463 Reg = tryParseRegister();
3464 if (Reg == -1) {
3465 if (!haveEaten)
3466 return MatchOperand_NoMatch;
3467 Error(Parser.getTok().getLoc(), "register expected");
3468 return MatchOperand_ParseFail;
3469 }
3470 SMLoc E = Parser.getTok().getLoc();
3471
3472 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3473 0, S, E));
3474
3475 return MatchOperand_Success;
3476}
3477
Jim Grosbacha77295d2011-09-08 22:07:06 +00003478/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3479/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3480/// when they refer multiple MIOperands inside a single one.
3481bool ARMAsmParser::
3482cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3483 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3484 // Rt, Rt2
3485 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3486 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3487 // Create a writeback register dummy placeholder.
3488 Inst.addOperand(MCOperand::CreateReg(0));
3489 // addr
3490 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3491 // pred
3492 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3493 return true;
3494}
3495
3496/// cvtT2StrdPre - Convert parsed operands to MCInst.
3497/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3498/// when they refer multiple MIOperands inside a single one.
3499bool ARMAsmParser::
3500cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3501 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3502 // Create a writeback register dummy placeholder.
3503 Inst.addOperand(MCOperand::CreateReg(0));
3504 // Rt, Rt2
3505 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3506 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3507 // addr
3508 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3509 // pred
3510 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3511 return true;
3512}
3513
Jim Grosbacheeec0252011-09-08 00:39:19 +00003514/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3515/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3516/// when they refer multiple MIOperands inside a single one.
3517bool ARMAsmParser::
3518cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3519 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3520 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3521
3522 // Create a writeback register dummy placeholder.
3523 Inst.addOperand(MCOperand::CreateImm(0));
3524
3525 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3526 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3527 return true;
3528}
3529
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003530/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3531/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3532/// when they refer multiple MIOperands inside a single one.
3533bool ARMAsmParser::
3534cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3535 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3536 // Create a writeback register dummy placeholder.
3537 Inst.addOperand(MCOperand::CreateImm(0));
3538 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3539 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3540 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3541 return true;
3542}
3543
Jim Grosbach1355cf12011-07-26 17:10:22 +00003544/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003545/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3546/// when they refer multiple MIOperands inside a single one.
3547bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003548cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003549 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3550 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3551
3552 // Create a writeback register dummy placeholder.
3553 Inst.addOperand(MCOperand::CreateImm(0));
3554
Jim Grosbach7ce05792011-08-03 23:50:40 +00003555 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003556 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3557 return true;
3558}
3559
Owen Anderson9ab0f252011-08-26 20:43:14 +00003560/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3561/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3562/// when they refer multiple MIOperands inside a single one.
3563bool ARMAsmParser::
3564cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3565 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3566 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3567
3568 // Create a writeback register dummy placeholder.
3569 Inst.addOperand(MCOperand::CreateImm(0));
3570
3571 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3572 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3573 return true;
3574}
3575
3576
Jim Grosbach548340c2011-08-11 19:22:40 +00003577/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3578/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3579/// when they refer multiple MIOperands inside a single one.
3580bool ARMAsmParser::
3581cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3582 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3583 // Create a writeback register dummy placeholder.
3584 Inst.addOperand(MCOperand::CreateImm(0));
3585 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3586 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3587 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3588 return true;
3589}
3590
Jim Grosbach1355cf12011-07-26 17:10:22 +00003591/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003592/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3593/// when they refer multiple MIOperands inside a single one.
3594bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003595cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003596 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3597 // Create a writeback register dummy placeholder.
3598 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003599 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3600 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3601 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003602 return true;
3603}
3604
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003605/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3606/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3607/// when they refer multiple MIOperands inside a single one.
3608bool ARMAsmParser::
3609cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3610 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3611 // Create a writeback register dummy placeholder.
3612 Inst.addOperand(MCOperand::CreateImm(0));
3613 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3614 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3615 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3616 return true;
3617}
3618
Jim Grosbach7ce05792011-08-03 23:50:40 +00003619/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3620/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3621/// when they refer multiple MIOperands inside a single one.
3622bool ARMAsmParser::
3623cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3624 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3625 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003626 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003627 // Create a writeback register dummy placeholder.
3628 Inst.addOperand(MCOperand::CreateImm(0));
3629 // addr
3630 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3631 // offset
3632 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3633 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003634 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3635 return true;
3636}
3637
Jim Grosbach7ce05792011-08-03 23:50:40 +00003638/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003639/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3640/// when they refer multiple MIOperands inside a single one.
3641bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003642cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3643 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3644 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003645 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003646 // Create a writeback register dummy placeholder.
3647 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003648 // addr
3649 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3650 // offset
3651 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3652 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003653 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3654 return true;
3655}
3656
Jim Grosbach7ce05792011-08-03 23:50:40 +00003657/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003658/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3659/// when they refer multiple MIOperands inside a single one.
3660bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003661cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3662 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003663 // Create a writeback register dummy placeholder.
3664 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003665 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003666 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003667 // addr
3668 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3669 // offset
3670 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3671 // pred
3672 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3673 return true;
3674}
3675
3676/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
3677/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3678/// when they refer multiple MIOperands inside a single one.
3679bool ARMAsmParser::
3680cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3681 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3682 // Create a writeback register dummy placeholder.
3683 Inst.addOperand(MCOperand::CreateImm(0));
3684 // Rt
3685 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3686 // addr
3687 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3688 // offset
3689 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3690 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003691 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3692 return true;
3693}
3694
Jim Grosbach2fd2b872011-08-10 20:29:19 +00003695/// cvtLdrdPre - Convert parsed operands to MCInst.
3696/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3697/// when they refer multiple MIOperands inside a single one.
3698bool ARMAsmParser::
3699cvtLdrdPre(MCInst &Inst, unsigned Opcode,
3700 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3701 // Rt, Rt2
3702 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3703 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3704 // Create a writeback register dummy placeholder.
3705 Inst.addOperand(MCOperand::CreateImm(0));
3706 // addr
3707 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3708 // pred
3709 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3710 return true;
3711}
3712
Jim Grosbach14605d12011-08-11 20:28:23 +00003713/// cvtStrdPre - Convert parsed operands to MCInst.
3714/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3715/// when they refer multiple MIOperands inside a single one.
3716bool ARMAsmParser::
3717cvtStrdPre(MCInst &Inst, unsigned Opcode,
3718 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3719 // Create a writeback register dummy placeholder.
3720 Inst.addOperand(MCOperand::CreateImm(0));
3721 // Rt, Rt2
3722 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3723 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3724 // addr
3725 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
3726 // pred
3727 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3728 return true;
3729}
3730
Jim Grosbach623a4542011-08-10 22:42:16 +00003731/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3732/// 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::
3735cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3736 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3737 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3738 // Create a writeback register dummy placeholder.
3739 Inst.addOperand(MCOperand::CreateImm(0));
3740 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3741 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3742 return true;
3743}
3744
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003745/// cvtThumbMultiple- 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::
3749cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
3750 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3751 // The second source operand must be the same register as the destination
3752 // operand.
3753 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00003754 (((ARMOperand*)Operands[3])->getReg() !=
3755 ((ARMOperand*)Operands[5])->getReg()) &&
3756 (((ARMOperand*)Operands[3])->getReg() !=
3757 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003758 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00003759 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003760 return false;
3761 }
3762 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3763 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00003764 // If we have a three-operand form, make sure to set Rn to be the operand
3765 // that isn't the same as Rd.
3766 unsigned RegOp = 4;
3767 if (Operands.size() == 6 &&
3768 ((ARMOperand*)Operands[4])->getReg() ==
3769 ((ARMOperand*)Operands[3])->getReg())
3770 RegOp = 5;
3771 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
3772 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00003773 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
3774
3775 return true;
3776}
Jim Grosbach623a4542011-08-10 22:42:16 +00003777
Jim Grosbach12431322011-10-24 22:16:58 +00003778bool ARMAsmParser::
3779cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
3780 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3781 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003782 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003783 // Create a writeback register dummy placeholder.
3784 Inst.addOperand(MCOperand::CreateImm(0));
3785 // Vn
3786 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3787 // pred
3788 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3789 return true;
3790}
3791
3792bool ARMAsmParser::
3793cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
3794 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3795 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003796 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00003797 // Create a writeback register dummy placeholder.
3798 Inst.addOperand(MCOperand::CreateImm(0));
3799 // Vn
3800 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3801 // Vm
3802 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3803 // pred
3804 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3805 return true;
3806}
3807
Jim Grosbach4334e032011-10-31 21:50:31 +00003808bool ARMAsmParser::
3809cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
3810 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3811 // Create a writeback register dummy placeholder.
3812 Inst.addOperand(MCOperand::CreateImm(0));
3813 // Vn
3814 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3815 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003816 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003817 // pred
3818 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3819 return true;
3820}
3821
3822bool ARMAsmParser::
3823cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
3824 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3825 // Create a writeback register dummy placeholder.
3826 Inst.addOperand(MCOperand::CreateImm(0));
3827 // Vn
3828 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
3829 // Vm
3830 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
3831 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00003832 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00003833 // pred
3834 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3835 return true;
3836}
3837
Bill Wendlinge7176102010-11-06 22:36:58 +00003838/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003839/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00003840bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003841parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00003842 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00003843 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00003844 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00003845 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003846 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003847
Sean Callanan18b83232010-01-19 21:44:56 +00003848 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00003849 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00003850 if (BaseRegNum == -1)
3851 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003852
Daniel Dunbar05710932011-01-18 05:34:17 +00003853 // The next token must either be a comma or a closing bracket.
3854 const AsmToken &Tok = Parser.getTok();
3855 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003856 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00003857
Jim Grosbach7ce05792011-08-03 23:50:40 +00003858 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00003859 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00003860 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003861
Jim Grosbach7ce05792011-08-03 23:50:40 +00003862 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003863 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00003864
Jim Grosbachfb12f352011-09-19 18:42:21 +00003865 // If there's a pre-indexing writeback marker, '!', just add it as a token
3866 // operand. It's rather odd, but syntactically valid.
3867 if (Parser.getTok().is(AsmToken::Exclaim)) {
3868 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3869 Parser.Lex(); // Eat the '!'.
3870 }
3871
Jim Grosbach7ce05792011-08-03 23:50:40 +00003872 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003873 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003874
Jim Grosbach7ce05792011-08-03 23:50:40 +00003875 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
3876 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003877
Jim Grosbach57dcb852011-10-11 17:29:55 +00003878 // If we have a ':', it's an alignment specifier.
3879 if (Parser.getTok().is(AsmToken::Colon)) {
3880 Parser.Lex(); // Eat the ':'.
3881 E = Parser.getTok().getLoc();
3882
3883 const MCExpr *Expr;
3884 if (getParser().ParseExpression(Expr))
3885 return true;
3886
3887 // The expression has to be a constant. Memory references with relocations
3888 // don't come through here, as they use the <label> forms of the relevant
3889 // instructions.
3890 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3891 if (!CE)
3892 return Error (E, "constant expression expected");
3893
3894 unsigned Align = 0;
3895 switch (CE->getValue()) {
3896 default:
3897 return Error(E, "alignment specifier must be 64, 128, or 256 bits");
3898 case 64: Align = 8; break;
3899 case 128: Align = 16; break;
3900 case 256: Align = 32; break;
3901 }
3902
3903 // Now we should have the closing ']'
3904 E = Parser.getTok().getLoc();
3905 if (Parser.getTok().isNot(AsmToken::RBrac))
3906 return Error(E, "']' expected");
3907 Parser.Lex(); // Eat right bracket token.
3908
3909 // Don't worry about range checking the value here. That's handled by
3910 // the is*() predicates.
3911 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
3912 ARM_AM::no_shift, 0, Align,
3913 false, S, E));
3914
3915 // If there's a pre-indexing writeback marker, '!', just add it as a token
3916 // operand.
3917 if (Parser.getTok().is(AsmToken::Exclaim)) {
3918 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3919 Parser.Lex(); // Eat the '!'.
3920 }
3921
3922 return false;
3923 }
3924
3925 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003926 // offset. Be friendly and also accept a plain integer (without a leading
3927 // hash) for gas compatibility.
3928 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003929 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003930 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003931 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00003932 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00003933 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00003934
Owen Anderson0da10cf2011-08-29 19:36:44 +00003935 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003936 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00003937 if (getParser().ParseExpression(Offset))
3938 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003939
3940 // The expression has to be a constant. Memory references with relocations
3941 // don't come through here, as they use the <label> forms of the relevant
3942 // instructions.
3943 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3944 if (!CE)
3945 return Error (E, "constant expression expected");
3946
Owen Anderson0da10cf2011-08-29 19:36:44 +00003947 // If the constant was #-0, represent it as INT32_MIN.
3948 int32_t Val = CE->getValue();
3949 if (isNegative && Val == 0)
3950 CE = MCConstantExpr::Create(INT32_MIN, getContext());
3951
Jim Grosbach7ce05792011-08-03 23:50:40 +00003952 // Now we should have the closing ']'
3953 E = Parser.getTok().getLoc();
3954 if (Parser.getTok().isNot(AsmToken::RBrac))
3955 return Error(E, "']' expected");
3956 Parser.Lex(); // Eat right bracket token.
3957
3958 // Don't worry about range checking the value here. That's handled by
3959 // the is*() predicates.
3960 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00003961 ARM_AM::no_shift, 0, 0,
3962 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003963
3964 // If there's a pre-indexing writeback marker, '!', just add it as a token
3965 // operand.
3966 if (Parser.getTok().is(AsmToken::Exclaim)) {
3967 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
3968 Parser.Lex(); // Eat the '!'.
3969 }
3970
3971 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00003972 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00003973
3974 // The register offset is optionally preceded by a '+' or '-'
3975 bool isNegative = false;
3976 if (Parser.getTok().is(AsmToken::Minus)) {
3977 isNegative = true;
3978 Parser.Lex(); // Eat the '-'.
3979 } else if (Parser.getTok().is(AsmToken::Plus)) {
3980 // Nothing to do.
3981 Parser.Lex(); // Eat the '+'.
3982 }
3983
3984 E = Parser.getTok().getLoc();
3985 int OffsetRegNum = tryParseRegister();
3986 if (OffsetRegNum == -1)
3987 return Error(E, "register expected");
3988
3989 // If there's a shift operator, handle it.
3990 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003991 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003992 if (Parser.getTok().is(AsmToken::Comma)) {
3993 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003994 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00003995 return true;
3996 }
3997
3998 // Now we should have the closing ']'
3999 E = Parser.getTok().getLoc();
4000 if (Parser.getTok().isNot(AsmToken::RBrac))
4001 return Error(E, "']' expected");
4002 Parser.Lex(); // Eat right bracket token.
4003
4004 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004005 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004006 S, E));
4007
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004008 // If there's a pre-indexing writeback marker, '!', just add it as a token
4009 // operand.
4010 if (Parser.getTok().is(AsmToken::Exclaim)) {
4011 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4012 Parser.Lex(); // Eat the '!'.
4013 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004014
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004015 return false;
4016}
4017
Jim Grosbach7ce05792011-08-03 23:50:40 +00004018/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004019/// ( lsl | lsr | asr | ror ) , # shift_amount
4020/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004021/// return true if it parses a shift otherwise it returns false.
4022bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4023 unsigned &Amount) {
4024 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004025 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004026 if (Tok.isNot(AsmToken::Identifier))
4027 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004028 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004029 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4030 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004031 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004032 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004033 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004034 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004035 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004036 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004037 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004038 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004039 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004040 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004041 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004042 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004043
Jim Grosbach7ce05792011-08-03 23:50:40 +00004044 // rrx stands alone.
4045 Amount = 0;
4046 if (St != ARM_AM::rrx) {
4047 Loc = Parser.getTok().getLoc();
4048 // A '#' and a shift amount.
4049 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004050 if (HashTok.isNot(AsmToken::Hash) &&
4051 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004052 return Error(HashTok.getLoc(), "'#' expected");
4053 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004054
Jim Grosbach7ce05792011-08-03 23:50:40 +00004055 const MCExpr *Expr;
4056 if (getParser().ParseExpression(Expr))
4057 return true;
4058 // Range check the immediate.
4059 // lsl, ror: 0 <= imm <= 31
4060 // lsr, asr: 0 <= imm <= 32
4061 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4062 if (!CE)
4063 return Error(Loc, "shift amount must be an immediate");
4064 int64_t Imm = CE->getValue();
4065 if (Imm < 0 ||
4066 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4067 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4068 return Error(Loc, "immediate shift value out of range");
4069 Amount = Imm;
4070 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004071
4072 return false;
4073}
4074
Jim Grosbach9d390362011-10-03 23:38:36 +00004075/// parseFPImm - A floating point immediate expression operand.
4076ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4077parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4078 SMLoc S = Parser.getTok().getLoc();
4079
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004080 if (Parser.getTok().isNot(AsmToken::Hash) &&
4081 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004082 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004083
4084 // Disambiguate the VMOV forms that can accept an FP immediate.
4085 // vmov.f32 <sreg>, #imm
4086 // vmov.f64 <dreg>, #imm
4087 // vmov.f32 <dreg>, #imm @ vector f32x2
4088 // vmov.f32 <qreg>, #imm @ vector f32x4
4089 //
4090 // There are also the NEON VMOV instructions which expect an
4091 // integer constant. Make sure we don't try to parse an FPImm
4092 // for these:
4093 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4094 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4095 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4096 TyOp->getToken() != ".f64"))
4097 return MatchOperand_NoMatch;
4098
Jim Grosbach9d390362011-10-03 23:38:36 +00004099 Parser.Lex(); // Eat the '#'.
4100
4101 // Handle negation, as that still comes through as a separate token.
4102 bool isNegative = false;
4103 if (Parser.getTok().is(AsmToken::Minus)) {
4104 isNegative = true;
4105 Parser.Lex();
4106 }
4107 const AsmToken &Tok = Parser.getTok();
4108 if (Tok.is(AsmToken::Real)) {
4109 APFloat RealVal(APFloat::IEEEdouble, Tok.getString());
4110 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4111 // If we had a '-' in front, toggle the sign bit.
4112 IntVal ^= (uint64_t)isNegative << 63;
4113 int Val = ARM_AM::getFP64Imm(APInt(64, IntVal));
4114 Parser.Lex(); // Eat the token.
4115 if (Val == -1) {
4116 TokError("floating point value out of range");
4117 return MatchOperand_ParseFail;
4118 }
4119 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4120 return MatchOperand_Success;
4121 }
4122 if (Tok.is(AsmToken::Integer)) {
4123 int64_t Val = Tok.getIntVal();
4124 Parser.Lex(); // Eat the token.
4125 if (Val > 255 || Val < 0) {
4126 TokError("encoded floating point value out of range");
4127 return MatchOperand_ParseFail;
4128 }
4129 Operands.push_back(ARMOperand::CreateFPImm(Val, S, getContext()));
4130 return MatchOperand_Success;
4131 }
4132
4133 TokError("invalid floating point immediate");
4134 return MatchOperand_ParseFail;
4135}
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004136/// Parse a arm instruction operand. For now this parses the operand regardless
4137/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004138bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004139 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004140 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004141
4142 // Check if the current operand has a custom associated parser, if so, try to
4143 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004144 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4145 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004146 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004147 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4148 // there was a match, but an error occurred, in which case, just return that
4149 // the operand parsing failed.
4150 if (ResTy == MatchOperand_ParseFail)
4151 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004152
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004153 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004154 default:
4155 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004156 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004157 case AsmToken::Identifier: {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004158 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004159 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004160 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004161 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004162 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004163 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004164 else if (Res == -1) // irrecoverable error
4165 return true;
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004166 if (Mnemonic == "vmrs" && Parser.getTok().getString() == "apsr_nzcv") {
4167 S = Parser.getTok().getLoc();
4168 Parser.Lex();
4169 Operands.push_back(ARMOperand::CreateToken("apsr_nzcv", S));
4170 return false;
4171 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004172
4173 // Fall though for the Identifier case that is not a register or a
4174 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004175 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004176 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004177 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004178 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004179 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004180 // This was not a register so parse other operands that start with an
4181 // identifier (like labels) as expressions and create them as immediates.
4182 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004183 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004184 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004185 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004186 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004187 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4188 return false;
4189 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004190 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004191 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004192 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004193 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004194 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004195 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004196 // #42 -> immediate.
4197 // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
Sean Callanan76264762010-04-02 22:27:05 +00004198 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004199 Parser.Lex();
Owen Anderson63553c72011-08-29 17:17:09 +00004200 bool isNegative = Parser.getTok().is(AsmToken::Minus);
Kevin Enderby515d5092009-10-15 20:48:48 +00004201 const MCExpr *ImmVal;
4202 if (getParser().ParseExpression(ImmVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004203 return true;
Owen Anderson63553c72011-08-29 17:17:09 +00004204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbached6a0c52011-11-01 22:37:37 +00004205 if (CE) {
4206 int32_t Val = CE->getValue();
4207 if (isNegative && Val == 0)
4208 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
Owen Anderson63553c72011-08-29 17:17:09 +00004209 }
Sean Callanan76264762010-04-02 22:27:05 +00004210 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004211 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4212 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004213 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004214 case AsmToken::Colon: {
4215 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004216 // FIXME: Check it's an expression prefix,
4217 // e.g. (FOO - :lower16:BAR) isn't legal.
4218 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004219 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004220 return true;
4221
Evan Cheng75972122011-01-13 07:58:56 +00004222 const MCExpr *SubExprVal;
4223 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004224 return true;
4225
Evan Cheng75972122011-01-13 07:58:56 +00004226 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4227 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004228 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004229 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004230 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004231 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004232 }
4233}
4234
Jim Grosbach1355cf12011-07-26 17:10:22 +00004235// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004236// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004237bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004238 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004239
4240 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004241 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004242 Parser.Lex(); // Eat ':'
4243
4244 if (getLexer().isNot(AsmToken::Identifier)) {
4245 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4246 return true;
4247 }
4248
4249 StringRef IDVal = Parser.getTok().getIdentifier();
4250 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004251 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004252 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004253 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004254 } else {
4255 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4256 return true;
4257 }
4258 Parser.Lex();
4259
4260 if (getLexer().isNot(AsmToken::Colon)) {
4261 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4262 return true;
4263 }
4264 Parser.Lex(); // Eat the last ':'
4265 return false;
4266}
4267
Daniel Dunbar352e1482011-01-11 15:59:50 +00004268/// \brief Given a mnemonic, split out possible predication code and carry
4269/// setting letters to form a canonical mnemonic and flags.
4270//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004271// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004272// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004273StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004274 unsigned &PredicationCode,
4275 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004276 unsigned &ProcessorIMod,
4277 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004278 PredicationCode = ARMCC::AL;
4279 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004280 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004281
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004282 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004283 //
4284 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004285 if ((Mnemonic == "movs" && isThumb()) ||
4286 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4287 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4288 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4289 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4290 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4291 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
4292 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004293 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004294
Jim Grosbach3f00e312011-07-11 17:09:57 +00004295 // First, split out any predication code. Ignore mnemonics we know aren't
4296 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004297 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004298 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004299 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004300 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004301 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4302 .Case("eq", ARMCC::EQ)
4303 .Case("ne", ARMCC::NE)
4304 .Case("hs", ARMCC::HS)
4305 .Case("cs", ARMCC::HS)
4306 .Case("lo", ARMCC::LO)
4307 .Case("cc", ARMCC::LO)
4308 .Case("mi", ARMCC::MI)
4309 .Case("pl", ARMCC::PL)
4310 .Case("vs", ARMCC::VS)
4311 .Case("vc", ARMCC::VC)
4312 .Case("hi", ARMCC::HI)
4313 .Case("ls", ARMCC::LS)
4314 .Case("ge", ARMCC::GE)
4315 .Case("lt", ARMCC::LT)
4316 .Case("gt", ARMCC::GT)
4317 .Case("le", ARMCC::LE)
4318 .Case("al", ARMCC::AL)
4319 .Default(~0U);
4320 if (CC != ~0U) {
4321 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4322 PredicationCode = CC;
4323 }
Bill Wendling52925b62010-10-29 23:50:21 +00004324 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004325
Daniel Dunbar352e1482011-01-11 15:59:50 +00004326 // Next, determine if we have a carry setting bit. We explicitly ignore all
4327 // the instructions we know end in 's'.
4328 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004329 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004330 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4331 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4332 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004333 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004334 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbachf1015402011-12-13 20:13:48 +00004335 Mnemonic == "fsts" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004336 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004337 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4338 CarrySetting = true;
4339 }
4340
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004341 // The "cps" instruction can have a interrupt mode operand which is glued into
4342 // the mnemonic. Check if this is the case, split it and parse the imod op
4343 if (Mnemonic.startswith("cps")) {
4344 // Split out any imod code.
4345 unsigned IMod =
4346 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4347 .Case("ie", ARM_PROC::IE)
4348 .Case("id", ARM_PROC::ID)
4349 .Default(~0U);
4350 if (IMod != ~0U) {
4351 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4352 ProcessorIMod = IMod;
4353 }
4354 }
4355
Jim Grosbach89df9962011-08-26 21:43:41 +00004356 // The "it" instruction has the condition mask on the end of the mnemonic.
4357 if (Mnemonic.startswith("it")) {
4358 ITMask = Mnemonic.slice(2, Mnemonic.size());
4359 Mnemonic = Mnemonic.slice(0, 2);
4360 }
4361
Daniel Dunbar352e1482011-01-11 15:59:50 +00004362 return Mnemonic;
4363}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004364
4365/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4366/// inclusion of carry set or predication code operands.
4367//
4368// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004369void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004370getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004371 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004372 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4373 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004374 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004375 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004376 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004377 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004378 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004379 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004380 Mnemonic == "mla" || Mnemonic == "smlal" ||
4381 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004382 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004383 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004384 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004385
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004386 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4387 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4388 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4389 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004390 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4391 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004392 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004393 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4394 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4395 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004396 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4397 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004398 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004399 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004400 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004401 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004402
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004403 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004404 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004405 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004406 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004407 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004408}
4409
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004410bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4411 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004412 // FIXME: This is all horribly hacky. We really need a better way to deal
4413 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004414
4415 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4416 // another does not. Specifically, the MOVW instruction does not. So we
4417 // special case it here and remove the defaulted (non-setting) cc_out
4418 // operand if that's the instruction we're trying to match.
4419 //
4420 // We do this as post-processing of the explicit operands rather than just
4421 // conditionally adding the cc_out in the first place because we need
4422 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004423 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004424 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4425 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4426 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4427 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004428
4429 // Register-register 'add' for thumb does not have a cc_out operand
4430 // when there are only two register operands.
4431 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4432 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4433 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4434 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4435 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004436 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004437 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4438 // have to check the immediate range here since Thumb2 has a variant
4439 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004440 if (((isThumb() && Mnemonic == "add") ||
4441 (isThumbTwo() && Mnemonic == "sub")) &&
4442 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004443 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4444 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4445 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004446 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4447 (static_cast<ARMOperand*>(Operands[5])->isReg() ||
4448 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004449 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004450 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4451 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004452 // selecting via the generic "add" mnemonic, so to know that we
4453 // should remove the cc_out operand, we have to explicitly check that
4454 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004455 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4456 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004457 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4458 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4459 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4460 // Nest conditions rather than one big 'if' statement for readability.
4461 //
4462 // If either register is a high reg, it's either one of the SP
4463 // variants (handled above) or a 32-bit encoding, so we just
4464 // check against T3.
4465 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4466 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4467 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4468 return false;
4469 // If both registers are low, we're in an IT block, and the immediate is
4470 // in range, we should use encoding T1 instead, which has a cc_out.
4471 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004472 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004473 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4474 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4475 return false;
4476
4477 // Otherwise, we use encoding T4, which does not have a cc_out
4478 // operand.
4479 return true;
4480 }
4481
Jim Grosbach64944f42011-09-14 21:00:40 +00004482 // The thumb2 multiply instruction doesn't have a CCOut register, so
4483 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4484 // use the 16-bit encoding or not.
4485 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4486 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4487 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4488 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4489 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4490 // If the registers aren't low regs, the destination reg isn't the
4491 // same as one of the source regs, or the cc_out operand is zero
4492 // outside of an IT block, we have to use the 32-bit encoding, so
4493 // remove the cc_out operand.
4494 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4495 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004496 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004497 !inITBlock() ||
4498 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4499 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4500 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4501 static_cast<ARMOperand*>(Operands[4])->getReg())))
4502 return true;
4503
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004504 // Also check the 'mul' syntax variant that doesn't specify an explicit
4505 // destination register.
4506 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4507 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4508 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4509 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4510 // If the registers aren't low regs or the cc_out operand is zero
4511 // outside of an IT block, we have to use the 32-bit encoding, so
4512 // remove the cc_out operand.
4513 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4514 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4515 !inITBlock()))
4516 return true;
4517
Jim Grosbach64944f42011-09-14 21:00:40 +00004518
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004519
Jim Grosbachf69c8042011-08-24 21:42:27 +00004520 // Register-register 'add/sub' for thumb does not have a cc_out operand
4521 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4522 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4523 // right, this will result in better diagnostics (which operand is off)
4524 // anyway.
4525 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4526 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004527 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4528 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4529 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4530 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004531
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004532 return false;
4533}
4534
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004535static bool isDataTypeToken(StringRef Tok) {
4536 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4537 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4538 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4539 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4540 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4541 Tok == ".f" || Tok == ".d";
4542}
4543
4544// FIXME: This bit should probably be handled via an explicit match class
4545// in the .td files that matches the suffix instead of having it be
4546// a literal string token the way it is now.
4547static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4548 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4549}
4550
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004551static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004552/// Parse an arm instruction mnemonic followed by its operands.
4553bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4554 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004555 // Apply mnemonic aliases before doing anything else, as the destination
4556 // mnemnonic may include suffices and we want to handle them normally.
4557 // The generic tblgen'erated code does this later, at the start of
4558 // MatchInstructionImpl(), but that's too late for aliases that include
4559 // any sort of suffix.
4560 unsigned AvailableFeatures = getAvailableFeatures();
4561 applyMnemonicAliases(Name, AvailableFeatures);
4562
Jim Grosbacha39cda72011-12-14 02:16:11 +00004563 // First check for the ARM-specific .req directive.
4564 if (Parser.getTok().is(AsmToken::Identifier) &&
4565 Parser.getTok().getIdentifier() == ".req") {
4566 parseDirectiveReq(Name, NameLoc);
4567 // We always return 'error' for this, as we're done with this
4568 // statement and don't need to match the 'instruction."
4569 return true;
4570 }
4571
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004572 // Create the leading tokens for the mnemonic, split by '.' characters.
4573 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004574 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004575
Daniel Dunbar352e1482011-01-11 15:59:50 +00004576 // Split out the predication code and carry setting flag from the mnemonic.
4577 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004578 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004579 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004580 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004581 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004582 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004583
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004584 // In Thumb1, only the branch (B) instruction can be predicated.
4585 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4586 Parser.EatToEndOfStatement();
4587 return Error(NameLoc, "conditional execution not supported in Thumb1");
4588 }
4589
Jim Grosbachffa32252011-07-19 19:13:28 +00004590 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4591
Jim Grosbach89df9962011-08-26 21:43:41 +00004592 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4593 // is the mask as it will be for the IT encoding if the conditional
4594 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4595 // where the conditional bit0 is zero, the instruction post-processing
4596 // will adjust the mask accordingly.
4597 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004598 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4599 if (ITMask.size() > 3) {
4600 Parser.EatToEndOfStatement();
4601 return Error(Loc, "too many conditions on IT instruction");
4602 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004603 unsigned Mask = 8;
4604 for (unsigned i = ITMask.size(); i != 0; --i) {
4605 char pos = ITMask[i - 1];
4606 if (pos != 't' && pos != 'e') {
4607 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004608 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004609 }
4610 Mask >>= 1;
4611 if (ITMask[i - 1] == 't')
4612 Mask |= 8;
4613 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004614 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004615 }
4616
Jim Grosbachffa32252011-07-19 19:13:28 +00004617 // FIXME: This is all a pretty gross hack. We should automatically handle
4618 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004619
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004620 // Next, add the CCOut and ConditionCode operands, if needed.
4621 //
4622 // For mnemonics which can ever incorporate a carry setting bit or predication
4623 // code, our matching model involves us always generating CCOut and
4624 // ConditionCode operands to match the mnemonic "as written" and then we let
4625 // the matcher deal with finding the right instruction or generating an
4626 // appropriate error.
4627 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004628 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004629
Jim Grosbach33c16a22011-07-14 22:04:21 +00004630 // If we had a carry-set on an instruction that can't do that, issue an
4631 // error.
4632 if (!CanAcceptCarrySet && CarrySetting) {
4633 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00004634 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00004635 "' can not set flags, but 's' suffix specified");
4636 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00004637 // If we had a predication code on an instruction that can't do that, issue an
4638 // error.
4639 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
4640 Parser.EatToEndOfStatement();
4641 return Error(NameLoc, "instruction '" + Mnemonic +
4642 "' is not predicable, but condition code specified");
4643 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00004644
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004645 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004646 if (CanAcceptCarrySet) {
4647 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004648 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004649 Loc));
4650 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004651
4652 // Add the predication code operand, if necessary.
4653 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004654 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
4655 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004656 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004657 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004658 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004659
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004660 // Add the processor imod operand, if necessary.
4661 if (ProcessorIMod) {
4662 Operands.push_back(ARMOperand::CreateImm(
4663 MCConstantExpr::Create(ProcessorIMod, getContext()),
4664 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004665 }
4666
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004667 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00004668 while (Next != StringRef::npos) {
4669 Start = Next;
4670 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004671 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004672
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004673 // Some NEON instructions have an optional datatype suffix that is
4674 // completely ignored. Check for that.
4675 if (isDataTypeToken(ExtraToken) &&
4676 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
4677 continue;
4678
Jim Grosbach81d2e392011-09-07 16:06:04 +00004679 if (ExtraToken != ".n") {
4680 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
4681 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
4682 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00004683 }
4684
4685 // Read the remaining operands.
4686 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004687 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004688 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004689 Parser.EatToEndOfStatement();
4690 return true;
4691 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004692
4693 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00004694 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004695
4696 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004697 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00004698 Parser.EatToEndOfStatement();
4699 return true;
4700 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004701 }
4702 }
Jim Grosbach16c74252010-10-29 14:46:02 +00004703
Chris Lattnercbf8a982010-09-11 16:18:25 +00004704 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00004705 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00004706 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00004707 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00004708 }
Bill Wendling146018f2010-11-06 21:42:12 +00004709
Chris Lattner34e53142010-09-08 05:10:46 +00004710 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00004711
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004712 // Some instructions, mostly Thumb, have forms for the same mnemonic that
4713 // do and don't have a cc_out optional-def operand. With some spot-checks
4714 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004715 // parse and adjust accordingly before actually matching. We shouldn't ever
4716 // try to remove a cc_out operand that was explicitly set on the the
4717 // mnemonic, of course (CarrySetting == true). Reason number #317 the
4718 // table driven matcher doesn't fit well with the ARM instruction set.
4719 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00004720 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4721 Operands.erase(Operands.begin() + 1);
4722 delete Op;
4723 }
4724
Jim Grosbachcf121c32011-07-28 21:57:55 +00004725 // ARM mode 'blx' need special handling, as the register operand version
4726 // is predicable, but the label operand version is not. So, we can't rely
4727 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00004728 // a k_CondCode operand in the list. If we're trying to match the label
4729 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00004730 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
4731 static_cast<ARMOperand*>(Operands[2])->isImm()) {
4732 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
4733 Operands.erase(Operands.begin() + 1);
4734 delete Op;
4735 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00004736
4737 // The vector-compare-to-zero instructions have a literal token "#0" at
4738 // the end that comes to here as an immediate operand. Convert it to a
4739 // token to play nicely with the matcher.
4740 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
4741 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
4742 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4743 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4744 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4745 if (CE && CE->getValue() == 0) {
4746 Operands.erase(Operands.begin() + 5);
4747 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4748 delete Op;
4749 }
4750 }
Jim Grosbach68259142011-10-03 22:30:24 +00004751 // VCMP{E} does the same thing, but with a different operand count.
4752 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
4753 static_cast<ARMOperand*>(Operands[4])->isImm()) {
4754 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
4755 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
4756 if (CE && CE->getValue() == 0) {
4757 Operands.erase(Operands.begin() + 4);
4758 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4759 delete Op;
4760 }
4761 }
Jim Grosbach934755a2011-08-22 23:47:13 +00004762 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00004763 // end. Convert it to a token here. Take care not to convert those
4764 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00004765 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00004766 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4767 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00004768 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4769 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
4770 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00004771 if (CE && CE->getValue() == 0 &&
4772 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004773 // The cc_out operand matches the IT block.
4774 ((inITBlock() != CarrySetting) &&
4775 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00004776 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00004777 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00004778 Operands.erase(Operands.begin() + 5);
4779 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
4780 delete Op;
4781 }
4782 }
4783
Chris Lattner98986712010-01-14 22:21:20 +00004784 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00004785}
4786
Jim Grosbach189610f2011-07-26 18:25:39 +00004787// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004788
4789// return 'true' if register list contains non-low GPR registers,
4790// 'false' otherwise. If Reg is in the register list or is HiReg, set
4791// 'containsReg' to true.
4792static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
4793 unsigned HiReg, bool &containsReg) {
4794 containsReg = false;
4795 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4796 unsigned OpReg = Inst.getOperand(i).getReg();
4797 if (OpReg == Reg)
4798 containsReg = true;
4799 // Anything other than a low register isn't legal here.
4800 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
4801 return true;
4802 }
4803 return false;
4804}
4805
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004806// Check if the specified regisgter is in the register list of the inst,
4807// starting at the indicated operand number.
4808static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
4809 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
4810 unsigned OpReg = Inst.getOperand(i).getReg();
4811 if (OpReg == Reg)
4812 return true;
4813 }
4814 return false;
4815}
4816
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004817// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
4818// the ARMInsts array) instead. Getting that here requires awkward
4819// API changes, though. Better way?
4820namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004821extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004822}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004823static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004824 return ARMInsts[Opcode];
4825}
4826
Jim Grosbach189610f2011-07-26 18:25:39 +00004827// FIXME: We would really like to be able to tablegen'erate this.
4828bool ARMAsmParser::
4829validateInstruction(MCInst &Inst,
4830 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00004831 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004832 SMLoc Loc = Operands[0]->getStartLoc();
4833 // Check the IT block state first.
Owen Andersonb6b7f512011-09-13 17:59:19 +00004834 // NOTE: In Thumb mode, the BKPT instruction has the interesting property of
4835 // being allowed in IT blocks, but not being predicable. It just always
4836 // executes.
4837 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004838 unsigned bit = 1;
4839 if (ITState.FirstCond)
4840 ITState.FirstCond = false;
4841 else
Jim Grosbacha1109882011-09-02 23:22:08 +00004842 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004843 // The instruction must be predicable.
4844 if (!MCID.isPredicable())
4845 return Error(Loc, "instructions in IT block must be predicable");
4846 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
4847 unsigned ITCond = bit ? ITState.Cond :
4848 ARMCC::getOppositeCondition(ITState.Cond);
4849 if (Cond != ITCond) {
4850 // Find the condition code Operand to get its SMLoc information.
4851 SMLoc CondLoc;
4852 for (unsigned i = 1; i < Operands.size(); ++i)
4853 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
4854 CondLoc = Operands[i]->getStartLoc();
4855 return Error(CondLoc, "incorrect condition in IT block; got '" +
4856 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
4857 "', but expected '" +
4858 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
4859 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00004860 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004861 } else if (isThumbTwo() && MCID.isPredicable() &&
4862 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00004863 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
4864 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004865 return Error(Loc, "predicated instructions must be in IT block");
4866
Jim Grosbach189610f2011-07-26 18:25:39 +00004867 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004868 case ARM::LDRD:
4869 case ARM::LDRD_PRE:
4870 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004871 case ARM::LDREXD: {
4872 // Rt2 must be Rt + 1.
4873 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4874 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4875 if (Rt2 != Rt + 1)
4876 return Error(Operands[3]->getStartLoc(),
4877 "destination operands must be sequential");
4878 return false;
4879 }
Jim Grosbach14605d12011-08-11 20:28:23 +00004880 case ARM::STRD: {
4881 // Rt2 must be Rt + 1.
4882 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
4883 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4884 if (Rt2 != Rt + 1)
4885 return Error(Operands[3]->getStartLoc(),
4886 "source operands must be sequential");
4887 return false;
4888 }
Jim Grosbach53642c52011-08-10 20:49:18 +00004889 case ARM::STRD_PRE:
4890 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00004891 case ARM::STREXD: {
4892 // Rt2 must be Rt + 1.
4893 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
4894 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
4895 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00004896 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00004897 "source operands must be sequential");
4898 return false;
4899 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004900 case ARM::SBFX:
4901 case ARM::UBFX: {
4902 // width must be in range [1, 32-lsb]
4903 unsigned lsb = Inst.getOperand(2).getImm();
4904 unsigned widthm1 = Inst.getOperand(3).getImm();
4905 if (widthm1 >= 32 - lsb)
4906 return Error(Operands[5]->getStartLoc(),
4907 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00004908 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00004909 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004910 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004911 // If we're parsing Thumb2, the .w variant is available and handles
4912 // most cases that are normally illegal for a Thumb1 LDM
4913 // instruction. We'll make the transformation in processInstruction()
4914 // if necessary.
4915 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004916 // Thumb LDM instructions are writeback iff the base register is not
4917 // in the register list.
4918 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004919 bool hasWritebackToken =
4920 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
4921 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00004922 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004923 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004924 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
4925 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004926 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004927 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004928 return Error(Operands[2]->getStartLoc(),
4929 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004930 // If we should not have writeback, there must not be a '!'. This is
4931 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00004932 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00004933 return Error(Operands[3]->getStartLoc(),
4934 "writeback operator '!' not allowed when base register "
4935 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00004936
4937 break;
4938 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00004939 case ARM::t2LDMIA_UPD: {
4940 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
4941 return Error(Operands[4]->getStartLoc(),
4942 "writeback operator '!' not allowed when base register "
4943 "in register list");
4944 break;
4945 }
Jim Grosbach54026372011-11-10 23:17:11 +00004946 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
4947 // so only issue a diagnostic for thumb1. The instructions will be
4948 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004949 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004950 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004951 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
4952 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004953 return Error(Operands[2]->getStartLoc(),
4954 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004955 break;
4956 }
4957 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00004958 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00004959 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
4960 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00004961 return Error(Operands[2]->getStartLoc(),
4962 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00004963 break;
4964 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00004965 case ARM::tSTMIA_UPD: {
4966 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00004967 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00004968 return Error(Operands[4]->getStartLoc(),
4969 "registers must be in range r0-r7");
4970 break;
4971 }
Jim Grosbach189610f2011-07-26 18:25:39 +00004972 }
4973
4974 return false;
4975}
4976
Jim Grosbach84defb52011-12-02 22:34:51 +00004977static unsigned getRealVSTLNOpcode(unsigned Opc) {
4978 switch(Opc) {
4979 default: assert(0 && "unexpected opcode!");
4980 case ARM::VST1LNdWB_fixed_Asm_8: return ARM::VST1LNd8_UPD;
4981 case ARM::VST1LNdWB_fixed_Asm_P8: return ARM::VST1LNd8_UPD;
4982 case ARM::VST1LNdWB_fixed_Asm_I8: return ARM::VST1LNd8_UPD;
4983 case ARM::VST1LNdWB_fixed_Asm_S8: return ARM::VST1LNd8_UPD;
4984 case ARM::VST1LNdWB_fixed_Asm_U8: return ARM::VST1LNd8_UPD;
4985 case ARM::VST1LNdWB_fixed_Asm_16: return ARM::VST1LNd16_UPD;
4986 case ARM::VST1LNdWB_fixed_Asm_P16: return ARM::VST1LNd16_UPD;
4987 case ARM::VST1LNdWB_fixed_Asm_I16: return ARM::VST1LNd16_UPD;
4988 case ARM::VST1LNdWB_fixed_Asm_S16: return ARM::VST1LNd16_UPD;
4989 case ARM::VST1LNdWB_fixed_Asm_U16: return ARM::VST1LNd16_UPD;
4990 case ARM::VST1LNdWB_fixed_Asm_32: return ARM::VST1LNd32_UPD;
4991 case ARM::VST1LNdWB_fixed_Asm_F: return ARM::VST1LNd32_UPD;
4992 case ARM::VST1LNdWB_fixed_Asm_F32: return ARM::VST1LNd32_UPD;
4993 case ARM::VST1LNdWB_fixed_Asm_I32: return ARM::VST1LNd32_UPD;
4994 case ARM::VST1LNdWB_fixed_Asm_S32: return ARM::VST1LNd32_UPD;
4995 case ARM::VST1LNdWB_fixed_Asm_U32: return ARM::VST1LNd32_UPD;
4996 case ARM::VST1LNdWB_register_Asm_8: return ARM::VST1LNd8_UPD;
4997 case ARM::VST1LNdWB_register_Asm_P8: return ARM::VST1LNd8_UPD;
4998 case ARM::VST1LNdWB_register_Asm_I8: return ARM::VST1LNd8_UPD;
4999 case ARM::VST1LNdWB_register_Asm_S8: return ARM::VST1LNd8_UPD;
5000 case ARM::VST1LNdWB_register_Asm_U8: return ARM::VST1LNd8_UPD;
5001 case ARM::VST1LNdWB_register_Asm_16: return ARM::VST1LNd16_UPD;
5002 case ARM::VST1LNdWB_register_Asm_P16: return ARM::VST1LNd16_UPD;
5003 case ARM::VST1LNdWB_register_Asm_I16: return ARM::VST1LNd16_UPD;
5004 case ARM::VST1LNdWB_register_Asm_S16: return ARM::VST1LNd16_UPD;
5005 case ARM::VST1LNdWB_register_Asm_U16: return ARM::VST1LNd16_UPD;
5006 case ARM::VST1LNdWB_register_Asm_32: return ARM::VST1LNd32_UPD;
5007 case ARM::VST1LNdWB_register_Asm_F: return ARM::VST1LNd32_UPD;
5008 case ARM::VST1LNdWB_register_Asm_F32: return ARM::VST1LNd32_UPD;
5009 case ARM::VST1LNdWB_register_Asm_I32: return ARM::VST1LNd32_UPD;
5010 case ARM::VST1LNdWB_register_Asm_S32: return ARM::VST1LNd32_UPD;
5011 case ARM::VST1LNdWB_register_Asm_U32: return ARM::VST1LNd32_UPD;
5012 case ARM::VST1LNdAsm_8: return ARM::VST1LNd8;
5013 case ARM::VST1LNdAsm_P8: return ARM::VST1LNd8;
5014 case ARM::VST1LNdAsm_I8: return ARM::VST1LNd8;
5015 case ARM::VST1LNdAsm_S8: return ARM::VST1LNd8;
5016 case ARM::VST1LNdAsm_U8: return ARM::VST1LNd8;
5017 case ARM::VST1LNdAsm_16: return ARM::VST1LNd16;
5018 case ARM::VST1LNdAsm_P16: return ARM::VST1LNd16;
5019 case ARM::VST1LNdAsm_I16: return ARM::VST1LNd16;
5020 case ARM::VST1LNdAsm_S16: return ARM::VST1LNd16;
5021 case ARM::VST1LNdAsm_U16: return ARM::VST1LNd16;
5022 case ARM::VST1LNdAsm_32: return ARM::VST1LNd32;
5023 case ARM::VST1LNdAsm_F: return ARM::VST1LNd32;
5024 case ARM::VST1LNdAsm_F32: return ARM::VST1LNd32;
5025 case ARM::VST1LNdAsm_I32: return ARM::VST1LNd32;
5026 case ARM::VST1LNdAsm_S32: return ARM::VST1LNd32;
5027 case ARM::VST1LNdAsm_U32: return ARM::VST1LNd32;
5028 }
5029}
5030
5031static unsigned getRealVLDLNOpcode(unsigned Opc) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005032 switch(Opc) {
5033 default: assert(0 && "unexpected opcode!");
Jim Grosbach872eedb2011-12-02 22:01:52 +00005034 case ARM::VLD1LNdWB_fixed_Asm_8: return ARM::VLD1LNd8_UPD;
5035 case ARM::VLD1LNdWB_fixed_Asm_P8: return ARM::VLD1LNd8_UPD;
5036 case ARM::VLD1LNdWB_fixed_Asm_I8: return ARM::VLD1LNd8_UPD;
5037 case ARM::VLD1LNdWB_fixed_Asm_S8: return ARM::VLD1LNd8_UPD;
5038 case ARM::VLD1LNdWB_fixed_Asm_U8: return ARM::VLD1LNd8_UPD;
5039 case ARM::VLD1LNdWB_fixed_Asm_16: return ARM::VLD1LNd16_UPD;
5040 case ARM::VLD1LNdWB_fixed_Asm_P16: return ARM::VLD1LNd16_UPD;
5041 case ARM::VLD1LNdWB_fixed_Asm_I16: return ARM::VLD1LNd16_UPD;
5042 case ARM::VLD1LNdWB_fixed_Asm_S16: return ARM::VLD1LNd16_UPD;
5043 case ARM::VLD1LNdWB_fixed_Asm_U16: return ARM::VLD1LNd16_UPD;
5044 case ARM::VLD1LNdWB_fixed_Asm_32: return ARM::VLD1LNd32_UPD;
5045 case ARM::VLD1LNdWB_fixed_Asm_F: return ARM::VLD1LNd32_UPD;
5046 case ARM::VLD1LNdWB_fixed_Asm_F32: return ARM::VLD1LNd32_UPD;
5047 case ARM::VLD1LNdWB_fixed_Asm_I32: return ARM::VLD1LNd32_UPD;
5048 case ARM::VLD1LNdWB_fixed_Asm_S32: return ARM::VLD1LNd32_UPD;
5049 case ARM::VLD1LNdWB_fixed_Asm_U32: return ARM::VLD1LNd32_UPD;
5050 case ARM::VLD1LNdWB_register_Asm_8: return ARM::VLD1LNd8_UPD;
5051 case ARM::VLD1LNdWB_register_Asm_P8: return ARM::VLD1LNd8_UPD;
5052 case ARM::VLD1LNdWB_register_Asm_I8: return ARM::VLD1LNd8_UPD;
5053 case ARM::VLD1LNdWB_register_Asm_S8: return ARM::VLD1LNd8_UPD;
5054 case ARM::VLD1LNdWB_register_Asm_U8: return ARM::VLD1LNd8_UPD;
5055 case ARM::VLD1LNdWB_register_Asm_16: return ARM::VLD1LNd16_UPD;
5056 case ARM::VLD1LNdWB_register_Asm_P16: return ARM::VLD1LNd16_UPD;
5057 case ARM::VLD1LNdWB_register_Asm_I16: return ARM::VLD1LNd16_UPD;
5058 case ARM::VLD1LNdWB_register_Asm_S16: return ARM::VLD1LNd16_UPD;
5059 case ARM::VLD1LNdWB_register_Asm_U16: return ARM::VLD1LNd16_UPD;
5060 case ARM::VLD1LNdWB_register_Asm_32: return ARM::VLD1LNd32_UPD;
5061 case ARM::VLD1LNdWB_register_Asm_F: return ARM::VLD1LNd32_UPD;
5062 case ARM::VLD1LNdWB_register_Asm_F32: return ARM::VLD1LNd32_UPD;
5063 case ARM::VLD1LNdWB_register_Asm_I32: return ARM::VLD1LNd32_UPD;
5064 case ARM::VLD1LNdWB_register_Asm_S32: return ARM::VLD1LNd32_UPD;
5065 case ARM::VLD1LNdWB_register_Asm_U32: return ARM::VLD1LNd32_UPD;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005066 case ARM::VLD1LNdAsm_8: return ARM::VLD1LNd8;
5067 case ARM::VLD1LNdAsm_P8: return ARM::VLD1LNd8;
5068 case ARM::VLD1LNdAsm_I8: return ARM::VLD1LNd8;
5069 case ARM::VLD1LNdAsm_S8: return ARM::VLD1LNd8;
5070 case ARM::VLD1LNdAsm_U8: return ARM::VLD1LNd8;
Jim Grosbach872eedb2011-12-02 22:01:52 +00005071 case ARM::VLD1LNdAsm_16: return ARM::VLD1LNd16;
5072 case ARM::VLD1LNdAsm_P16: return ARM::VLD1LNd16;
5073 case ARM::VLD1LNdAsm_I16: return ARM::VLD1LNd16;
5074 case ARM::VLD1LNdAsm_S16: return ARM::VLD1LNd16;
5075 case ARM::VLD1LNdAsm_U16: return ARM::VLD1LNd16;
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005076 case ARM::VLD1LNdAsm_32: return ARM::VLD1LNd32;
5077 case ARM::VLD1LNdAsm_F: return ARM::VLD1LNd32;
5078 case ARM::VLD1LNdAsm_F32: return ARM::VLD1LNd32;
5079 case ARM::VLD1LNdAsm_I32: return ARM::VLD1LNd32;
5080 case ARM::VLD1LNdAsm_S32: return ARM::VLD1LNd32;
5081 case ARM::VLD1LNdAsm_U32: return ARM::VLD1LNd32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005082 }
5083}
5084
Jim Grosbach83ec8772011-11-10 23:42:14 +00005085bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005086processInstruction(MCInst &Inst,
5087 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5088 switch (Inst.getOpcode()) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005089 // Handle NEON VST1 complex aliases.
5090 case ARM::VST1LNdWB_register_Asm_8:
5091 case ARM::VST1LNdWB_register_Asm_P8:
5092 case ARM::VST1LNdWB_register_Asm_I8:
5093 case ARM::VST1LNdWB_register_Asm_S8:
5094 case ARM::VST1LNdWB_register_Asm_U8:
5095 case ARM::VST1LNdWB_register_Asm_16:
5096 case ARM::VST1LNdWB_register_Asm_P16:
5097 case ARM::VST1LNdWB_register_Asm_I16:
5098 case ARM::VST1LNdWB_register_Asm_S16:
5099 case ARM::VST1LNdWB_register_Asm_U16:
5100 case ARM::VST1LNdWB_register_Asm_32:
5101 case ARM::VST1LNdWB_register_Asm_F:
5102 case ARM::VST1LNdWB_register_Asm_F32:
5103 case ARM::VST1LNdWB_register_Asm_I32:
5104 case ARM::VST1LNdWB_register_Asm_S32:
5105 case ARM::VST1LNdWB_register_Asm_U32: {
5106 MCInst TmpInst;
5107 // Shuffle the operands around so the lane index operand is in the
5108 // right place.
5109 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5110 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5111 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5112 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5113 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5114 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5115 TmpInst.addOperand(Inst.getOperand(1)); // lane
5116 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5117 TmpInst.addOperand(Inst.getOperand(6));
5118 Inst = TmpInst;
5119 return true;
5120 }
5121 case ARM::VST1LNdWB_fixed_Asm_8:
5122 case ARM::VST1LNdWB_fixed_Asm_P8:
5123 case ARM::VST1LNdWB_fixed_Asm_I8:
5124 case ARM::VST1LNdWB_fixed_Asm_S8:
5125 case ARM::VST1LNdWB_fixed_Asm_U8:
5126 case ARM::VST1LNdWB_fixed_Asm_16:
5127 case ARM::VST1LNdWB_fixed_Asm_P16:
5128 case ARM::VST1LNdWB_fixed_Asm_I16:
5129 case ARM::VST1LNdWB_fixed_Asm_S16:
5130 case ARM::VST1LNdWB_fixed_Asm_U16:
5131 case ARM::VST1LNdWB_fixed_Asm_32:
5132 case ARM::VST1LNdWB_fixed_Asm_F:
5133 case ARM::VST1LNdWB_fixed_Asm_F32:
5134 case ARM::VST1LNdWB_fixed_Asm_I32:
5135 case ARM::VST1LNdWB_fixed_Asm_S32:
5136 case ARM::VST1LNdWB_fixed_Asm_U32: {
5137 MCInst TmpInst;
5138 // Shuffle the operands around so the lane index operand is in the
5139 // right place.
5140 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5141 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5142 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5143 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5144 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5145 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5146 TmpInst.addOperand(Inst.getOperand(1)); // lane
5147 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5148 TmpInst.addOperand(Inst.getOperand(5));
5149 Inst = TmpInst;
5150 return true;
5151 }
5152 case ARM::VST1LNdAsm_8:
5153 case ARM::VST1LNdAsm_P8:
5154 case ARM::VST1LNdAsm_I8:
5155 case ARM::VST1LNdAsm_S8:
5156 case ARM::VST1LNdAsm_U8:
5157 case ARM::VST1LNdAsm_16:
5158 case ARM::VST1LNdAsm_P16:
5159 case ARM::VST1LNdAsm_I16:
5160 case ARM::VST1LNdAsm_S16:
5161 case ARM::VST1LNdAsm_U16:
5162 case ARM::VST1LNdAsm_32:
5163 case ARM::VST1LNdAsm_F:
5164 case ARM::VST1LNdAsm_F32:
5165 case ARM::VST1LNdAsm_I32:
5166 case ARM::VST1LNdAsm_S32:
5167 case ARM::VST1LNdAsm_U32: {
5168 MCInst TmpInst;
5169 // Shuffle the operands around so the lane index operand is in the
5170 // right place.
5171 TmpInst.setOpcode(getRealVSTLNOpcode(Inst.getOpcode()));
5172 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5173 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5174 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5175 TmpInst.addOperand(Inst.getOperand(1)); // lane
5176 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5177 TmpInst.addOperand(Inst.getOperand(5));
5178 Inst = TmpInst;
5179 return true;
5180 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00005181 // Handle NEON VLD1 complex aliases.
Jim Grosbach872eedb2011-12-02 22:01:52 +00005182 case ARM::VLD1LNdWB_register_Asm_8:
5183 case ARM::VLD1LNdWB_register_Asm_P8:
5184 case ARM::VLD1LNdWB_register_Asm_I8:
5185 case ARM::VLD1LNdWB_register_Asm_S8:
5186 case ARM::VLD1LNdWB_register_Asm_U8:
5187 case ARM::VLD1LNdWB_register_Asm_16:
5188 case ARM::VLD1LNdWB_register_Asm_P16:
5189 case ARM::VLD1LNdWB_register_Asm_I16:
5190 case ARM::VLD1LNdWB_register_Asm_S16:
5191 case ARM::VLD1LNdWB_register_Asm_U16:
5192 case ARM::VLD1LNdWB_register_Asm_32:
5193 case ARM::VLD1LNdWB_register_Asm_F:
5194 case ARM::VLD1LNdWB_register_Asm_F32:
5195 case ARM::VLD1LNdWB_register_Asm_I32:
5196 case ARM::VLD1LNdWB_register_Asm_S32:
5197 case ARM::VLD1LNdWB_register_Asm_U32: {
5198 MCInst TmpInst;
5199 // Shuffle the operands around so the lane index operand is in the
5200 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005201 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005202 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5203 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5204 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5205 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5206 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5207 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5208 TmpInst.addOperand(Inst.getOperand(1)); // lane
5209 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5210 TmpInst.addOperand(Inst.getOperand(6));
5211 Inst = TmpInst;
5212 return true;
5213 }
5214 case ARM::VLD1LNdWB_fixed_Asm_8:
5215 case ARM::VLD1LNdWB_fixed_Asm_P8:
5216 case ARM::VLD1LNdWB_fixed_Asm_I8:
5217 case ARM::VLD1LNdWB_fixed_Asm_S8:
5218 case ARM::VLD1LNdWB_fixed_Asm_U8:
5219 case ARM::VLD1LNdWB_fixed_Asm_16:
5220 case ARM::VLD1LNdWB_fixed_Asm_P16:
5221 case ARM::VLD1LNdWB_fixed_Asm_I16:
5222 case ARM::VLD1LNdWB_fixed_Asm_S16:
5223 case ARM::VLD1LNdWB_fixed_Asm_U16:
5224 case ARM::VLD1LNdWB_fixed_Asm_32:
5225 case ARM::VLD1LNdWB_fixed_Asm_F:
5226 case ARM::VLD1LNdWB_fixed_Asm_F32:
5227 case ARM::VLD1LNdWB_fixed_Asm_I32:
5228 case ARM::VLD1LNdWB_fixed_Asm_S32:
5229 case ARM::VLD1LNdWB_fixed_Asm_U32: {
5230 MCInst TmpInst;
5231 // Shuffle the operands around so the lane index operand is in the
5232 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005233 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005234 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5235 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5236 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5237 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5238 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5239 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5240 TmpInst.addOperand(Inst.getOperand(1)); // lane
5241 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5242 TmpInst.addOperand(Inst.getOperand(5));
5243 Inst = TmpInst;
5244 return true;
5245 }
Jim Grosbachdad2f8e2011-12-02 18:52:30 +00005246 case ARM::VLD1LNdAsm_8:
5247 case ARM::VLD1LNdAsm_P8:
5248 case ARM::VLD1LNdAsm_I8:
5249 case ARM::VLD1LNdAsm_S8:
5250 case ARM::VLD1LNdAsm_U8:
5251 case ARM::VLD1LNdAsm_16:
5252 case ARM::VLD1LNdAsm_P16:
5253 case ARM::VLD1LNdAsm_I16:
5254 case ARM::VLD1LNdAsm_S16:
5255 case ARM::VLD1LNdAsm_U16:
5256 case ARM::VLD1LNdAsm_32:
5257 case ARM::VLD1LNdAsm_F:
5258 case ARM::VLD1LNdAsm_F32:
5259 case ARM::VLD1LNdAsm_I32:
5260 case ARM::VLD1LNdAsm_S32:
5261 case ARM::VLD1LNdAsm_U32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005262 MCInst TmpInst;
5263 // Shuffle the operands around so the lane index operand is in the
5264 // right place.
Jim Grosbach84defb52011-12-02 22:34:51 +00005265 TmpInst.setOpcode(getRealVLDLNOpcode(Inst.getOpcode()));
Jim Grosbach7636bf62011-12-02 00:35:16 +00005266 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5267 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5268 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5269 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5270 TmpInst.addOperand(Inst.getOperand(1)); // lane
5271 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5272 TmpInst.addOperand(Inst.getOperand(5));
5273 Inst = TmpInst;
5274 return true;
5275 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00005276 // Handle the Thumb2 mode MOV complex aliases.
5277 case ARM::t2MOVsi:
5278 case ARM::t2MOVSsi: {
5279 // Which instruction to expand to depends on the CCOut operand and
5280 // whether we're in an IT block if the register operands are low
5281 // registers.
5282 bool isNarrow = false;
5283 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5284 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5285 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
5286 isNarrow = true;
5287 MCInst TmpInst;
5288 unsigned newOpc;
5289 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
5290 default: llvm_unreachable("unexpected opcode!");
5291 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
5292 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
5293 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
5294 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
5295 }
5296 unsigned Ammount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
5297 if (Ammount == 32) Ammount = 0;
5298 TmpInst.setOpcode(newOpc);
5299 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5300 if (isNarrow)
5301 TmpInst.addOperand(MCOperand::CreateReg(
5302 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5303 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5304 TmpInst.addOperand(MCOperand::CreateImm(Ammount));
5305 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5306 TmpInst.addOperand(Inst.getOperand(4));
5307 if (!isNarrow)
5308 TmpInst.addOperand(MCOperand::CreateReg(
5309 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
5310 Inst = TmpInst;
5311 return true;
5312 }
5313 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00005314 case ARM::ASRr:
5315 case ARM::LSRr:
5316 case ARM::LSLr:
5317 case ARM::RORr: {
5318 ARM_AM::ShiftOpc ShiftTy;
5319 switch(Inst.getOpcode()) {
5320 default: llvm_unreachable("unexpected opcode!");
5321 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
5322 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
5323 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
5324 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
5325 }
5326 // A shift by zero is a plain MOVr, not a MOVsi.
5327 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
5328 MCInst TmpInst;
5329 TmpInst.setOpcode(ARM::MOVsr);
5330 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5331 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5332 TmpInst.addOperand(Inst.getOperand(2)); // Rm
5333 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5334 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5335 TmpInst.addOperand(Inst.getOperand(4));
5336 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5337 Inst = TmpInst;
5338 return true;
5339 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00005340 case ARM::ASRi:
5341 case ARM::LSRi:
5342 case ARM::LSLi:
5343 case ARM::RORi: {
5344 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005345 switch(Inst.getOpcode()) {
5346 default: llvm_unreachable("unexpected opcode!");
5347 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
5348 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
5349 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
5350 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
5351 }
5352 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00005353 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00005354 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
5355 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005356 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00005357 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00005358 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5359 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00005360 if (Opc == ARM::MOVsi)
5361 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00005362 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
5363 TmpInst.addOperand(Inst.getOperand(4));
5364 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
5365 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005366 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00005367 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00005368 case ARM::RRXi: {
5369 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
5370 MCInst TmpInst;
5371 TmpInst.setOpcode(ARM::MOVsi);
5372 TmpInst.addOperand(Inst.getOperand(0)); // Rd
5373 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5374 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
5375 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5376 TmpInst.addOperand(Inst.getOperand(3));
5377 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
5378 Inst = TmpInst;
5379 return true;
5380 }
Jim Grosbach0352b462011-11-10 23:58:34 +00005381 case ARM::t2LDMIA_UPD: {
5382 // If this is a load of a single register, then we should use
5383 // a post-indexed LDR instruction instead, per the ARM ARM.
5384 if (Inst.getNumOperands() != 5)
5385 return false;
5386 MCInst TmpInst;
5387 TmpInst.setOpcode(ARM::t2LDR_POST);
5388 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5389 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5390 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5391 TmpInst.addOperand(MCOperand::CreateImm(4));
5392 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5393 TmpInst.addOperand(Inst.getOperand(3));
5394 Inst = TmpInst;
5395 return true;
5396 }
5397 case ARM::t2STMDB_UPD: {
5398 // If this is a store of a single register, then we should use
5399 // a pre-indexed STR instruction instead, per the ARM ARM.
5400 if (Inst.getNumOperands() != 5)
5401 return false;
5402 MCInst TmpInst;
5403 TmpInst.setOpcode(ARM::t2STR_PRE);
5404 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5405 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5406 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5407 TmpInst.addOperand(MCOperand::CreateImm(-4));
5408 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5409 TmpInst.addOperand(Inst.getOperand(3));
5410 Inst = TmpInst;
5411 return true;
5412 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005413 case ARM::LDMIA_UPD:
5414 // If this is a load of a single register via a 'pop', then we should use
5415 // a post-indexed LDR instruction instead, per the ARM ARM.
5416 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
5417 Inst.getNumOperands() == 5) {
5418 MCInst TmpInst;
5419 TmpInst.setOpcode(ARM::LDR_POST_IMM);
5420 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5421 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5422 TmpInst.addOperand(Inst.getOperand(1)); // Rn
5423 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
5424 TmpInst.addOperand(MCOperand::CreateImm(4));
5425 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5426 TmpInst.addOperand(Inst.getOperand(3));
5427 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005428 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005429 }
5430 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00005431 case ARM::STMDB_UPD:
5432 // If this is a store of a single register via a 'push', then we should use
5433 // a pre-indexed STR instruction instead, per the ARM ARM.
5434 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
5435 Inst.getNumOperands() == 5) {
5436 MCInst TmpInst;
5437 TmpInst.setOpcode(ARM::STR_PRE_IMM);
5438 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
5439 TmpInst.addOperand(Inst.getOperand(4)); // Rt
5440 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
5441 TmpInst.addOperand(MCOperand::CreateImm(-4));
5442 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
5443 TmpInst.addOperand(Inst.getOperand(3));
5444 Inst = TmpInst;
5445 }
5446 break;
Jim Grosbachda847862011-12-05 21:06:26 +00005447 case ARM::t2ADDri12:
5448 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
5449 // mnemonic was used (not "addw"), encoding T3 is preferred.
5450 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
5451 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5452 break;
5453 Inst.setOpcode(ARM::t2ADDri);
5454 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5455 break;
5456 case ARM::t2SUBri12:
5457 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
5458 // mnemonic was used (not "subw"), encoding T3 is preferred.
5459 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
5460 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
5461 break;
5462 Inst.setOpcode(ARM::t2SUBri);
5463 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
5464 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005465 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00005466 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5467 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5468 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5469 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005470 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005471 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005472 return true;
5473 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00005474 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00005475 case ARM::tSUBi8:
5476 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
5477 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
5478 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
5479 // to encoding T1 if <Rd> is omitted."
Jim Grosbach83ec8772011-11-10 23:42:14 +00005480 if (Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00005481 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005482 return true;
5483 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00005484 break;
Jim Grosbach927b9df2011-12-05 22:16:39 +00005485 case ARM::t2ADDrr: {
5486 // If the destination and first source operand are the same, and
5487 // there's no setting of the flags, use encoding T2 instead of T3.
5488 // Note that this is only for ADD, not SUB. This mirrors the system
5489 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
5490 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
5491 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00005492 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5493 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00005494 break;
5495 MCInst TmpInst;
5496 TmpInst.setOpcode(ARM::tADDhirr);
5497 TmpInst.addOperand(Inst.getOperand(0));
5498 TmpInst.addOperand(Inst.getOperand(0));
5499 TmpInst.addOperand(Inst.getOperand(2));
5500 TmpInst.addOperand(Inst.getOperand(3));
5501 TmpInst.addOperand(Inst.getOperand(4));
5502 Inst = TmpInst;
5503 return true;
5504 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005505 case ARM::tB:
5506 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005507 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005508 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005509 return true;
5510 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005511 break;
5512 case ARM::t2B:
5513 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005514 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005515 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005516 return true;
5517 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005518 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00005519 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00005520 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005521 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00005522 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005523 return true;
5524 }
Jim Grosbachc0755102011-08-31 21:17:31 +00005525 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00005526 case ARM::tBcc:
5527 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00005528 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00005529 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005530 return true;
5531 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00005532 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005533 case ARM::tLDMIA: {
5534 // If the register list contains any high registers, or if the writeback
5535 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
5536 // instead if we're in Thumb2. Otherwise, this should have generated
5537 // an error in validateInstruction().
5538 unsigned Rn = Inst.getOperand(0).getReg();
5539 bool hasWritebackToken =
5540 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5541 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5542 bool listContainsBase;
5543 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
5544 (!listContainsBase && !hasWritebackToken) ||
5545 (listContainsBase && hasWritebackToken)) {
5546 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5547 assert (isThumbTwo());
5548 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
5549 // If we're switching to the updating version, we need to insert
5550 // the writeback tied operand.
5551 if (hasWritebackToken)
5552 Inst.insert(Inst.begin(),
5553 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005554 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005555 }
5556 break;
5557 }
Jim Grosbach8213c962011-09-16 20:50:13 +00005558 case ARM::tSTMIA_UPD: {
5559 // If the register list contains any high registers, we need to use
5560 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5561 // should have generated an error in validateInstruction().
5562 unsigned Rn = Inst.getOperand(0).getReg();
5563 bool listContainsBase;
5564 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
5565 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
5566 assert (isThumbTwo());
5567 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00005568 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00005569 }
5570 break;
5571 }
Jim Grosbach54026372011-11-10 23:17:11 +00005572 case ARM::tPOP: {
5573 bool listContainsBase;
5574 // If the register list contains any high registers, we need to use
5575 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
5576 // should have generated an error in validateInstruction().
5577 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005578 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005579 assert (isThumbTwo());
5580 Inst.setOpcode(ARM::t2LDMIA_UPD);
5581 // Add the base register and writeback operands.
5582 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5583 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005584 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005585 }
5586 case ARM::tPUSH: {
5587 bool listContainsBase;
5588 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00005589 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00005590 assert (isThumbTwo());
5591 Inst.setOpcode(ARM::t2STMDB_UPD);
5592 // Add the base register and writeback operands.
5593 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
5594 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00005595 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00005596 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005597 case ARM::t2MOVi: {
5598 // If we can use the 16-bit encoding and the user didn't explicitly
5599 // request the 32-bit variant, transform it here.
5600 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5601 Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00005602 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
5603 Inst.getOperand(4).getReg() == ARM::CPSR) ||
5604 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005605 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5606 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5607 // The operands aren't in the same order for tMOVi8...
5608 MCInst TmpInst;
5609 TmpInst.setOpcode(ARM::tMOVi8);
5610 TmpInst.addOperand(Inst.getOperand(0));
5611 TmpInst.addOperand(Inst.getOperand(4));
5612 TmpInst.addOperand(Inst.getOperand(1));
5613 TmpInst.addOperand(Inst.getOperand(2));
5614 TmpInst.addOperand(Inst.getOperand(3));
5615 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005616 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005617 }
5618 break;
5619 }
5620 case ARM::t2MOVr: {
5621 // If we can use the 16-bit encoding and the user didn't explicitly
5622 // request the 32-bit variant, transform it here.
5623 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5624 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5625 Inst.getOperand(2).getImm() == ARMCC::AL &&
5626 Inst.getOperand(4).getReg() == ARM::CPSR &&
5627 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5628 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
5629 // The operands aren't the same for tMOV[S]r... (no cc_out)
5630 MCInst TmpInst;
5631 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
5632 TmpInst.addOperand(Inst.getOperand(0));
5633 TmpInst.addOperand(Inst.getOperand(1));
5634 TmpInst.addOperand(Inst.getOperand(2));
5635 TmpInst.addOperand(Inst.getOperand(3));
5636 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005637 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00005638 }
5639 break;
5640 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005641 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00005642 case ARM::t2SXTB:
5643 case ARM::t2UXTH:
5644 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00005645 // If we can use the 16-bit encoding and the user didn't explicitly
5646 // request the 32-bit variant, transform it here.
5647 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
5648 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5649 Inst.getOperand(2).getImm() == 0 &&
5650 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
5651 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00005652 unsigned NewOpc;
5653 switch (Inst.getOpcode()) {
5654 default: llvm_unreachable("Illegal opcode!");
5655 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
5656 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
5657 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
5658 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
5659 }
Jim Grosbach326efe52011-09-19 20:29:33 +00005660 // The operands aren't the same for thumb1 (no rotate operand).
5661 MCInst TmpInst;
5662 TmpInst.setOpcode(NewOpc);
5663 TmpInst.addOperand(Inst.getOperand(0));
5664 TmpInst.addOperand(Inst.getOperand(1));
5665 TmpInst.addOperand(Inst.getOperand(3));
5666 TmpInst.addOperand(Inst.getOperand(4));
5667 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00005668 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00005669 }
5670 break;
5671 }
Jim Grosbach89df9962011-08-26 21:43:41 +00005672 case ARM::t2IT: {
5673 // The mask bits for all but the first condition are represented as
5674 // the low bit of the condition code value implies 't'. We currently
5675 // always have 1 implies 't', so XOR toggle the bits if the low bit
5676 // of the condition code is zero. The encoding also expects the low
5677 // bit of the condition to be encoded as bit 4 of the mask operand,
5678 // so mask that in if needed
5679 MCOperand &MO = Inst.getOperand(1);
5680 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005681 unsigned OrigMask = Mask;
5682 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00005683 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00005684 assert(Mask && TZ <= 3 && "illegal IT mask value!");
5685 for (unsigned i = 3; i != TZ; --i)
5686 Mask ^= 1 << i;
5687 } else
5688 Mask |= 0x10;
5689 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005690
5691 // Set up the IT block state according to the IT instruction we just
5692 // matched.
5693 assert(!inITBlock() && "nested IT blocks?!");
5694 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
5695 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
5696 ITState.CurPosition = 0;
5697 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00005698 break;
5699 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00005700 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00005701 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005702}
5703
Jim Grosbach47a0d522011-08-16 20:45:50 +00005704unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
5705 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
5706 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00005707 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005708 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00005709 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
5710 assert(MCID.hasOptionalDef() &&
5711 "optionally flag setting instruction missing optional def operand");
5712 assert(MCID.NumOperands == Inst.getNumOperands() &&
5713 "operand count mismatch!");
5714 // Find the optional-def operand (cc_out).
5715 unsigned OpNo;
5716 for (OpNo = 0;
5717 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
5718 ++OpNo)
5719 ;
5720 // If we're parsing Thumb1, reject it completely.
5721 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
5722 return Match_MnemonicFail;
5723 // If we're parsing Thumb2, which form is legal depends on whether we're
5724 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005725 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
5726 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00005727 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005728 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
5729 inITBlock())
5730 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005731 }
Jim Grosbach194bd892011-08-16 22:20:01 +00005732 // Some high-register supporting Thumb1 encodings only allow both registers
5733 // to be from r0-r7 when in Thumb2.
5734 else if (Opc == ARM::tADDhirr && isThumbOne() &&
5735 isARMLowRegister(Inst.getOperand(1).getReg()) &&
5736 isARMLowRegister(Inst.getOperand(2).getReg()))
5737 return Match_RequiresThumb2;
5738 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00005739 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00005740 isARMLowRegister(Inst.getOperand(0).getReg()) &&
5741 isARMLowRegister(Inst.getOperand(1).getReg()))
5742 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00005743 return Match_Success;
5744}
5745
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005746bool ARMAsmParser::
5747MatchAndEmitInstruction(SMLoc IDLoc,
5748 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5749 MCStreamer &Out) {
5750 MCInst Inst;
5751 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005752 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005753 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00005754 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00005755 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005756 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00005757 // Context sensitive operand constraints aren't handled by the matcher,
5758 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00005759 if (validateInstruction(Inst, Operands)) {
5760 // Still progress the IT block, otherwise one wrong condition causes
5761 // nasty cascading errors.
5762 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00005763 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00005764 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005765
Jim Grosbachf8fce712011-08-11 17:35:48 +00005766 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00005767 // encoding is selected. Loop on it while changes happen so the
5768 // individual transformations can chain off each other. E.g.,
5769 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
5770 while (processInstruction(Inst, Operands))
5771 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00005772
Jim Grosbacha1109882011-09-02 23:22:08 +00005773 // Only move forward at the very end so that everything in validate
5774 // and process gets a consistent answer about whether we're in an IT
5775 // block.
5776 forwardITPosition();
5777
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005778 Out.EmitInstruction(Inst);
5779 return false;
Chris Lattnere73d4f82010-10-28 21:41:58 +00005780 case Match_MissingFeature:
5781 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
5782 return true;
5783 case Match_InvalidOperand: {
5784 SMLoc ErrorLoc = IDLoc;
5785 if (ErrorInfo != ~0U) {
5786 if (ErrorInfo >= Operands.size())
5787 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00005788
Chris Lattnere73d4f82010-10-28 21:41:58 +00005789 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
5790 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
5791 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005792
Chris Lattnere73d4f82010-10-28 21:41:58 +00005793 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005794 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00005795 case Match_MnemonicFail:
Jim Grosbach47a0d522011-08-16 20:45:50 +00005796 return Error(IDLoc, "invalid instruction");
Daniel Dunbarb4129152011-02-04 17:12:23 +00005797 case Match_ConversionFail:
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00005798 // The converter function will have already emited a diagnostic.
5799 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005800 case Match_RequiresNotITBlock:
5801 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00005802 case Match_RequiresITBlock:
5803 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00005804 case Match_RequiresV6:
5805 return Error(IDLoc, "instruction variant requires ARMv6 or later");
5806 case Match_RequiresThumb2:
5807 return Error(IDLoc, "instruction variant requires Thumb2");
Chris Lattnere73d4f82010-10-28 21:41:58 +00005808 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005809
Eric Christopherc223e2b2010-10-29 09:26:59 +00005810 llvm_unreachable("Implement any new match types added!");
Bill Wendling146018f2010-11-06 21:42:12 +00005811 return true;
Chris Lattnerfa42fad2010-10-28 21:28:01 +00005812}
5813
Jim Grosbach1355cf12011-07-26 17:10:22 +00005814/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005815bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
5816 StringRef IDVal = DirectiveID.getIdentifier();
5817 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005818 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005819 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005820 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00005821 else if (IDVal == ".arm")
5822 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005823 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005824 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005825 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005826 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00005827 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00005828 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00005829 else if (IDVal == ".unreq")
5830 return parseDirectiveUnreq(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005831 return true;
5832}
5833
Jim Grosbach1355cf12011-07-26 17:10:22 +00005834/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005835/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00005836bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005837 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5838 for (;;) {
5839 const MCExpr *Value;
5840 if (getParser().ParseExpression(Value))
5841 return true;
5842
Chris Lattneraaec2052010-01-19 19:46:13 +00005843 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005844
5845 if (getLexer().is(AsmToken::EndOfStatement))
5846 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00005847
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005848 // FIXME: Improve diagnostic.
5849 if (getLexer().isNot(AsmToken::Comma))
5850 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005851 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005852 }
5853 }
5854
Sean Callananb9a25b72010-01-19 20:27:46 +00005855 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005856 return false;
5857}
5858
Jim Grosbach1355cf12011-07-26 17:10:22 +00005859/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00005860/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00005861bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00005862 if (getLexer().isNot(AsmToken::EndOfStatement))
5863 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005864 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005865
Jim Grosbach9a70df92011-12-07 18:04:19 +00005866 if (!isThumb())
5867 SwitchMode();
5868 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
5869 return false;
5870}
5871
5872/// parseDirectiveARM
5873/// ::= .arm
5874bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
5875 if (getLexer().isNot(AsmToken::EndOfStatement))
5876 return Error(L, "unexpected token in directive");
5877 Parser.Lex();
5878
5879 if (isThumb())
5880 SwitchMode();
5881 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00005882 return false;
5883}
5884
Jim Grosbach1355cf12011-07-26 17:10:22 +00005885/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00005886/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00005887bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00005888 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
5889 bool isMachO = MAI.hasSubsectionsViaSymbols();
5890 StringRef Name;
5891
5892 // Darwin asm has function name after .thumb_func direction
5893 // ELF doesn't
5894 if (isMachO) {
5895 const AsmToken &Tok = Parser.getTok();
5896 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
5897 return Error(L, "unexpected token in .thumb_func directive");
Jim Grosbachd475f862011-11-10 20:48:53 +00005898 Name = Tok.getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005899 Parser.Lex(); // Consume the identifier token.
5900 }
5901
Jim Grosbachd475f862011-11-10 20:48:53 +00005902 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00005903 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005904 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005905
Rafael Espindola64695402011-05-16 16:17:21 +00005906 // FIXME: assuming function name will be the line following .thumb_func
5907 if (!isMachO) {
Jim Grosbachd475f862011-11-10 20:48:53 +00005908 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00005909 }
5910
Jim Grosbach642fc9c2010-11-05 22:33:53 +00005911 // Mark symbol as a thumb symbol.
5912 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
5913 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00005914 return false;
5915}
5916
Jim Grosbach1355cf12011-07-26 17:10:22 +00005917/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00005918/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00005919bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005920 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005921 if (Tok.isNot(AsmToken::Identifier))
5922 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00005923 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00005924 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00005925 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005926 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00005927 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00005928 else
5929 return Error(L, "unrecognized syntax mode in .syntax directive");
5930
5931 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005932 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005933 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005934
5935 // TODO tell the MC streamer the mode
5936 // getParser().getStreamer().Emit???();
5937 return false;
5938}
5939
Jim Grosbach1355cf12011-07-26 17:10:22 +00005940/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00005941/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00005942bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00005943 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00005944 if (Tok.isNot(AsmToken::Integer))
5945 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00005946 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00005947 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00005948 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00005949 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00005950 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005951 else
5952 return Error(L, "invalid operand to .code directive");
5953
5954 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00005955 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00005956 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00005957
Evan Cheng32869202011-07-08 22:36:29 +00005958 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00005959 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005960 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005961 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00005962 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00005963 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00005964 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00005965 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00005966 }
Jim Grosbach2a301702010-11-05 22:40:53 +00005967
Kevin Enderby515d5092009-10-15 20:48:48 +00005968 return false;
5969}
5970
Jim Grosbacha39cda72011-12-14 02:16:11 +00005971/// parseDirectiveReq
5972/// ::= name .req registername
5973bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
5974 Parser.Lex(); // Eat the '.req' token.
5975 unsigned Reg;
5976 SMLoc SRegLoc, ERegLoc;
5977 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
5978 Parser.EatToEndOfStatement();
5979 return Error(SRegLoc, "register name expected");
5980 }
5981
5982 // Shouldn't be anything else.
5983 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5984 Parser.EatToEndOfStatement();
5985 return Error(Parser.getTok().getLoc(),
5986 "unexpected input in .req directive.");
5987 }
5988
5989 Parser.Lex(); // Consume the EndOfStatement
5990
5991 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
5992 return Error(SRegLoc, "redefinition of '" + Name +
5993 "' does not match original.");
5994
5995 return false;
5996}
5997
5998/// parseDirectiveUneq
5999/// ::= .unreq registername
6000bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
6001 if (Parser.getTok().isNot(AsmToken::Identifier)) {
6002 Parser.EatToEndOfStatement();
6003 return Error(L, "unexpected input in .unreq directive.");
6004 }
6005 RegisterReqs.erase(Parser.getTok().getIdentifier());
6006 Parser.Lex(); // Eat the identifier.
6007 return false;
6008}
6009
Sean Callanan90b70972010-04-07 20:29:34 +00006010extern "C" void LLVMInitializeARMAsmLexer();
6011
Kevin Enderby9c41fa82009-10-30 22:55:57 +00006012/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006013extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00006014 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
6015 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00006016 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00006017}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006018
Chris Lattner0692ee62010-09-06 19:11:01 +00006019#define GET_REGISTER_MATCHER
6020#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00006021#include "ARMGenAsmMatcher.inc"